Skip to content

09-循环语句

循环语句用于重复执行一段代码,直到满足特定条件。C# 提供了四种循环机制,每种适用于不同场景。


一、四种循环对比总览

循环类型执行特点最少执行次数适用场景
while先判断条件,后执行循环体0 次不确定循环次数,可能一次都不执行
do-while先执行循环体,后判断条件1 次至少需要执行一次循环体
for初始化、条件、迭代集中在头部0 次明确知道循环次数
foreach自动遍历集合元素0 次遍历数组或集合全部元素

二、while 循环

基本语法

csharp
while (条件表达式)
{
    // 循环体——条件为 true 时重复执行
}

执行流程: 先判断条件 → 为 true 则执行循环体 → 再次判断条件 → 直到条件为 false 退出。

示例:数字累加

csharp
// 计算 1+2+3+...+100
int i = 1;
int sum = 0;

while (i <= 100)
{
    sum += i;   // 等价于 sum = sum + i
    i++;        // 计数器递增——必须有改变条件的语句
}

Console.WriteLine($"1+2+...+100 = {sum}");  // 输出:5050

示例:猜数字游戏

csharp
Random rnd = new Random();
int target = rnd.Next(1, 101);  // 生成 1~100 的随机数
int guess = 0;
int attempts = 0;

Console.WriteLine("猜一个 1~100 之间的数字:");

while (guess != target)
{
    guess = int.Parse(Console.ReadLine());
    attempts++;

    if (guess > target)
        Console.WriteLine("太大了,再试试!");
    else if (guess < target)
        Console.WriteLine("太小了,再试试!");
}

Console.WriteLine($"恭喜你猜对了!答案是 {target},共猜了 {attempts} 次。");

注意事项

问题说明示例
死循环条件永远为 true,循环永不结束while (true) { }
忘记递增循环变量未改变,导致死循环while (i < 10) { } 但 i 从不增加
条件不满足条件一开始就为 false,循环体一次也不执行while (false) { }

三、do-while 循环

基本语法

csharp
do
{
    // 循环体——至少执行一次
} while (条件表达式);  // 注意:末尾有分号

与 while 的核心区别

csharp
// while:可能一次都不执行
int a = 10;
while (a < 5)
{
    Console.WriteLine("这行不会输出");
}

// do-while:至少执行一次
int b = 10;
do
{
    Console.WriteLine("这行会输出一次");
} while (b < 5);

示例:菜单选择

csharp
string choice;
do
{
    Console.WriteLine("=== 菜单 ===");
    Console.WriteLine("1. 查询余额");
    Console.WriteLine("2. 取款");
    Console.WriteLine("3. 存款");
    Console.WriteLine("0. 退出");
    Console.Write("请选择:");

    choice = Console.ReadLine();

    switch (choice)
    {
        case "1":
            Console.WriteLine("您的余额为:1000 元");
            break;
        case "2":
            Console.WriteLine("请输入取款金额");
            break;
        case "3":
            Console.WriteLine("请输入存款金额");
            break;
    }

    Console.WriteLine();  // 空行
} while (choice != "0");  // 选择 0 时退出

Console.WriteLine("感谢使用,再见!");

四、for 循环

基本语法与执行顺序

csharp
for (初始化表达式; 条件表达式; 迭代表达式)
{
    // 循环体
}

执行顺序:

步骤1: 初始化表达式(仅执行一次)

步骤2: 条件表达式(true 则继续,false 则退出)

步骤3: 执行循环体

步骤4: 迭代表达式

回到步骤2

示例:遍历数组求和

csharp
int[] scores = { 85, 92, 78, 95, 88 };
int sum = 0;

for (int i = 0; i < scores.Length; i++)
{
    sum += scores[i];
}

double average = (double)sum / scores.Length;
Console.WriteLine($"总分:{sum},平均分:{average:F1}");  // 输出:总分:438,平均分:87.6

多种变体

csharp
// 1. 多个变量同时控制
for (int i = 1, j = 10; i < j; i++, j--)
{
    Console.WriteLine($"i={i}, j={j}");
}

// 2. 省略初始化
int k = 0;
for (; k < 5; k++)
{
    Console.WriteLine(k);
}

// 3. 省略所有表达式(死循环)
// for (;;) { }

// 4. 循环变量在外部使用
int m;
for (m = 0; m < 10; m++) { }
Console.WriteLine($"最终值:{m}");  // 输出:10

实战:打印乘法表

csharp
for (int i = 1; i <= 9; i++)
{
    for (int j = 1; j <= i; j++)
    {
        Console.Write($"{j}×{i}={i * j,-4}");  // -4 表示左对齐占4位
    }
    Console.WriteLine();
}

五、foreach 循环

用于遍历实现了 IEnumerable 接口的集合(数组、List、Dictionary 等)。

基本语法

csharp
foreach (元素类型 变量名 in 集合)
{
    // 使用变量
}

示例:遍历不同集合

csharp
// 遍历数组
int[] numbers = { 10, 20, 30 };
foreach (int n in numbers)
    Console.WriteLine(n);

// 遍历 List
List<string> names = new List<string> { "张三", "李四", "王五" };
foreach (string name in names)
    Console.WriteLine(name);

// 遍历 Dictionary
Dictionary<string, int> scores = new Dictionary<string, int>
{
    { "语文", 90 }, { "数学", 85 }, { "英语", 88 }
};
foreach (KeyValuePair<string, int> kvp in scores)
{
    Console.WriteLine($"{kvp.Key}:{kvp.Value}分");
}

// 只遍历键或值
foreach (string key in scores.Keys) Console.WriteLine(key);
foreach (int value in scores.Values) Console.WriteLine(value);

foreach 的限制

csharp
// 限制1:迭代变量是只读的,不能修改
int[] arr = { 1, 2, 3 };
foreach (int n in arr)
{
    // n = 10;  // 编译错误:无法对 foreach 变量赋值
}

// 限制2:遍历时不能修改集合(增删元素)
List<int> list = new List<int> { 1, 2, 3 };
foreach (int n in list)
{
    // list.Add(4);  // 运行错误:InvalidOperationException
    // list.Remove(n);  // 同样会抛出异常
}

// 如果需要修改,使用 for 循环
for (int i = list.Count - 1; i >= 0; i--)
{
    if (list[i] % 2 == 0)
        list.RemoveAt(i);
}

六、循环控制语句

控制语句作用适用场景
break立即终止整个循环找到目标后提前结束
continue跳过本次循环剩余部分,进入下一次迭代排除某些特殊情况
return退出整个方法(不仅仅是循环)需要直接结束方法
goto跳转到指定标签多层嵌套循环中快速跳出(慎用)

break:提前退出

csharp
// 查找第一个偶数
int[] numbers = { 3, 5, 2, 7, 8 };
for (int i = 0; i < numbers.Length; i++)
{
    if (numbers[i] % 2 == 0)
    {
        Console.WriteLine($"找到第一个偶数:{numbers[i]},索引:{i}");
        break;  // 找到后立即退出循环
    }
}
// 输出:找到第一个偶数:2,索引:2

continue:跳过本次

csharp
// 打印 1~10 之间的奇数
for (int i = 1; i <= 10; i++)
{
    if (i % 2 == 0)
        continue;  // 偶数跳过,不打印
    Console.Write($"{i} ");
}
// 输出:1 3 5 7 9

break 与 continue 对比

csharp
for (int i = 1; i <= 5; i++)
{
    if (i == 3)
        break;    // i=3 时整个循环结束
    Console.Write(i + " ");
}
// break 输出:1 2

for (int i = 1; i <= 5; i++)
{
    if (i == 3)
        continue;  // i=3 时跳过,继续下一次
    Console.Write(i + " ");
}
// continue 输出:1 2 4 5

goto:跳出多层嵌套

csharp
// 在二维数组中查找指定值
int[,] matrix = {
    { 1, 2, 3 },
    { 4, 5, 6 },
    { 7, 8, 9 }
};
int target = 5;
bool found = false;

for (int i = 0; i < matrix.GetLength(0); i++)
{
    for (int j = 0; j < matrix.GetLength(1); j++)
    {
        if (matrix[i, j] == target)
        {
            Console.WriteLine($"找到 {target} 在 [{i},{j}]");
            goto Found;  // 直接跳转到标签
        }
    }
}

Console.WriteLine("未找到");

Found:
Console.WriteLine("查找结束");

七、嵌套循环

语法理解

外层循环每执行一次,内层循环完整执行一轮

csharp
// 理解嵌套执行流程
for (int i = 1; i <= 3; i++)
{
    Console.WriteLine($"外层 i={i} —— 进入内层循环");
    for (int j = 1; j <= 3; j++)
    {
        Console.WriteLine($"  内层 j={j}");
    }
    Console.WriteLine($"外层 i={i} —— 内层循环结束");
}
// 外层执行 3 次,内层执行 3×3=9 次

实战:打印图形

csharp
// 直角三角形
for (int i = 1; i <= 5; i++)
{
    for (int j = 1; j <= i; j++)
    {
        Console.Write("*");
    }
    Console.WriteLine();
}
// 输出:
// *
// **
// ***
// ****
// *****

// 菱形
int n = 5;
for (int i = 1; i <= n; i++)
{
    for (int j = i; j < n; j++) Console.Write(" ");
    for (int j = 1; j <= 2 * i - 1; j++) Console.Write("*");
    Console.WriteLine();
}
for (int i = n - 1; i >= 1; i--)
{
    for (int j = n; j > i; j--) Console.Write(" ");
    for (int j = 1; j <= 2 * i - 1; j++) Console.Write("*");
    Console.WriteLine();
}

八、死循环与正确退出方式

某些场景(如服务器监听、游戏主循环)需要死循环,配合 break 或条件退出。

csharp
// 聊天程序:输入 exit 退出
while (true)
{
    Console.Write("请输入消息(输入 exit 退出):");
    string input = Console.ReadLine();

    if (input == "exit")
    {
        Console.WriteLine("再见!");
        break;  // 退出循环
    }

    if (string.IsNullOrWhiteSpace(input))
    {
        Console.WriteLine("输入不能为空,请重新输入");
        continue;  // 跳过本次,回到循环开头
    }

    Console.WriteLine($"你发送了:{input}");
}

九、综合案例

学生成绩管理系统

csharp
static void Main()
{
    List<int> scores = new List<int>();

    while (true)
    {
        Console.WriteLine("\n=== 学生成绩管理系统 ===");
        Console.WriteLine("1. 添加成绩");
        Console.WriteLine("2. 查看所有成绩");
        Console.WriteLine("3. 统计信息");
        Console.WriteLine("4. 查找成绩");
        Console.WriteLine("0. 退出");
        Console.Write("请选择:");

        string choice = Console.ReadLine();

        switch (choice)
        {
            case "1":
                Console.Write("请输入成绩(0-100):");
                if (int.TryParse(Console.ReadLine(), out int score) && score >= 0 && score <= 100)
                {
                    scores.Add(score);
                    Console.WriteLine("添加成功!");
                }
                else
                {
                    Console.WriteLine("输入无效!");
                }
                break;

            case "2":
                Console.WriteLine($"共 {scores.Count} 个成绩:");
                for (int i = 0; i < scores.Count; i++)
                    Console.WriteLine($"  [{i}] {scores[i]}");
                break;

            case "3":
                if (scores.Count > 0)
                {
                    int sum = 0, max = scores[0], min = scores[0];
                    foreach (int s in scores)
                    {
                        sum += s;
                        if (s > max) max = s;
                        if (s < min) min = s;
                    }
                    Console.WriteLine($"平均分:{(double)sum / scores.Count:F1}");
                    Console.WriteLine($"最高分:{max}");
                    Console.WriteLine($"最低分:{min}");
                }
                else
                {
                    Console.WriteLine("暂无成绩数据");
                }
                break;

            case "4":
                Console.Write("请输入要查找的分数:");
                if (int.TryParse(Console.ReadLine(), out int target))
                {
                    bool found = false;
                    for (int i = 0; i < scores.Count; i++)
                    {
                        if (scores[i] == target)
                        {
                            Console.WriteLine($"在索引 [{i}] 处找到");
                            found = true;
                        }
                    }
                    if (!found) Console.WriteLine("未找到该成绩");
                }
                break;

            case "0":
                Console.WriteLine("感谢使用!");
                return;  // 退出 Main 方法

            default:
                Console.WriteLine("无效选项,请重新选择");
                break;
        }
    }
}

核心知识点总结

循环类型语法特点计数方式典型应用
while条件前置外部计数器不确定次数的循环
do-while条件后置(至少一次)外部计数器菜单选择、输入验证
for初始化/条件/迭代集中内置计数器确定次数的循环、数组遍历
foreach自动迭代无需计数器遍历集合全部元素

注意事项

  1. 避免死循环:确保循环条件最终会变为 false
  2. 循环变量作用域for 中声明的变量只在循环内有效
  3. 修改集合foreach 中不能修改集合(增删元素),用 for 代替
  4. 性能考虑:将不需要重复计算的表达式移到循环外部
    csharp
    // 不推荐
    for (int i = 0; i < list.Count; i++)  // 每次循环都计算 Count
    
    // 推荐
    for (int i = 0, count = list.Count; i < count; i++)  // Count 只计算一次
  5. break vs continue vs return
    • break:退出当前循环
    • continue:跳过本次循环剩余代码
    • return:退出整个方法

Released under the MIT License.