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.TryParse | falseで返る(処理継続できる) | ユーザー入力・貼り付けがある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 05 | 2, 4, 1, 3, 5 | 2 | 3 | 15 |
| 2 4 6 | 2, 4, 6 | 3 | 0 | 12 |
| 1,3,5 | 1, 3, 5(カンマ区切り対応時) | 0 | 3 | 9 |
| 10 20 a 30 | 10, 20, 30(aは不正として除外) | 3 | 0 | 60 |
| -1 -2 -3 | -1, -2, -3 | 1 | 2 | -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#)の場面で、ほぼそのまま流用できます。

コメント