C#(シーシャープ)で繰り返し処理を行う際に最もよく使われるのが「for文」です。
繰り返しの回数が決まっている場合に特に便利で、簡潔に記述できるため、初心者が最初に学ぶべき構文のひとつです。
この記事では、C#におけるfor文の基本構文から、実践的な使用例、よくあるミスとその対策までをわかりやすく解説します。
こんな方におすすめです
- C#プログラミングを始めたばかりの方
- 繰り返し処理を効率的に書きたい方
- 配列やリストの処理を学びたい方
- for文でエラーが出て困っている方
この記事でできるようになること
- for文の基本構文を完全に理解
- 様々なパターンの繰り返し処理を書ける
- 配列やリストを効率的に処理できる
- よくあるエラーを回避できる
- 実践的なプログラムを作成できる
それでは、まずfor文の基本構文から学んでいきましょう。
for文の基本構文を理解しよう

for文の構造
基本の書き方:
for (初期化; 条件; 更新)
{
// 繰り返す処理
}
各部分の詳細説明
初期化:
- ループの最初に1回だけ実行される
- 通常はカウンタ変数を定義・初期化
- 例:
int i = 0
条件:
- 毎回のループ開始前にチェックされる
- trueの間はループを継続
- falseになったらループ終了
- 例:
i < 5
更新:
- 各ループの最後に実行される
- 通常はカウンタ変数を変更
- 例:
i++
(iを1増加)
最初の例:基本的な数値の表示
0から4までの数字を表示
for (int i = 0; i < 5; i++)
{
Console.WriteLine(i);
}
実行結果:
0
1
2
3
4
実行の流れを詳しく見てみよう
Step 1:初期化 int i = 0
- 変数iが作られ、0が代入される
Step 2:条件チェック i < 5
- i = 0, 0 < 5 は true なのでループ実行
Step 3:処理実行 Console.WriteLine(i)
- “0”が表示される
Step 4:更新 i++
- iが1になる
Step 5:条件チェック i < 5
- i = 1, 1 < 5 は true なのでループ継続
この流れを繰り返し:
- i = 2, 3, 4の時も同様に実行
- i = 5になった時、5 < 5 は false なのでループ終了
より実用的な例
1から10までの合計を計算
int sum = 0;
for (int i = 1; i <= 10; i++)
{
sum += i; // sum = sum + i と同じ
}
Console.WriteLine($"1から10までの合計: {sum}");
実行結果:
1から10までの合計: 55
九九の表を作成
for (int i = 1; i <= 9; i++)
{
for (int j = 1; j <= 9; j++)
{
Console.Write($"{i * j:D2} "); // 2桁で表示
}
Console.WriteLine(); // 改行
}
実行結果(一部):
01 02 03 04 05 06 07 08 09
02 04 06 08 10 12 14 16 18
03 06 09 12 15 18 21 24 27
...
基本形を覚えたら、次は少し応用的な使い方に進んでみましょう。
応用例と実践的な使い方

配列の操作
配列のすべての要素を表示
string[] fruits = {"Apple", "Banana", "Cherry", "Date", "Elderberry"};
for (int i = 0; i < fruits.Length; i++)
{
Console.WriteLine($"{i + 1}. {fruits[i]}");
}
実行結果:
1. Apple
2. Banana
3. Cherry
4. Date
5. Elderberry
重要なポイント:
- 配列のサイズは
fruits.Length
で取得 - インデックスは0から始まるため、表示番号は
i + 1
- 範囲外アクセスを防ぐため
i < fruits.Length
を使用
配列の要素を検索
string[] names = {"太郎", "花子", "次郎", "美子", "一郎"};
string searchName = "花子";
int foundIndex = -1;
for (int i = 0; i < names.Length; i++)
{
if (names[i] == searchName)
{
foundIndex = i;
break; // 見つかったらループを抜ける
}
}
if (foundIndex != -1)
{
Console.WriteLine($"{searchName}は{foundIndex + 1}番目にあります");
}
else
{
Console.WriteLine($"{searchName}は見つかりませんでした");
}
配列の最大値と最小値を見つける
int[] numbers = {45, 23, 89, 12, 67, 34, 91, 56};
int max = numbers[0];
int min = numbers[0];
for (int i = 1; i < numbers.Length; i++)
{
if (numbers[i] > max)
{
max = numbers[i];
}
if (numbers[i] < min)
{
min = numbers[i];
}
}
Console.WriteLine($"最大値: {max}");
Console.WriteLine($"最小値: {min}");
様々なループパターン
逆順にループする
// 10から0まで2ずつ減らしながら表示
for (int i = 10; i >= 0; i -= 2)
{
Console.WriteLine(i);
}
実行結果:
10
8
6
4
2
0
特定の条件をスキップ
// 1から20まで、3の倍数以外を表示
for (int i = 1; i <= 20; i++)
{
if (i % 3 == 0)
{
continue; // 3の倍数はスキップ
}
Console.Write($"{i} ");
}
実行結果:
1 2 4 5 7 8 10 11 13 14 16 17 19 20
ネストしたfor文(二重ループ)
// 星印でピラミッドを作成
for (int i = 1; i <= 5; i++)
{
// 空白を印刷
for (int j = 5; j > i; j--)
{
Console.Write(" ");
}
// 星を印刷
for (int k = 1; k <= i; k++)
{
Console.Write("* ");
}
Console.WriteLine(); // 改行
}
実行結果:
*
* *
* * *
* * * *
* * * * *
Listの操作
Listの要素を処理
using System;
using System.Collections.Generic;
List<int> scores = new List<int> {85, 92, 78, 95, 88, 76, 90};
// 80点以上の点数のみ表示
Console.WriteLine("80点以上の成績:");
for (int i = 0; i < scores.Count; i++)
{
if (scores[i] >= 80)
{
Console.WriteLine($"{i + 1}番目: {scores[i]}点");
}
}
// 平均点を計算
int total = 0;
for (int i = 0; i < scores.Count; i++)
{
total += scores[i];
}
double average = (double)total / scores.Count;
Console.WriteLine($"平均点: {average:F1}点");
文字列の操作
文字列の各文字を処理
string text = "Hello, World!";
int vowelCount = 0;
string vowels = "aeiouAEIOU";
for (int i = 0; i < text.Length; i++)
{
char currentChar = text[i];
// 母音かどうかチェック
for (int j = 0; j < vowels.Length; j++)
{
if (currentChar == vowels[j])
{
vowelCount++;
break;
}
}
}
Console.WriteLine($"文字列「{text}」には母音が{vowelCount}個あります");
インデックスを使って要素を操作できるのがfor文の利点です。また、繰り返しのパターンも柔軟に設定できます。
より複雑なループを扱う際に注意したい「よくあるミス」について、次に見ていきましょう。
よくあるエラーと注意点

代表的なエラーパターン
エラー1:無限ループ
問題のあるコード:
// 危険!無限ループになる
for (int i = 0; i >= 0; i++) // 条件が常にtrue
{
Console.WriteLine(i); // 永遠に続く
}
なぜ無限ループになるのか:
i >= 0
という条件は、iが0以上である限り常にtruei++
でiは増加し続けるため、条件がfalseになることがない
正しい修正例:
// 正しい書き方
for (int i = 0; i < 10; i++) // 明確な終了条件
{
Console.WriteLine(i);
}
エラー2:配列の範囲外アクセス
問題のあるコード:
int[] numbers = {1, 2, 3, 4, 5};
// 危険!配列の範囲を超える
for (int i = 0; i <= numbers.Length; i++) // <= が問題
{
Console.WriteLine(numbers[i]); // numbers[5]でエラー
}
エラーメッセージ:
System.IndexOutOfRangeException: Index was outside the bounds of the array.
正しい修正例:
int[] numbers = {1, 2, 3, 4, 5};
// 正しい書き方
for (int i = 0; i < numbers.Length; i++) // < を使用
{
Console.WriteLine(numbers[i]);
}
エラー3:変数のスコープ問題
問題のあるコード:
// ループ外でiを使おうとしてエラー
for (int i = 0; i < 5; i++)
{
Console.WriteLine(i);
}
Console.WriteLine(i); // エラー!iはここでは使えない
正しい修正例:
// ループ外で変数を定義
int i;
for (i = 0; i < 5; i++)
{
Console.WriteLine(i);
}
Console.WriteLine($"ループ終了後のi: {i}"); // 正常に動作
一般的なミスとその対策
ミス1:off-by-one エラー
よくある間違い:
int[] array = new int[10];
// 間違い:配列サイズを1つ超えている
for (int i = 1; i <= array.Length; i++)
{
array[i] = i; // array[10]でエラー
}
正しい書き方:
int[] array = new int[10];
// 正しい:0から9まで
for (int i = 0; i < array.Length; i++)
{
array[i] = i + 1;
}
ミス2:更新部分の間違い
問題のあるコード:
// 間違い:iが更新されない
for (int i = 0; i < 10; /* i++が抜けている */)
{
Console.WriteLine(i); // 無限ループ
}
正しい書き方:
// 正しい:更新部分を忘れずに
for (int i = 0; i < 10; i++)
{
Console.WriteLine(i);
}
ミス3:ネストしたループでの変数名の混同
問題のあるコード:
// 間違い:同じ変数名を使用
for (int i = 0; i < 3; i++)
{
for (int i = 0; i < 3; i++) // 変数名が重複
{
Console.WriteLine(i);
}
}
正しい書き方:
// 正しい:異なる変数名を使用
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 3; j++) // 異なる変数名
{
Console.WriteLine($"i={i}, j={j}");
}
}
デバッグのコツ
デバッグ用の出力を追加
int[] numbers = {10, 20, 30, 40, 50};
for (int i = 0; i < numbers.Length; i++)
{
// デバッグ用の出力
Console.WriteLine($"Debug: i={i}, numbers[i]={numbers[i]}");
// 実際の処理
if (numbers[i] > 25)
{
Console.WriteLine($"Found: {numbers[i]}");
}
}
条件を段階的にチェック
int[] data = {1, 2, 3, 4, 5};
// まず単純なループで動作確認
for (int i = 0; i < data.Length; i++)
{
Console.WriteLine($"Processing index {i}");
}
// 次に実際の処理を追加
for (int i = 0; i < data.Length; i++)
{
Console.WriteLine($"Processing index {i}: value = {data[i]}");
// ここに複雑な処理を追加
}
エラーの原因を事前に知っておくことで、より安全にfor文を活用できます。
実践的なプログラム例
例1:成績管理システム
using System;
class Program
{
static void Main()
{
// 5人の学生の成績
string[] students = {"田中", "佐藤", "鈴木", "高橋", "渡辺"};
int[] scores = {85, 92, 78, 95, 88};
Console.WriteLine("=== 成績一覧 ===");
for (int i = 0; i < students.Length; i++)
{
string grade = GetGrade(scores[i]);
Console.WriteLine($"{students[i]}: {scores[i]}点 ({grade})");
}
// 統計情報の計算
int total = 0;
int maxScore = scores[0];
int minScore = scores[0];
string topStudent = students[0];
for (int i = 0; i < scores.Length; i++)
{
total += scores[i];
if (scores[i] > maxScore)
{
maxScore = scores[i];
topStudent = students[i];
}
if (scores[i] < minScore)
{
minScore = scores[i];
}
}
double average = (double)total / scores.Length;
Console.WriteLine("\n=== 統計情報 ===");
Console.WriteLine($"平均点: {average:F1}点");
Console.WriteLine($"最高点: {maxScore}点 ({topStudent})");
Console.WriteLine($"最低点: {minScore}点");
}
static string GetGrade(int score)
{
if (score >= 90) return "A";
else if (score >= 80) return "B";
else if (score >= 70) return "C";
else if (score >= 60) return "D";
else return "F";
}
}
例2:簡単な暗号化プログラム
using System;
class Program
{
static void Main()
{
string message = "Hello World";
int shift = 3; // シーザー暗号のシフト量
Console.WriteLine($"元のメッセージ: {message}");
// 暗号化
string encrypted = "";
for (int i = 0; i < message.Length; i++)
{
char c = message[i];
if (char.IsLetter(c))
{
// アルファベットの場合のみ暗号化
char shifted = ShiftCharacter(c, shift);
encrypted += shifted;
}
else
{
// アルファベット以外はそのまま
encrypted += c;
}
}
Console.WriteLine($"暗号化: {encrypted}");
// 復号化
string decrypted = "";
for (int i = 0; i < encrypted.Length; i++)
{
char c = encrypted[i];
if (char.IsLetter(c))
{
char shifted = ShiftCharacter(c, -shift); // 逆方向にシフト
decrypted += shifted;
}
else
{
decrypted += c;
}
}
Console.WriteLine($"復号化: {decrypted}");
}
static char ShiftCharacter(char c, int shift)
{
if (char.IsUpper(c))
{
return (char)((c - 'A' + shift + 26) % 26 + 'A');
}
else
{
return (char)((c - 'a' + shift + 26) % 26 + 'a');
}
}
}
例3:数字当てゲーム
using System;
class Program
{
static void Main()
{
Random random = new Random();
int secretNumber = random.Next(1, 101); // 1-100の乱数
int maxAttempts = 7;
bool gameWon = false;
Console.WriteLine("数字当てゲーム!");
Console.WriteLine("1から100までの数字を当ててください。");
Console.WriteLine($"チャンスは{maxAttempts}回です。\n");
for (int attempt = 1; attempt <= maxAttempts; attempt++)
{
Console.Write($"試行 {attempt}/{maxAttempts}: ");
// ユーザー入力の取得と検証
string input = Console.ReadLine();
if (!int.TryParse(input, out int guess))
{
Console.WriteLine("有効な数字を入力してください。");
attempt--; // 無効な入力は回数にカウントしない
continue;
}
if (guess == secretNumber)
{
Console.WriteLine($"正解!{attempt}回で当てました!");
gameWon = true;
break;
}
else if (guess < secretNumber)
{
Console.WriteLine("もっと大きな数字です。");
}
else
{
Console.WriteLine("もっと小さな数字です。");
}
// 残り回数の表示
if (attempt < maxAttempts)
{
Console.WriteLine($"残り{maxAttempts - attempt}回\n");
}
}
if (!gameWon)
{
Console.WriteLine($"残念!正解は {secretNumber} でした。");
}
}
}
まとめ
for文の重要性
C#のfor文は、構造がシンプルでありながら柔軟性が高く、プログラムの効率化に欠かせない存在です。
この記事の要点
基本構文の理解
- 初期化、条件、更新の三要素
- 実行の流れを正確に把握
- ループ変数のスコープを理解
実践的な応用
- 配列とListの効率的な処理
- ネストしたループの活用
- 条件分岐との組み合わせ
エラー対策
- 無限ループの回避
- 配列の範囲外アクセス防止
- 変数スコープの適切な管理
コメント