第2节:程序逻辑与控制流——让程序“思考”

引言:从"听话"到"会思考"

欢迎回来!上一节课,我们让程序学会了"说话"------它能打印出Hello, World!,还能做简单的数学题。但你不觉得它有点"死脑筋"吗?我们让它算1+1,它绝不会给你算2+2。它就像一个刚出生的婴儿,你喂它什么,它就吃什么。

今天,我们要给这个婴儿装上大脑 ,让它学会自己做决定重复做事情

  • 做决定:比如,"如果今天下雨,我就带伞;否则,我就不带。" 这在我们生活中无处不在。
  • 重复做事 :比如,老师让你把"我错了"抄写100遍。你肯定不会傻傻地写100行printf,你会想:"有没有办法让电脑自己重复100次?"

在编程里,我们管这两种能力叫 "流程控制" 。掌握了它,你的程序就从"计算器"升级成了"自动机器人"!这对于我们未来分析病毒和漏洞至关重要,因为恶意软件的行为就是由无数个判断和循环构成的。

第一部分:程序的"比较心"------运算符详解

想让程序会判断,首先得教会它"比较"。这就需要用到运算符。

1. 算术运算符:老朋友,新规矩

这些你在Python里都见过,但C语言有点"小气"。

运算符 作用 例子 (C语言) 和Python的差异
+ a + b 一样
- a - b 一样
* a * b 一样
/ a / b 注意! 5 / 2 结果是 2,不是2.5!因为两个整数相除,结果还是整数,小数部分直接被丢弃(不是四舍五入)。
% 取模(求余数) 5 % 2 结果是 1 一样

重点吐槽:C语言没有幂运算符!

在Python里,你可以轻松地写 2**3 来计算2的3次方。在C语言里?没这好事! 你得用 pow(2, 3) 这个函数,而且记得要在开头 #include <math.h>

底层原理小贴士: 为什么 5 / 2 等于2?因为CPU有专门的整数运算单元,做整数除法非常快。如果要得到小数结果 2.5,你必须至少让其中一个数变成小数形式,比如 5.0 / 25 / 2.0。这体现了C语言"贴近硬件"的特性,它默认使用最高效的方式。

2. 关系运算符:比比谁大谁小

这些运算符用来比较两个值,结果是"真"或"假"。在C语言中,"真"用数字 1 表示,"假"用数字 0 表示。

运算符 含义 例子
== 等于 5 == 3 结果是 0 (假)
!= 不等于 5 != 3 结果是 1 (真)
> 大于 5 > 3 结果是 1 (真)
< 小于 5 < 3 结果是 0 (假)
>= 大于等于 5 >= 5 结果是 1 (真)
<= 小于等于 5 <= 3 结果是 0 (假)

血泪教训:=== 是天壤之别!

  • =赋值 ,比如 a = 5; 意思是"把5放进变量a里"。
  • ==比较 ,比如 a == 5 意思是"看看变量a的值是不是等于5"。
  • 如果你在if条件里错写成 if (a = 5),编译器可能不会报错,但这行代码的意思是"把5赋给a,然后判断a的值(5)是否为真(真)",结果这个if永远都会执行!这是C程序员最常犯的错误之一。

3. 逻辑运算符:处理复杂条件

当需要同时满足多个条件时,就用它们。

运算符 含义 例子 和Python的差异
&& 逻辑与 (and) (a > 0) && (a < 10) // a大于0 并且 a小于10 Python用关键字 and
` ` 逻辑或 (or)
! 逻辑非 (not) !(a == 0) // a 等于0 Python用关键字 not

记忆技巧: && 像两根绳子拴在一起,必须都满足。|| 像两条岔路,满足一条就行。

第二部分:程序的"十字路口"------条件分支语句

现在,我们让程序根据比较的结果,走不同的路。

1. if 语句:如果...就...

这是最简单的判断。

c 复制代码
if (条件) {
    // 如果条件为真,就执行这里面的代码
}

例子:

c 复制代码
int score = 95;
if (score >= 60) {
    printf("恭喜,你及格了!\n");
}

2. if-else 语句:如果...就...否则...

二选一。

c 复制代码
if (条件) {
    // 条件为真,执行这里
} else {
    // 条件为假,执行这里
}

例子:

c 复制代码
int age = 16;
if (age >= 18) {
    printf("你可以进入网吧。\n");
} else {
    printf("未成年人禁止入内!\n"); // 这行会被执行
}

3. else-if 结构:多岔路口

用于多种可能性的判断。

c 复制代码
int score = 85;
if (score >= 90) {
    printf("优秀!\n");
} else if (score >= 80) {
    printf("良好!\n"); // 这行会被执行
} else if (score >= 70) {
    printf("中等!\n");
} else if (score >= 60) {
    printf("及格!\n");
} else {
    printf("不及格,要加油了!\n");
}

执行流程: 程序会从上到下逐个判断条件,一旦某个条件为真,就执行对应的代码块,然后直接跳过 后面所有的 else-ifelse

4. switch-case 语句:精确匹配

当你的判断是基于一个变量精确等于某个值 时,用 switch 更清晰。

c 复制代码
int day = 3;
switch (day) {
    case 1:
        printf("星期一\n");
        break; // 记住这个break!
    case 2:
        printf("星期二\n");
        break;
    case 3:
        printf("星期三\n"); // 这行会被执行
        break;
    default: // 如果所有case都不匹配,就执行default
        printf("无效的天数\n");
        break;
}

break的重要性: break 的作用是跳出整个 switch 语句 。如果没有 break,程序会从匹配到的那个 case 开始,一直执行下去,直到遇到 break 或者 switch 结束!这叫做"case穿透"。(虽然有时故意用它来实现高级功能,但新手务必每个case都加上break)。

底层原理小贴士: 为什么有了if-else还要switch?因为switch在底层实现上,编译器有时会为它生成一种叫跳转表 的机制。想象成一个电梯,switch(变量)直接把你送到对应的楼层(case),非常高效。而一长串的if-else-if则像爬楼梯,需要一层一层地判断。在处理大量分支时,switch性能通常更好。

第三部分:程序的"永动机"------循环语句

现在,我们来解决"抄写100遍"的问题。

1. while 循环:只要...就继续...

先检查条件,再决定是否执行循环体。

c 复制代码
while (条件) {
    // 只要条件为真,就重复执行这里的代码
}

例子:打印1到10

c 复制代码
int i = 1; // 1. 初始化计数器
while (i <= 10) { // 2. 循环条件
    printf("%d\n", i);
    i++; // 3. 更新计数器 (i++ 相当于 i = i + 1)
}

注意: 如果你忘了写 i++i 的值永远不变,条件 i <= 10 就永远为真,循环会永远执行下去,这叫 死循环 。在控制台里,你可以按 Ctrl+C 来强行终止它。

2. do-while 循环:先干再说...

先执行一次循环体,再检查条件。

c 复制代码
do {
    // 先执行这里的代码...
} while (条件); // ...然后看条件是否为真,为真就再执行一次

它与 while 的最大区别: do-while 至少会执行一次循环体,而 while 可能一次都不执行。

例子:让用户输入密码,直到正确为止

c 复制代码
int password;
int correct_password = 123456;
do {
    printf("请输入密码:");
    scanf("%d", &password);
} while (password != correct_password);
printf("登录成功!\n");

3. for 循环:全能王

for 循环把循环三要素(初始化、条件、更新)都写在了一行,结构非常清晰,是最常用的循环。

c 复制代码
for (初始化; 循环条件; 更新) {
    // 循环体
}

例子:打印1到10 (for循环版)

c 复制代码
for (int i = 1; i <= 10; i++) {
    printf("%d\n", i);
}

执行顺序:

  1. int i = 1; (初始化,只执行一次)
  2. i <= 10; (判断条件,若为真,进入循环体;若为假,结束循环)
  3. 执行 printf("%d\n", i);
  4. i++ (更新计数器)
  5. 跳回第2步,继续判断...

for循环的底层视角: 你可以把for循环看作是while循环的"语法糖"。编译器最终会把for循环翻译成类似while循环的底层指令。但它把循环控制逻辑封装得更好,使得代码更易读、更不易出错(比如,不容易忘记写计数器更新)。

4. 循环里的两个"叛徒":breakcontinue

  • break立刻终止整个循环,直接跳出来。就像在游戏中接到了"立刻撤退"的命令,不管任务完成没有,马上就走。
  • continue跳过 本次循环中 continue 之后的代码,直接进入下一次循环。就像体育课上老师让你"跳过这个动作,做下一个"。

例子:

c 复制代码
// break 例子:找到第一个能被3整除的数就停止
for (int i = 1; i <= 10; i++) {
    if (i % 3 == 0) {
        printf("找到了:%d\n", i);
        break; // 找到6后,立刻结束循环,7、8、9、10就不会被检查了
    }
}

// continue 例子:打印1-10中所有的奇数
for (int i = 1; i <= 10; i++) {
    if (i % 2 == 0) { // 如果是偶数
        continue; // 跳过下面的printf,直接进行i++
    }
    printf("%d 是奇数\n", i); // 只有奇数会执行到这里
}
第四部分:实战演练------思维体操

光说不练假把式,我们来两个经典的练习,把今天学的知识全部用上。

实战一:猜数字游戏

游戏规则: 程序随机生成一个1-100的数字,玩家来猜。程序会根据玩家猜的数字,提示"大了"或"小了",直到猜中为止,并告诉玩家猜了多少次。

代码实现:

c 复制代码
#include <stdio.h>
#include <stdlib.h> // 为了用rand()和srand()
#include <time.h>   // 为了用time()

int main() {
    // 1. 生成随机数种子,这样每次运行的随机数才不一样
    srand(time(NULL));
    // 2. 生成1-100的随机数
    int secret_number = rand() % 100 + 1;
    int guess;
    int count = 0; // 计数器

    printf("欢迎来到猜数字游戏!我已经想了一个1-100之间的数字。\n");

    do {
        printf("请输入你的猜测:");
        scanf("%d", &guess);
        count++; // 猜的次数+1

        if (guess > secret_number) {
            printf("太大了!\n");
        } else if (guess < secret_number) {
            printf("太小了!\n");
        } else {
            printf("太棒了!你猜对了!就是 %d!\n", secret_number);
            printf("你一共猜了 %d 次。\n", count);
        }
    } while (guess != secret_number); // 只要没猜对,就继续循环

    return 0;
}

这个程序综合运用了: do-while循环、if-else-if分支、运算符、变量和输入输出。好好体会它的逻辑流程!

实战二:计算斐波那契数列的前N项

数列规则: 这个数列从0和1开始,后面的每一项都是前两项之和。像这样:0, 1, 1, 2, 3, 5, 8, 13, 21...

代码实现:

c 复制代码
#include <stdio.h>

int main() {
    int n;
    printf("请输入要生成斐波那契数列的前几项:");
    scanf("%d", &n);

    if (n <= 0) {
        printf("请输入一个正整数。\n");
    } else {
        printf("斐波那契数列前 %d 项为:\n", n);

        long long a = 0, b = 1, next; // 用long long防止数字太大溢出

        for (int i = 1; i <= n; i++) {
            if (i == 1) {
                printf("%lld ", a); // 第一项是0
            } else if (i == 2) {
                printf("%lld ", b); // 第二项是1
            } else {
                next = a + b;
                printf("%lld ", next);
                a = b; // 更新a和b,为计算下一项做准备
                b = next;
            }
        }
        printf("\n");
    }
    return 0;
}

这个程序综合运用了: for循环、if-else-if分支、变量的更新。它展示了如何用循环来生成一个序列,并处理了边界情况(前两项)。

总结与展望

恭喜你!经过这一节课的学习,你的程序已经"活"过来了。它不再只是机械地执行指令,而是学会了根据情况做决策,并能不知疲倦地重复劳动。

  • 运算符是程序进行比较和逻辑判断的工具。
  • if-elseswitch 让程序有了选择的能力。
  • while , do-while , for 让程序能够自动化地处理重复性任务。
  • breakcontinue 让你能更精细地控制循环的流程。

所有这些,都是构建复杂程序的基石。一个病毒扫描程序,就是通过无数个循环和判断,来检查文件是否匹配病毒特征。一个网络爬虫,也是通过循环来不断地抓取网页。

在下一节课,我们将学习函数------一种能将复杂任务分解成多个小任务的"魔法",这将让我们的代码变得井井有条,威力倍增。旅程越来越有趣了,加油!

相关推荐
hixiong1232 小时前
C# OpenCVSharp使用 读光-票证检测矫正模型
人工智能·opencv·c#
敲代码的瓦龙2 小时前
操作系统?进程!!!
linux·c++·操作系统
lly2024062 小时前
Go 语言接口
开发语言
霜绛2 小时前
C#知识补充(二)——命名空间、泛型、委托和事件
开发语言·学习·unity·c#
大千AI助手2 小时前
HotpotQA:推动多跳推理问答发展的标杆数据集
人工智能·神经网络·llm·qa·大千ai助手·hotpotqa·多跳推理能力
红尘炼丹客2 小时前
《DeepSeek-OCR: Contexts Optical Compression》速览
人工智能·python·自然语言处理·ocr
TiAmo zhang2 小时前
现代C++的AI革命:C++20/C++23核心特性解析与实战应用
c++·人工智能·c++20
Dxxyyyy2 小时前
零基础学JAVA--Day26(枚举类)
java·开发语言
好望角雾眠2 小时前
第四阶段C#通讯开发-6:Socket之UDP
开发语言·笔记·学习·udp·c#