流程控制:程序的“交通指挥员”

大家好,我是你们的老朋友。今天我们来聊聊C++和Qt里的流程控制。说白了,就是教程序“什么时候该做什么事”。

我刚开始学编程时,觉得这玩意儿特简单。不就是if-else嘛,谁不会啊?结果后来写了个复杂的业务逻辑,嵌套了七八层if,自己都看晕了。嗯,从那以后我才明白——流程控制写得好不好,直接决定代码是“艺术品”还是“垃圾堆”。

核心思想:程序默认是顺序执行的——从上往下,一行一行跑。流程控制就是打破这种顺序,让程序能“思考”、能“循环”、能“跳转”。

1. if/else:最常用的“岔路口”

if/else 就像你走到一个岔路口。条件成立走左边,不成立走右边。你想想看,生活中到处都是这种选择。

int score = 85;
if (score >= 60) {
    cout << "及格了,不错!" << endl;
} else {
    cout << "不及格,继续努力!" << endl;
}

我个人习惯把 if 后面的花括号直接写在同行,这样代码更紧凑。当然也有人喜欢换行,这个看团队规范。

小技巧:如果只有一条语句,可以省略花括号。但我建议永远不要省——我踩过这个坑,后来加代码时忘了加括号,结果逻辑全乱了。

多分支时用 else if:

if (score >= 90) {
    cout << "优秀" << endl;
} else if (score >= 80) {
    cout << "良好" << endl;
} else if (score >= 60) {
    cout << "及格" << endl;
} else {
    cout << "不及格" << endl;
}

注意:else 总是匹配最近的 if。我曾经见过一个bug,就是因为else匹配错了,排查了一下午。建议多用花括号明确范围。

2. switch:多路选择的“高速公路”

当你有多个固定值要判断时,switch 比 if-else 更清晰。它就像高速公路上的出口指示牌——根据你的出口号直接拐出去。

int day = 3;
switch (day) {
    case 1:
        cout << "周一" << endl;
        break;
    case 2:
        cout << "周二" << endl;
        break;
    case 3:
        cout << "周三" << endl;
        break;
    default:
        cout << "其他" << endl;
        break;
}

这里有个关键点——break 不能忘。忘了 break 就会“穿透”到下一个 case。有时候我们故意利用这个特性,比如多个 case 共享同一段代码:

switch (grade) {
    case 'A':
    case 'B':
        cout << "通过" << endl;
        break;
    case 'C':
    case 'D':
        cout << "补考" << endl;
        break;
}

我的经验:switch 只适合判断整型、字符型、枚举型。别拿它判断字符串——那是 if-else 的活。

3. while 和 do-while:循环的两种“姿势”

while 循环:先判断,再执行。条件不满足,一次都不跑。

int i = 0;
while (i < 5) {
    cout << i << " ";
    i++;
}
// 输出:0 1 2 3 4

do-while 循环:先执行一次,再判断。至少跑一次。

int i = 0;
do {
    cout << i << " ";
    i++;
} while (i < 5);
// 输出:0 1 2 3 4

有什么区别?你想想看——如果条件一开始就不成立,while 直接跳过,do-while 至少执行一次。我在项目中用 do-while 的场景不多,但处理用户输入验证时特别好用:

int choice;
do {
    cout << "请输入1-3之间的数字:";
    cin >> choice;
} while (choice < 1 || choice > 3);

避坑指南:我曾经写过一个 while 循环,忘了更新循环变量,结果死循环了。程序卡死,CPU 飙到100%。嗯,从那以后我每次写循环都先检查“退出条件会不会变”。

4. for 循环:最常用的“计数循环”

for 循环是 C++ 里最灵活的循环。它把初始化、条件判断、变量更新都写在一行:

for (int i = 0; i < 10; i++) {
    cout << i << " ";
}
// 输出:0 1 2 3 4 5 6 7 8 9

三个部分都可以省略,但分号不能省:

int i = 0;
for (; i < 10; ) {
    cout << i << " ";
    i++;
}

我个人习惯用 for 循环遍历数组或容器:

int arr[] = {10, 20, 30, 40, 50};
for (int i = 0; i < 5; i++) {
    cout << arr[i] << " ";
}

C++11 之后有了范围 for 循环,更简洁:

for (int x : arr) {
    cout << x << " ";
}

核心区别:for 循环适合“知道要循环多少次”的场景,while 适合“不知道次数,只知道条件”的场景。

5. break 和 continue:循环里的“刹车”和“跳过”

break:立即跳出整个循环。continue:跳过本次循环的剩余部分,进入下一次。

for (int i = 0; i < 10; i++) {
    if (i == 5) {
        break;  // 到5就停,输出:0 1 2 3 4
    }
    cout << i << " ";
}

for (int i = 0; i < 10; i++) {
    if (i % 2 == 0) {
        continue;  // 跳过偶数,输出:1 3 5 7 9
    }
    cout << i << " ";
}

注意:break 只跳出当前一层循环。嵌套循环里想跳出外层?要么用 goto,要么用标志变量。我建议用标志变量——goto 容易把代码搞乱。

6. goto:被“妖魔化”的跳转

很多教材说“goto 是魔鬼,永远别用”。我不完全同意。goto 确实容易写出“意大利面条式代码”,但有些场景它确实方便。

for (int i = 0; i < 10; i++) {
    for (int j = 0; j < 10; j++) {
        if (someCondition) {
            goto cleanup;
        }
    }
}
cleanup:
    cout << "跳出双层循环" << endl;

我在项目中用过一次 goto——处理多层循环里的错误清理。当时用标志变量要写好几行,goto 一行搞定。但说实话,能用其他方式就别用 goto。

我的建议:goto 可以用,但仅限于“向前跳转”清理资源。别用它向后跳——那才是真正的“魔鬼”。

知识体系总览

下面这张图总结了本章的流程控制结构:

C++ 流程控制知识体系 分支控制 if / else if / else switch / case / default 三目运算符 ? : 循环控制 for 循环(计数循环) while 循环(先判断后执行) do-while(至少执行一次) 跳转控制 break(跳出当前循环) continue(跳过本次循环) goto(无条件跳转,慎用) 三者配合使用,可以写出任意复杂的程序逻辑

总结对比表

控制结构 适用场景 执行次数 注意事项
if/else 条件分支,范围判断 0或1次 注意else匹配,多用花括号
switch 多值匹配(整型/枚举) 0或1次 别忘了break,小心穿透
for 已知循环次数 0~N次 循环变量别在内部修改
while 未知次数,已知条件 0~N次 小心死循环
do-while 至少执行一次 1~N次 条件写在后面
break 提前退出循环 0或1次 只跳出当前一层
continue 跳过本次循环 0~N次 注意循环变量更新
goto 多层跳出/错误处理 0或1次 尽量不用,用标志变量替代

好了,流程控制就讲到这里。这些东西看着简单,但写代码时处处都是坑。我建议你每学一个结构,就写几个小例子跑一跑。代码这东西,光看是学不会的。

一句话总结:if/else 做选择,for/while 做循环,break/continue 做控制,goto 做最后的“救命稻草”。

公众号:蓝海资料掘金营,微信deep3321