CC++ & Algorithm

顺序结构程序设计

简单8
语言版本:C++
概述:程序就像做菜一样,从上往下一步一步执行,这就是顺序结构。

顺序结构程序设计:像做菜一样,一步一步来

程序就像我们在厨房里做一道菜:先洗菜、切菜,再开火、放油,最后下锅翻炒。每一步都有固定的顺序,不能颠倒,否则可能会做出黑暗料理。在C++里,顺序结构就是让代码从上往下一条一条地执行,就像按顺序完成菜谱上的步骤一样。

什么是顺序结构?

顺序结构是编程中最简单、最基础的控制结构。它没有分叉、没有循环,只是一行一行地往下走。你可以想象成在排队买冰淇淋:先付钱,再拿到券,然后去窗口取冰淇淋。如果顺序搞反了,可能两手空空。C++程序默认就是顺序执行的,除非你用了ifwhile等改变流程的语句。

为什么顺序很重要?

因为计算机很“死板”,它只会老老实实地按代码的顺序执行。如果顺序错了,结果就会完全不一样。比如下面这个例子:

#include <iostream>
using namespace std;

int main() {
    int a = 3;          // 定义变量a,赋值为3
    int b = 5;          // 定义变量b,赋值为5
    int sum = a + b;    // 计算a+b,结果存入sum
    cout << "两个数的和是:" << sum << endl;  // 输出sum
    return 0;
}

这段代码先定义ab,再计算和,最后输出。如果我把第三行和第四行的顺序交换:

int a = 3;
cout << "两个数的和是:" << sum << endl;  // 此时sum还没有定义,会报错!
int sum = a + b;

计算机就会报错,因为它在用到sum时还没定义。即使先定义sum但不赋值,输出也会是一个随机的垃圾值。就像你还没给手机充电就想开机,结果当然不对劲。

顺序结构中的常见操作

顺序结构通常包含三类操作:

  • 输入:从键盘读取数据(比如用cin
  • 处理:进行计算或逻辑操作(比如加减乘除、字符串拼接)
  • 输出:把结果显示出来(比如用cout

一个典型的“输入-处理-输出”程序是这样的:

#include <iostream>
using namespace std;

int main() {
    int num1, num2;          // 定义两个整数变量
    cout << "请输入两个整数:"; 
    cin >> num1 >> num2;     // 从键盘读入两个数
    int product = num1 * num2;   // 计算乘积
    cout << "它们的乘积是:" << product << endl;  // 输出结果
    return 0;
}

这个程序先让用户输入,再计算,最后输出。如果先把计算结果放在输入之前,就会出错。

生活中顺序结构的例子

顺序结构在生活中无处不在:

  • 数学考试:先读题,再列式,最后计算答案。
  • 吃早餐:先盛粥,再夹菜,最后喝粥。如果先喝粥再盛粥,桌子就脏了。
  • 玩游戏:先打开游戏,再选择角色,最后开始战斗。如果跳过前面的步骤,游戏可能无法正常启动。

新手容易犯的错误

  1. 变量使用前未定义或未赋值
    比如下面的代码会输出一个随机数(甚至编译错误):

    int x;
    cout << x;  // x没赋值,输出不确定
    
  2. 顺序颠倒导致逻辑错误
    想要交换两个变量的值,必须用第三个变量暂存,顺序很重要:

    int a = 5, b = 3, temp; // temp是临时变量
    temp = a;   // temp = 5
    a = b;      // a = 3
    b = temp;   // b = 5
    

    如果写成a = b; b = a;,结果就会变成a=3,b=3,因为第一个赋值把a原来的值覆盖了。

  3. 忘记换行导致输出挤在一起
    cout默认不会自动换行,需要用endl\n

    cout << "第一行";  // 不带换行
    cout << "第二行";  // 输出结果:第一行第二行
    

完整可运行的示例:计算圆的面积和周长

下面是一个用顺序结构解决问题的完整程序:

#include <iostream>
using namespace std;

int main() {
    double radius;                 // 半径
    const double PI = 3.14159;     // 常量PI
    
    cout << "请输入圆的半径:";
    cin >> radius;                 // 输入半径
    
    double area = PI * radius * radius;       // 计算面积
    double perimeter = 2 * PI * radius;       // 计算周长
    
    cout << "圆的面积是:" << area << endl;
    cout << "圆的周长是:" << perimeter << endl;
    
    return 0;
}

这个程序严格按照“输入→计算→输出”的顺序执行,每一步都不能调换。

相关指引

  • 如果你想给程序增加判断能力(比如根据考试分数输出不同评语),可以学习 if-else分支语句
  • 如果想让程序重复执行某一件事(比如计算全班同学的平均分),可以学习 for循环while循环
  • 顺序结构是所有程序的基础,掌握好它,再学习其他结构就会轻松很多。

if-else分支语句:让电脑学会“做选择”

生活中我们经常要做选择:如果今天下雨,就带伞;否则就不带。如果这次考试及格了,就奖励自己一个冰淇淋;否则就继续努力。C++中的 if-else 语句正好帮我们实现这种“二选一”的判断逻辑。

if-else 的基本结构

想象你在一个十字路口,面前有两个方向:左边是“条件为真”的路,右边是“条件为假”的路。if-else 就是那个路牌,它告诉你走哪条路。

if (条件) {
    // 条件成立时执行的代码
} else {
    // 条件不成立时执行的代码
}

流程:先判断括号里的条件是否成立(true),如果成立就执行大括号里的代码;否则执行 else 后面的代码。

生活中的例子:判断成绩是否及格

小明这次考了85分,老师说不低于60分就算及格。我们可以用程序来模拟:

#include <iostream>
using namespace std;

int main() {
    int score = 85;  // 小明的分数
    
    if (score >= 60) {
        cout << "恭喜你,及格了!" << endl;
    } else {
        cout << "继续努力,下次一定行!" << endl;
    }
    
    return 0;
}

因为85≥60,所以计算机执行第一个分支,输出“恭喜你”。如果分数是45,就会输出“继续努力”。

只有 if 没有 else 的情况

有时候我们只需要在条件成立时做一件事,不成立时什么都不做。那就不用写 else:

if (score >= 60) {
    cout << "及格了!" << endl;
}
// 如果不及格,这里什么也不输出

多个条件:else if

如果判断不止两个分支,比如考试成绩分三档:

  • 90分以上:优秀
  • 60~89分:及格
  • 60分以下:不及格

我们可以用 else if 连接多个条件:

#include <iostream>
using namespace std;

int main() {
    int score = 85;
    
    if (score >= 90) {
        cout << "优秀!" << endl;
    } else if (score >= 60) {
        cout << "及格!" << endl;
    } else {
        cout << "不及格!" << endl;
    }
    
    return 0;
}

注意:条件检查是从上往下依次判断的。一旦某个条件成立,就会执行对应的代码块,然后跳过后面的所有 else if 和 else。所以上面的例子中,85分虽然满足 score>=60,但不会执行“优秀”,因为先判断了 score>=90 不成立。

嵌套的 if-else

if-else 里面可以再放一个 if-else,这叫嵌套。比如我们要判断一个数是正数、负数还是零:

#include <iostream>
using namespace std;

int main() {
    int num;
    cout << "请输入一个整数:";
    cin >> num;
    
    if (num > 0) {
        cout << "正数" << endl;
    } else {
        // num <= 0 的情况
        if (num < 0) {
            cout << "负数" << endl;
        } else {
            cout << "零" << endl;
        }
    }
    
    return 0;
}

嵌套时要注意花括号的配对,就像俄罗斯套娃一样,每个内层括号都要完整匹配。初学者常常忘记写内层的花括号,导致代码逻辑混乱。

新手容易犯的错误

  1. if 后面的条件忘了加括号
    正确:if (score >= 60)
    错误:if score >= 60

  2. 条件里用等号(=)和双等号(==)混淆
    = 是赋值,== 才是判断相等
    错误:if (a = 5) 会把5赋值给a,然后条件永远为true(因为非零值为真),逻辑完全错了。

  3. else 后面不要加条件
    else 表示“所有其他情况”,不能写成 else (条件),但可以写成 else if (条件)

  4. 花括号省略导致意外
    如果 if 或 else 后面只有一行代码,可以省略花括号,但新手容易误以为后面多行都属于该分支。比如:

    if (score >= 60)
        cout << "及格" << endl;
        cout << "这句话不受if控制,始终输出" << endl;
    

    这里第二行在 if 体之外,所以不论分数多少都会输出。建议即使一行也加上花括号。

完整可运行的示例:简单计算器(加减法)

这个程序让用户输入两个数和运算符(+或-),然后输出结果:

#include <iostream>
using namespace std;

int main() {
    double a, b;           // 两个操作数
    char op;               // 运算符
    cout << "请输入两个数和运算符(如 3 + 5):";
    cin >> a >> op >> b;
    
    if (op == '+') {
        cout << "结果:" << a + b << endl;
    } else if (op == '-') {
        cout << "结果:" << a - b << endl;
    } else {
        cout << "不支持的运算符!" << endl;
    }
    
    return 0;
}

相关指引

  • 如果判断的条件非常多(比如星期几对应不同活动),用 if-else if 可能会很长,这时可以学习 switch多分支语句 让代码更清晰。
  • 如果你想在循环里做判断(比如猜数字游戏),可以结合 while循环 一起使用。
  • if-else 让程序有了“大脑”,能根据情况做出不同动作,是编写智能程序的基础。

switch多分支语句:像游乐园里的多个滑梯

当你需要根据一个整数的值来决定做什么,而且有很多种可能时,用一连串的 if-else if 可能很啰嗦。这时候 switch 语句就像游乐园里的多道滑梯:你手里拿着一张数字票,走到对应的滑梯口,滑下去玩对应的项目。

switch 的基本结构

switch (变量) {
    case1:
        // 代码1
        break;
    case2:
        // 代码2
        break;
    // 更多 case ...
    default:
        // 其他情况
}

工作原理:计算机计算变量(必须是整数、字符或枚举类型)的值,然后从上到下匹配每个 case 后的值。一旦匹配,就会从那个 case 开始执行,直到遇到 break 才跳出整个 switch。如果所有 case 都不匹配,就执行 default 部分的代码(default 可以省略)。

生活中的例子:星期几做什么事

比如一个学生按星期几安排课外活动:

#include <iostream>
using namespace std;

int main() {
    int day = 3;  // 假设今天是星期三
    
    switch (day) {
        case 1:
            cout << "星期一:写代码" << endl;
            break;
        case 2:
            cout << "星期二:看书" << endl;
            break;
        case 3:
            cout << "星期三:跑步" << endl;
            break;
        case 4:
            cout << "星期四:画画" << endl;
            break;
        case 5:
            cout << "星期五:打游戏" << endl;
            break;
        case 6:
        case 7:
            cout << "周末:尽情玩" << endl;
            break;
        default:
            cout << "输入错误,请输入1~7" << endl;
    }
    
    return 0;
}

day 是3时,输出“星期三:跑步”。注意 case 6: 后面没有代码也没有 break,它会“穿透”到 case 7: 并执行那里的代码,所以星期六和星期日都会输出“周末:尽情玩”。这就是 穿透fall-through 特性,可以让我们把多个 case 合并成同一个操作。

为什么需要 break?

如果没有 break,程序执行完当前 case 后不会跳出 switch,而是继续执行下一个 case 的代码,不管值是否匹配。这就像滑梯底部没有刹车,你会直接滑到下一个滑梯的起点。有时候我们故意利用穿透(如上例的 case 6 和 case 7),但更多时候需要加上 break 防止错误。

switch 能判断哪些类型?

switch 只能判断整型(int、char、short、long、enum等),不能判断浮点数(float/double)或字符串(string)。如果你想判断浮点数或范围(比如 score >= 60),只能用 if-else。

新手容易犯的错误

  1. 忘记写 break 导致意外穿透
    比如写了一个星期几判断,忘记写 break,结果星期三会输出“星期三跑步”和“星期四画画”等,逻辑全乱。所以一般要在每个 case 末尾加 break,除非特意想穿透。

  2. case 后面忘记空格
    正确:case 1:
    错误:case1:(会被当作变量名)

  3. default 的位置
    default 可以放在 switch 的任何位置,但习惯放在最后。注意 default 后面也要加 break,虽然它后面通常没有 case了,但为了风格统一建议加上。

  4. case 值重复
    两个 case 不能用相同的值。

  5. 变量类型不匹配
    如果 switch 的变量是 char 类型,case 值要用单引号:case 'A':

完整可运行的示例:简易菜单程序

学校食堂的午餐有几种选择,用 switch 实现点餐:

#include <iostream>
using namespace std;

int main() {
    int choice;                    // 用户选择的编号
    cout << "欢迎用餐!请选择今日午餐:" << endl;
    cout << "1. 红烧肉饭" << endl;
    cout << "2. 鸡腿饭" << endl;
    cout << "3. 牛肉面" << endl;
    cout << "4. 饺子" << endl;
    cout << "请输入数字(1-4):";
    cin >> choice;
    
    switch (choice) {
        case 1:
            cout << "您选择了红烧肉饭,美味!" << endl;
            break;
        case 2:
            cout << "您选择了鸡腿饭,营养均衡!" << endl;
            break;
        case 3:
            cout << "您选择了牛肉面,热乎!" << endl;
            break;
        case 4:
            cout << "您选择了饺子,管饱!" << endl;
            break;
        default:
            cout << "没有这个选项,请重新选择。" << endl;
    }
    
    return 0;
}

相关指引

  • switch 适用于离散的、固定的值判断。如果条件更复杂(比如范围、多个条件组合),请使用 if-else分支语句
  • 在循环中经常用 switch 处理菜单选择,可以结合 循环嵌套 实现反复点餐直到退出。
  • 学会 switch,你的程序就拥有像自动售货机一样的能力——根据按键分配不同的商品。

for循环:像数数一样,重复固定次数

在编程中,我们经常需要重复做同一件事很多遍,比如输出1到100的数字,或者把全班同学的分数加起来。for循环 就是专门用来做“固定次数”重复的利器。它就像老师带着学生数数:“从1数到10,一个接一个,数完就停。”

for循环的三个部分

for循环的语法有三个关键部分,用分号隔开:

for (初始化; 条件; 更新) {
    // 循环体
}
  • 初始化:在循环开始前执行一次,通常用来定义循环变量并赋初值(比如 int i = 1)。
  • 条件:每次循环开始前检查,如果条件为真则继续循环,否则退出。
  • 更新:每次循环体执行完后执行,通常用来改变循环变量(比如 i++ 让 i 增加1)。

你可以把 for 循环想象成上学期的跑步打卡:第一天开始(初始化),每天检查是否已经够100天(条件),每天结束后在日历上打个勾(更新),然后继续。

例子:输出1到10的数字

#include <iostream>
using namespace std;

int main() {
    for (int i = 1; i <= 10; i++) {
        cout << i << " ";
    }
    cout << endl;
    return 0;
}

执行过程:

  1. int i = 1 执行一次。
  2. 检查 i <= 10,成立则进入循环体输出 i。
  3. 执行 i++,i 变为2。
  4. 回到第2步检查,直到 i=11 时条件不成立,循环结束。

输出:1 2 3 4 5 6 7 8 9 10

用 for 循环做累加

比如计算1+2+...+100:

#include <iostream>
using namespace std;

int main() {
    int sum = 0;                      // 累加器,初始为0
    for (int i = 1; i <= 100; i++) {
        sum += i;                     // 相当于 sum = sum + i
    }
    cout << "1+2+...+100 = " << sum << endl;
    return 0;
}

这里 sum 就像存钱罐,每循环一次就往里扔一枚面值为 i 的硬币。最后 sum = 5050。

循环变量可以递减

for 循环不一定非要从1递增到N,也可以从大到小。比如倒着输出:

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

新手容易犯的错误

  1. 死循环:条件永远为真,比如忘记写更新部分,或者更新写反了。

    for (int i = 1; i <= 10; ) {  // 没写 i++,i 永远为1,条件永远真
        cout << i;
    }
    

    程序会疯狂输出1,卡死。

  2. 在循环体里修改循环变量导致意外
    比如在循环体里写 i = 100,可能会提前结束或跳过一些迭代。

  3. 分号错误
    三个部分之间必须用分号,但不能有多余分号。比如 for (int i=1; i<=10; i++); 多了一个分号,循环体变成空语句,后面的花括号只执行一次。

  4. 循环变量作用域
    C++11之后,在 for 初始化部分定义的变量(如 int i)只在循环内部有效。如果循环结束后还想用 i,需要在外面定义。

完整可运行的示例:打印九九乘法表(部分)

下面用 for 循环嵌套(先不深入)实现一行乘法表:

#include <iostream>
using namespace std;

int main() {
    int n;
    cout << "请输入一个数字(1-9):";
    cin >> n;
    
    for (int i = 1; i <= n; i++) {
        cout << i << " * " << n << " = " << i * n << endl;
    }
    
    return 0;
}

输入 5 输出:

1 * 5 = 5
2 * 5 = 10
3 * 5 = 15
4 * 5 = 20
5 * 5 = 25

相关指引

  • 如果循环次数不确定,只知道什么时候停止,用 while循环 更合适。
  • 如果你需要在循环里再套一层循环(比如打印一个矩形),学习 循环嵌套
  • for 循环配合之前学的 if 语句可以解决很多实际问题,比如找出1到100之间的所有偶数。

while循环:只要条件满足,就会一直做

你听说过“还没做完作业不能看电视”吗?这句话里就藏着 while循环 的思想:只要“还没做完作业”这个条件成立,你就得一直做(重复写作业),而电视(循环体外的动作)就一直不能做。while循环就是“先检查条件,条件为真就做,然后再检查”的重复结构。

基本语法

while (条件) {
    // 循环体
}

执行过程

  1. 先判断条件。
  2. 如果条件为真,则执行一次循环体,然后回到第1步。
  3. 如果条件为假,则跳过循环体,执行后面代码。

所以,如果一开始条件就是假,循环体一次都不会执行。

与 for 循环的区别

  • for 循环通常用于循环次数已知的情况(如“从1到100”)。
  • while 循环更灵活,常用于“不知道具体次数,但知道什么时候结束”的情况。比如,不断询问用户密码直到正确为止。

例子:用 while 循环计算1到100的和

#include <iostream>
using namespace std;

int main() {
    int i = 1;          // 循环变量,从1开始
    int sum = 0;        // 累加器
    
    while (i <= 100) {
        sum += i;       // 累加
        i++;            // 更新变量,非常重要!
    }
    
    cout << "1+2+...+100 = " << sum << endl;
    return 0;
}

注意:一定要有 i++,否则 i 永远等于1,条件永远为真,程序会死循环。很多新手忘记写更新语句,导致程序卡死。

生活中的例子:密码验证

假设你设置的密码是 123456,程序要求用户输入密码,输错就重试,直到正确为止:

#include <iostream>
using namespace std;

int main() {
    int password;
    cout << "请输入密码:";
    cin >> password;
    
    while (password != 123456) {
        cout << "密码错误,请重新输入:";
        cin >> password;
    }
    
    cout << "登录成功!" << endl;
    return 0;
}

这里循环次数不确定,可能试一次就正确,也可能试很多次。while 循环完美适合这种场景。

什么时候用 while 而不是 for?

  • 如果循环次数由输入或计算决定,且事先不知道,用 while。
  • 如果循环需要同时初始化、条件检查和更新,用 for 更紧凑。
  • 实际上,两者可以相互转换,但选择哪个取决于哪段代码更易读。

新手容易犯的错误

  1. 忘记写更新语句导致死循环
    这是最常见的 while 错误。循环体内没有改变条件中变量的语句,条件永远为真。

  2. 条件写反了
    比如 while (i > 100) 想实现从1累加到100,结果条件一开始就不成立,循环体一次都不执行。

  3. 在条件中用赋值号=而不是双等号==
    while (a = 5) 会把5赋值给a,然后因为5非零,条件永远为真,死循环且逻辑错误。

完整可运行的示例:猜数字游戏(简化版)

计算机想一个1~10的整数,你猜,直到猜中为止(这里只用了while,没有if-else做提示,后面会增强):

#include <iostream>
#include <cstdlib>
#include <ctime>
using namespace std;

int main() {
    srand(time(0));                      // 随机种子
    int target = rand() % 10 + 1;        // 生成1~10的随机数
    int guess;
    
    cout << "我心里想了一个1到10之间的数字,你来猜猜看!" << endl;
    cout << "请输入你的猜测:";
    cin >> guess;
    
    while (guess != target) {
        cout << "猜错了,再试一次:";
        cin >> guess;
    }
    
    cout << "恭喜你,猜对了!" << endl;
    return 0;
}

这个程序只用 while 循环实现了“猜不对就重复”的逻辑。如果结合 if 语句,可以给出“大了/小了”的提示。详见 分支与循环综合应用

相关指引

  • 如果希望循环体至少执行一次(比如先输出菜单再询问是否继续),用 do-while循环 更合适。
  • while 循环经常与 if 联合使用,实现更复杂的重复操作。
  • 学习 for循环 可以掌握另一种重复模式。

do-while循环:先做一次,再决定要不要继续

你有没有听过“先尝后买”这句话?商家让你先吃一小口,好不好吃再决定买不买。do-while循环 就是这样:先执行一次循环体,然后再判断条件是否继续。它保证循环体至少会执行一次,这一点和 while 循环不同。

语法

do {
    // 循环体
} while (条件);

注意:后面有一个分号!这是很多新手容易忘的。

执行过程

  1. 执行一次循环体。
  2. 判断条件,如果为真,回到第1步;否则退出。

与 while 的对比

  • while:先判断,可能一次都不执行。
  • do-while:先执行一次,再判断,至少执行一次。

生活中的例子:先吃一口再说

你妈妈煮了一锅汤,让你尝一下咸淡。你先喝一口(do),如果觉得不够咸,就再加盐(循环体),然后再尝一口,直到满意为止。

在程序中,假设我们想反复询问用户“是否继续?”但至少先显示一次菜单:

#include <iostream>
using namespace std;

int main() {
    char choice;
    do {
        cout << "请输入你的选择(y/n):";
        cin >> choice;
    } while (choice != 'y' && choice != 'n');
    
    cout << "你输入的是:" << choice << endl;
    return 0;
}

这个程序先让用户输入一次,然后判断是否既不是 y 也不是 n,如果是就继续要求输入。注意:这里条件写的是“当输入不是 y 且不是 n 时继续”,所以输入 y 或 n 都会退出。

用 do-while 输出1到5

#include <iostream>
using namespace std;

int main() {
    int i = 1;
    do {
        cout << i << " ";
        i++;
    } while (i <= 5);
    cout << endl;
    return 0;
}

如果初始 i = 6,循环体也会先执行一次(输出6,i变为7),然后判断 i<=5 不成立退出。输出结果为:6(仅一个数字)。

什么时候用 do-while?

当程序逻辑要求“先做一次再决定”时,do-while 是最自然的。比如:

  • 菜单循环:至少显示一次菜单让用户选择。
  • 游戏回合:至少进行一轮游戏再询问是否继续。
  • 校验输入:先读取一次输入,如果无效则重试。

新手容易犯的错误

  1. 忘记写分号
    while (条件); 这个分号很容易忘,编译器会报错。

  2. 循环体只有一行时忘记花括号
    虽然 do-while 的循环体可以只有一行不加大括号,但为了清晰和扩展,建议始终加花括号。

  3. 条件写反
    比如想要“当密码错误时继续”,却写成 while (password == 123456);,结果正确密码反而会让循环继续。

完整可运行的示例:反复计算直到退出

一个简单的计算器,每次让用户输入两个数和操作符,输出结果,然后问是否继续:

#include <iostream>
using namespace std;

int main() {
    char ch;  // 是否继续
    do {
        double a, b;
        char op;
        cout << "输入表达式(如 3.5 + 2.1):";
        cin >> a >> op >> b;
        
        if (op == '+') {
            cout << "结果:" << a + b << endl;
        } else if (op == '-') {
            cout << "结果:" << a - b << endl;
        } else {
            cout << "不支持的运算符!" << endl;
        }
        
        cout << "是否继续计算?(y/n):";
        cin >> ch;
    } while (ch == 'y' || ch == 'Y');
    
    cout << "再见!" << endl;
    return 0;
}

这里用 do-while 确保至少计算一次。

相关指引


循环嵌套:循环里面套循环,就像做课间操

想象一下学校做课间操的情景:全校有3个年级(外层循环),每个年级有4个班(内层循环),每个班的学生依次做动作。这就是循环嵌套——一个循环的循环体里又包含另一个完整的循环。外层循环每执行一次,内层循环就要完整执行一遍。

最经典的例子:打印一个矩形

* 打印一个3行4列的矩形:

#include <iostream>
using namespace std;

int main() {
    // 外层循环:控制行数(3行)
    for (int i = 1; i <= 3; i++) {
        // 内层循环:控制每行的星号数(4个)
        for (int j = 1; j <= 4; j++) {
            cout << "*";
        }
        cout << endl;  // 每行结束后换行
    }
    return 0;
}

运行结果:

****
****
****

执行过程

  • i=1时,内层循环执行j从1到4,输出4个*,然后换行。
  • i=2时,同样内层循环再完整执行一遍,输出第二行。
  • i=3时,输出第三行。

内层循环像钟表的分针,外层像时针,分针转一圈(4次),时针才走一步(1行)。

打印乘法表

外层控制乘数,内层控制被乘数,且内层循环次数依赖于外层变量:

#include <iostream>
using namespace std;

int main() {
    for (int i = 1; i <= 9; i++) {
        for (int j = 1; j <= i; j++) {  // 内层循环到i为止
            cout << j << "*" << i << "=" << i*j << "\t";
        }
        cout << endl;
    }
    return 0;
}

输出:

1*1=1	
1*2=2	2*2=4	
1*3=3	2*3=6	3*3=9	
...

注意内层循环的条件是 j <= i,所以第一行只有1个等式,第二行2个,……第九行9个。

两种常见的嵌套形式

  1. 内外层独立:内层循环次数固定(如矩形)。
  2. 内层依赖于外层:内层循环次数随外层变化(如乘法表)。

新手容易犯的错误

  1. 内外层变量名相同
    如果内层也定义一个 int i,会覆盖外层变量,导致逻辑混乱(C++允许,但容易错)。建议内层用不同的名字,如 j, k。

  2. 忘记重置内层变量
    如果内层循环用 while 实现,且在内层结束后没有重置条件变量,第二次外层循环时内层条件可能已经不满足,导致内层不执行。例如:

    int i = 1;
    while (i <= 3) {
        int j = 1;
        while (j <= 4) {
            cout << "*";
            j++;      // 每行内层后j=5
        }
        // 这里正常,但如果是while(j <= 4)且j没有在每行前重置,就会出问题
        i++;
    }
    
  3. 嵌套层次太深
    3层以上嵌套容易让代码难以理解,也影响效率。如果必须多层,考虑用函数分解。

完整可运行的示例:打印菱形图案

用循环嵌套打印一个简单菱形(上半部分+下半部分):

#include <iostream>
using namespace std;

int main() {
    int rows = 5;  // 行数(奇数)
    
    // 上半部分(包括中间一行)
    for (int i = 1; i <= rows; i++) {
        for (int j = 1; j <= rows - i; j++) {
            cout << " ";   // 打印空格
        }
        for (int k = 1; k <= 2 * i - 1; k++) {
            cout << "*";   // 打印星号
        }
        cout << endl;
    }
    
    // 下半部分
    for (int i = rows - 1; i >= 1; i--) {
        for (int j = 1; j <= rows - i; j++) {
            cout << " ";
        }
        for (int k = 1; k <= 2 * i - 1; k++) {
            cout << "*";
        }
        cout << endl;
    }
    
    return 0;
}

相关指引

  • 循环嵌套经常与 顺序结构分支结构 结合,解决更复杂的问题。
  • 学习完基本的循环嵌套,可以挑战 分支与循环综合应用 中的猜数字、求最大公约数等问题。
  • 注意:嵌套循环的时间复杂度是乘积关系,层次过多或循环次数过大可能导致程序运行缓慢。

分支与循环综合应用:让程序解决真实问题

你已经学会了 if-else 分支、switch 多分支、for/while/do-while 循环以及循环嵌套。现在,把这些武器组合起来,就能编写出解决实际问题的程序了。就像做一道复杂的菜,你需要同时控制火候(循环重复)和调料(条件判断)。

综合应用一:猜数字游戏

计算机随机想一个1~100之间的数字,你猜,它会提示“大了”或“小了”,直到猜对为止。这里用到了:

  • srand + rand 生成随机数(需要 #include <cstdlib>#include <ctime>
  • do-while 循环保证至少猜一次
  • if-else 分支给出提示
#include <iostream>
#include <cstdlib>
#include <ctime>
using namespace std;

int main() {
    srand(time(0));                      // 随机种子
    int target = rand() % 100 + 1;       // 生成1~100的随机数
    int guess;                           // 玩家猜测的数
    int attempts = 0;                    // 猜的次数
    
    cout << "我在想一个1到100之间的数字,你来猜猜看!" << endl;
    
    do {
        cout << "请输入你的猜测:";
        cin >> guess;
        attempts++;                      // 每次猜测计数加1
        
        if (guess > target) {
            cout << "太大了!再试试。" << endl;
        } else if (guess < target) {
            cout << "太小了!再试试。" << endl;
        } else {
            cout << "恭喜你,猜对了!你一共猜了 " << attempts << " 次。" << endl;
        }
    } while (guess != target);           // 没猜对就继续
    
    return 0;
}

这个程序把 do-while 和 if-else 完美结合,每次循环都根据猜测结果输出不同提示。注意:attempts 变量记录次数,在循环内累加。

综合应用二:辗转相除法求最大公约数

数学中的欧几里得算法:两个正整数a和b,反复用大数除以小数取余,直到余数为0,这时除数就是最大公约数。

#include <iostream>
using namespace std;

int main() {
    int a, b;
    cout << "输入两个正整数:";
    cin >> a >> b;
    
    int original_a = a;  // 保存原始值用于输出
    int original_b = b;
    
    while (a % b != 0) {
        int remainder = a % b;   // 余数
        a = b;                   // 把原来的b赋给a
        b = remainder;           // 把余数赋给b
    }
    
    cout << original_a << " 和 " << original_b << " 的最大公约数是:" << b << endl;
    return 0;
}

这里用了 while 循环,因为不知道要循环多少次,只知道什么时候停止(余数为0)。循环体内进行了赋值交换,这是顺序结构的应用。

综合应用三:统计班级成绩

假设一个班有30个学生,输入他们的数学成绩,输出最高分、最低分和平均分。这需要:

  • for 循环循环30次
  • 每次输入一个分数,同时用 if 判断更新最大值和最小值
  • 累加分数最后计算平均分
#include <iostream>
using namespace std;

int main() {
    const int NUM_STUDENTS = 30;  // 学生人数
    double score;                 // 当前输入的分数
    double sum = 0;               // 总分
    double maxScore = 0;          // 最高分(初始设为0,假设分数非负)
    double minScore = 100;        // 最低分(初始设为100,假设满分100)
    
    cout << "请输入 " << NUM_STUDENTS << " 个学生的成绩(0~100):" << endl;
    
    for (int i = 1; i <= NUM_STUDENTS; i++) {
        cout << "第" << i << "个学生:";
        cin >> score;
        
        sum += score;               // 累加总分
        
        if (score > maxScore) {     // 更新最高分
            maxScore = score;
        }
        if (score < minScore) {     // 更新最低分
            minScore = score;
        }
    }
    
    double average = sum / NUM_STUDENTS;  // 平均分
    cout << "平均分:" << average << endl;
    cout << "最高分:" << maxScore << endl;
    cout << "最低分:" << minScore << endl;
    
    return 0;
}

这里 for 循环控制次数,if 分支在循环体内做判断。注意 maxScoreminScore 的初值设定要合理,否则可能无法正确记录。

新手容易犯的错误

  1. 忘记初始化累加器或计数器
    sum 没有赋初始值 0,会导致结果随机。
  2. 在循环内重置了需要保留的值
    比如把 maxScore 放在循环内每次都赋0,就永远得不到真正最大值。
  3. 逻辑条件错误
    比如猜数字中条件写成了 while (guess == target),会变成“猜对了继续”,死循环。
  4. 随机数种子只调用一次
    srand(time(0)) 应放在程序开头,如果放在循环内,会每次生成相同“随机”数(因为 time 变化慢)。

完整可运行的示例:猜数字的增强版(带有次数限制)

加一个限制:最多只能猜5次,超过则失败:

#include <iostream>
#include <cstdlib>
#include <ctime>
using namespace std;

int main() {
    srand(time(0));
    int target = rand() % 100 + 1;
    int guess;
    const int MAX_ATTEMPTS = 5;  // 最多猜5次
    
    cout << "我在想一个1~100之间的数字,你只有" << MAX_ATTEMPTS << "次机会哦!" << endl;
    
    for (int attempt = 1; attempt <= MAX_ATTEMPTS; attempt++) {
        cout << "第" << attempt << "次猜测:";
        cin >> guess;
        
        if (guess == target) {
            cout << "猜对了!你真厉害!" << endl;
            return 0;  // 直接结束程序
        } else if (guess > target) {
            cout << "太大了!" << endl;
        } else {
            cout << "太小了!" << endl;
        }
    }
    
    cout << "很遗憾,次数用完了。正确答案是:" << target << endl;
    return 0;
}

这里用了 for 循环控制次数,内部用 if-else 判断,并用 return 0 在猜对时提前退出程序(注意:在 main 函数中 return 会结束整个程序)。

相关指引

  • 想进一步学习更复杂的数据结构(如数组、字符串),可以关注后续内容。
  • 分支与循环是编程的“两板斧”,几乎所有程序都离不开它们。
  • 推荐实践项目:制作一个简易计算器、猜单词游戏、生成随机验证码等。

掌握了分支和循环,你就已经拥有了编写大部分小型程序的能力!接下来可以挑战更多有趣的算法和数据结构。

例题精讲

1单选题

以下C++程序在顺序结构下运行时,输出结果是什么? int a = 5; int b = 10; a = a + b; b = a - b; a = a - b; cout << a << " " << b;

A5 10
B10 5
C5 5
D10 10
2判断题

在顺序结构程序中,任何一个语句都可以任意调换顺序而不影响最终结果。

3填空题
请补全以下C++程序,使其实现从键盘输入两个整数,然后输出它们的和。
int main() {
    int a, b;
    cin >> a >> b;
    int sum = ___;
    cout << sum << endl;
    return 0;
}
4单选题

关于顺序结构的描述,正确的是?

A顺序结构只能包含一条语句
B顺序结构中的语句必须从上到下依次执行
C顺序结构可以包含循环和分支
D顺序结构中的语句可以部分跳过
5判断题

以下程序段是顺序结构的典型例子: int x = 1; x = x + 2; x = x * 3; cout << x;