C# TextBoxの空白区切り数値を分割して偶数・奇数をカウントし合計を出す方法(Split/LINQ/TryParse)

WindowsフォームのTextBoxに「02 04 01 03 05」のような空白区切りの数値を入力し、ボタンを押したら偶数・奇数の個数と合計を表示したい――この要件は、文字列を「分割」してから数値化し、集計するのが一番確実です。textBox1.Textをそのままintに変換すると「桁」を相手にする処理になりやすいので、本記事ではSplitとLINQ、さらにTryParseで安全に作る方法までまとめます。

目次

なぜ「textBox1.Text を int に変換」だと期待どおりにならないのか

TextBoxに入力されるのはあくまで文字列です。例えば textBox1 に「02 04 01 03 05」と入力されている場合、これは「複数の数値」ではなく、空白を含む1本の文字列です。

ここでよくある失敗が、次のように「文字列全体」をintにしようとするケースです。

int value = int.Parse(textBox1.Text);

この書き方だと、入力が「02 04 01 03 05」の時点で空白が含まれているため、基本的に例外(FormatException)になります。仮に空白がなかったとしても、たとえば「0204010305」を1つの数として扱うことになり、やりたいのは「02」「04」「01」…をそれぞれ集計することなので、目的がズレます。

やりたいことを整理すると、必要なのは次の流れです。

  • 文字列を「区切り」で分割して、トークン(例:「02」「04」…)の配列を作る
  • 各トークンを数値に変換する(必要ならエラー処理もする)
  • 偶数・奇数の個数、合計を集計する

正攻法:Splitで分割 → 数値化 → 集計

まずは基本形です。空白区切りを想定するなら、Splitで分割し、空要素を除外してから変換します。

処理の全体像

段階やること具体例
分割入力文字列を区切りでSplitする「02 04 01」→「02」「04」「01」
数値化各要素をintへ変換する「02」→ 2
集計偶数・奇数の個数、合計を算出する偶数2件/奇数1件/合計7

最小構成の実装(空白区切り・例外前提)

入力が必ず正しい(数値のみ、区切りは半角スペースのみ)と分かっている社内ツールなどでは、まずはこの形が分かりやすいです。

private void button1_Click(object sender, EventArgs e)
{
    // 1) Splitで分割(空要素を除外)
    var tokens = textBox1.Text
        .Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);

    // 2) 数値化(不正なら例外)
    int[] numbers = tokens.Select(int.Parse).ToArray();

    // 3) 集計
    int evenCount = numbers.Count(n => n % 2 == 0);
    int oddCount  = numbers.Count(n => n % 2 != 0);
    int sum       = numbers.Sum();

    // 表示(ラベルやテキストボックスなど、好みのコントロールへ)
    labelEven.Text = evenCount.ToString();
    labelOdd.Text  = oddCount.ToString();
    labelSum.Text  = sum.ToString();
}

この時点で、入力が「02 04 01 03 05」なら、偶数は2(2と4)、奇数は3(1,3,5)、合計は15になります。「02」のような先頭ゼロは int.Parse で問題なく扱えます(2として解釈されます)。

LINQで最短に書くとこうなる

上のコードは分かりやすさを優先しましたが、LINQを使うと「分割→数値化」も含めてかなり短く書けます。読みやすい範囲でまとめたい場合は次の形が定番です。

private void button1_Click(object sender, EventArgs e)
{
    int[] numbers = textBox1.Text
        .Split(new[] { ' ' }, StringSplitOptions.RemoveEmptyEntries)
        .Select(int.Parse)
        .ToArray();

    labelEven.Text = numbers.Count(n => n % 2 == 0).ToString();
    labelOdd.Text  = numbers.Count(n => n % 2 != 0).ToString();
    labelSum.Text  = numbers.Sum().ToString();
}

ただしこの形は、入力が汚い(空白が連続する、カンマが混ざる、文字が混ざる、数値が大きすぎる)と例外で落ちます。一般公開するツールや、運用が長い業務アプリでは次の「TryParse版」が実用的です。

実運用で強い:TryParseで不正入力を弾きながら集計する

ユーザー入力は、想定よりも簡単に崩れます。例えば次のようなケースはよく起きます。

  • スペースが連続する(「02  04」)
  • 改行やタブを混ぜて貼り付ける(Excelから貼り付け等)
  • カンマ区切りで入力してしまう(「2,4,1」)
  • 数値以外が混ざる(「2 4 a 1」)
  • 桁が大きすぎてintに入らない(「999999999999」)

この対策として、Splitは空要素除外、変換はint.TryParseで「成功したものだけ」採用し、失敗したトークンはまとめて通知する、という作りが安全です。

区切りを「空白+改行+タブ+カンマ+全角スペース」に対応する例

スペース以外も区切りになり得るなら、Splitの区切り文字に複数指定します。全角スペース(「 」)も入れておくと、コピペ時の事故が減ります。

private void button1_Click(object sender, EventArgs e)
{
    // 実運用でよく混ざる区切りをまとめて許可
    char[] separators = new[] { ' ', '\t', '\r', '\n', ',', ' ' };

    string[] tokens = textBox1.Text
        .Split(separators, StringSplitOptions.RemoveEmptyEntries);

    int evenCount = 0;
    int oddCount = 0;
    long sum = 0; // 合計は溢れにくいようlongにしておくと安心

    var invalidTokens = new List<string>();

    foreach (string token in tokens)
    {
        if (!int.TryParse(token, out int n))
        {
            invalidTokens.Add(token);
            continue;
        }

        if (n % 2 == 0) evenCount++;
        else oddCount++;

        sum += n;
    }

    labelEven.Text = evenCount.ToString();
    labelOdd.Text  = oddCount.ToString();
    labelSum.Text  = sum.ToString();

    // 不正入力があった場合の通知例(運用方針に合わせて調整)
    if (invalidTokens.Count > 0)
    {
        MessageBox.Show(
            "数値として解釈できない値が含まれています:\n" + string.Join(", ", invalidTokens),
            "入力エラー",
            MessageBoxButtons.OK,
            MessageBoxIcon.Warning
        );
    }
}

ここでは合計をlongにしています。理由は単純で、数が多い入力(例:1000個以上)や大きい数が混ざった時に、intの範囲を超える可能性があるからです。個々の要素はintで良いが合計だけはlongにしたい、という場面は意外と多いので、最初からこの形にしておくと後で助かります。

ParseとTryParseの違い(選び方の目安)

方法不正値が来たら向いている場面注意点
int.Parse例外で止まる入力が必ず正しい前提(社内限定・自動入力)運用中に落ちると困るアプリでは危険
int.TryParsefalseで返る(処理継続できる)ユーザー入力・貼り付けがあるUI失敗時の扱い(無視/警告/入力拒否)を決める必要

「業務アプリで落ちないこと」が優先ならTryParseが基本です。逆に「入力が完全に制御されていて、落ちたらすぐ気付ける」ならParseでも構いません。

LINQでもTryParse対応はできる(ただし読みやすさ優先で)

LINQだけでTryParseをきれいにやろうとすると、少し工夫が必要です。実務では「foreachで1回回して終わり」が一番読みやすいことも多いですが、どうしてもLINQでまとめたい場合は次のように書けます。

private void button1_Click(object sender, EventArgs e)
{
    char[] separators = new[] { ' ', '\t', '\r', '\n', ',', ' ' };

    var tokens = textBox1.Text
        .Split(separators, StringSplitOptions.RemoveEmptyEntries);

    // TryParse成功したものだけ採用
    var numbers = tokens
        .Select(t => new { Token = t, Ok = int.TryParse(t, out int n), Value = n })
        .ToList();

    var valid = numbers.Where(x => x.Ok).Select(x => x.Value).ToArray();
    var invalid = numbers.Where(x => !x.Ok).Select(x => x.Token).ToList();

    int evenCount = valid.Count(n => n % 2 == 0);
    int oddCount  = valid.Count(n => n % 2 != 0);
    long sum      = valid.Select(n => (long)n).Sum();

    labelEven.Text = evenCount.ToString();
    labelOdd.Text  = oddCount.ToString();
    labelSum.Text  = sum.ToString();

    if (invalid.Count > 0)
    {
        MessageBox.Show(
            "数値として解釈できない値が含まれています:\n" + string.Join(", ", invalid),
            "入力エラー",
            MessageBoxButtons.OK,
            MessageBoxIcon.Warning
        );
    }
}

この書き方は「成立した値だけ集計」「失敗したトークンも保持」を両立できますが、匿名型が混ざるため慣れていないチームだと読みづらくなることがあります。チーム開発では、読み手に合わせて foreach 版を選ぶほうが無難です。

入力の例と、期待される出力の確認

動作確認用に、代表的な入力例と出力の考え方を表にしておきます。テストケースとして使うと安心です。

入力例解釈される数値偶数奇数合計
02 04 01 03 052, 4, 1, 3, 52315
2  4  62, 4, 63012
1,3,51, 3, 5(カンマ区切り対応時)039
10 20 a 3010, 20, 30(aは不正として除外)3060
-1 -2 -3-1, -2, -312-6

なお、奇数判定は「n % 2 != 0」で問題ありません。負の数でも、偶数は「割り切れる」こと自体で判定できるため「n % 2 == 0」はそのまま使えます。

よくあるつまずきポイントと、先回りの対策

Splitの「空要素除外」を忘れて、空文字をParseして落ちる

「2  4」のようにスペースが連続すると、Split結果に空文字が混ざります。これをそのままParseすると例外になります。対策は、StringSplitOptions.RemoveEmptyEntries を付けるだけです。

textBox1.Text.Split(separators, StringSplitOptions.RemoveEmptyEntries)

スペース以外の区切りが混ざる(貼り付けが原因のことが多い)

Excelやメールから貼り付けると、タブ区切り・改行区切りになることが多いです。現場の運用を想定するなら、最初から「空白/タブ/改行/カンマ/全角スペース」を受け付けてしまうほうがサポートコストが下がります。

合計だけ溢れる(個々はintでも合計はintを超える)

大量の入力や、比較的大きい値が混ざると合計がintの範囲(約±21億)を超えることがあります。合計だけlongにするのは手軽で効果が大きい対策です。将来「もっと大きい数も扱いたい」になったとき、修正が最小で済みます。

エラー時に「全部無視」か「入力を止める」かを決めておく

TryParseを使うと「不正値をスキップして続行」できますが、運用方針はアプリによって違います。

  • 集計を優先:不正値は無視し、何が無視されたかだけ警告(今回の例)
  • 正確性を優先:不正値が1つでもあったら集計せず、入力全体をやり直してもらう
  • ユーザー体験を優先:不正なトークンの位置をハイライトして、その場で修正できるUIにする

「どれが正しい」ではなく、利用者と用途に合わせて決めるのが重要です。

そのまま使える:おすすめの「関数化」パターン

ボタンのクリックイベントに全部書くと、あとからUIが増えたときに修正しづらくなります。入力解析(パース)を関数に分離しておくと、テストもしやすく、別画面でも再利用できます。

private static (int[] ValidNumbers, string[] InvalidTokens) ParseNumbers(string input)
{
    char[] separators = new[] { ' ', '\t', '\r', '\n', ',', ' ' };

    var tokens = input.Split(separators, StringSplitOptions.RemoveEmptyEntries);

    var valid = new List<int>(tokens.Length);
    var invalid = new List<string>();

    foreach (var token in tokens)
    {
        if (int.TryParse(token, out int n))
        {
            valid.Add(n);
        }
        else
        {
            invalid.Add(token);
        }
    }

    return (valid.ToArray(), invalid.ToArray());
}

private void button1_Click(object sender, EventArgs e)
{
    var (numbers, invalid) = ParseNumbers(textBox1.Text);

    int evenCount = 0;
    int oddCount = 0;
    long sum = 0;

    foreach (var n in numbers)
    {
        if (n % 2 == 0) evenCount++;
        else oddCount++;

        sum += n;
    }

    labelEven.Text = evenCount.ToString();
    labelOdd.Text  = oddCount.ToString();
    labelSum.Text  = sum.ToString();

    if (invalid.Length > 0)
    {
        MessageBox.Show(
            "数値として解釈できない値が含まれています:\n" + string.Join(", ", invalid),
            "入力エラー",
            MessageBoxButtons.OK,
            MessageBoxIcon.Warning
        );
    }
}

この形にしておくと、将来「範囲チェック(例:0〜100のみ許可)」「重複排除」「ソートして表示」などの仕様が追加されても、ParseNumbers側にロジックを寄せていけます。

さらに一歩:入力制限(任意)で「そもそも汚い入力を作らせない」

TryParseで守るのは大事ですが、UI側で入力を誘導できるなら、ユーザーのストレスも減らせます。例えば次のような工夫が有効です。

  • TextBoxの横に「例:02 04 01」のプレースホルダー的な説明を置く
  • 貼り付け前提なら「区切りはスペース/改行/カンマ可」と明記する
  • 不正トークンがあった場合、メッセージに加えて別のTextBoxやListBoxに一覧表示する

入力解析が安定していると、次に「表示の分かりやすさ」へ改善の手を伸ばしやすくなります。まずはSplit+TryParseで、落ちない土台を作るのが近道です。

まとめ:空白区切りの複数数値は「Splitして配列化」してから集計する

  • textBox1.Textは文字列なので、複数数値として扱うにはSplitで分割が必須
  • 最短実装ならLINQ(Count/Sum)で一気に書ける
  • 運用を考えるならTryParseで不正入力を弾き、区切りもスペース以外を許容すると強い
  • 合計はlongにしておくと、将来の「入力が増えた」問題にも耐えやすい

この方針で作っておけば、空白区切りの数値入力を扱うWindowsフォーム(C#)の場面で、ほぼそのまま流用できます。

この記事を書いた人

実務の現場で詰まりがちなポイントを地図にするITブログ「IT trip」を運営。Windows/Office(Teams・Excel)からSQL、サーバ運用、ガジェットまで、再現性のある手順と“なぜそうなるか”を丁寧に解説します。読んだらすぐ試せること、そして迷った人の次の一歩が見えることを大切にしています。

コメント

コメントする

目次