一、本节学习定位
本节内容是对上一节知识的回顾与方法总结,重点不是新增复杂语法,而是明确 C 语言学习中的一个核心问题:程序不是单纯由语法堆砌而成,程序设计首先依赖算法思路,其次才是用 C 语言语法表达算法。
在 C 语言入门阶段,很多题目看起来只是简单的数字处理,例如:
-
对三个数排序;
-
交换两个变量的值;
-
判断条件后执行不同语句;
-
按一定流程修改变量。
这些题目虽然代码不长,但都需要先明确算法步骤。如果算法没有想清楚,直接动手写代码,往往很难写出正确程序。
二、程序设计的核心:算法优先
1. 程序设计的基本认识
从学习角度看,一个程序可以理解为:
程序 = 算法 + 可执行的程序语言表达
其中,算法 是解决问题的步骤和方法,C 语言是表达算法的工具。
也就是说,写程序时不能只关注语法是否会写,还要先解决以下问题:
-
题目要解决什么问题;
-
输入数据是什么;
-
输出结果是什么;
-
中间需要经过哪些处理步骤;
-
每一步之间的先后顺序是什么;
-
是否需要判断、循环、交换、排序等操作。
如果没有清晰的解题思路,通常不应急着写代码。
三、例 1:两个变量的值互换
1. 问题描述
给定两个变量 a 和 b,要求交换它们的值。
例如:
交换前:a = 3, b = 5
交换后:a = 5, b = 3
2. 错误交换方式
初学者容易写出如下代码:
a = b;
b = a;
这段代码是错误的。原因是执行第一句后,a 的原值已经丢失。
假设初始值为:
a = 3, b = 5
执行过程如下:
| 步骤 | 语句 | a 的值 | b 的值 | 说明 |
|---|---|---|---|---|
| 初始 | - | 3 | 5 | 原始数据 |
| 第 1 步 | a = b; |
5 | 5 | a 的原值 3 丢失 |
| 第 2 步 | b = a; |
5 | 5 | b 仍然得到 5 |
最终结果不是交换,而是两个变量都变成了 b 的原值。
3. 正确交换方式:借助第三个变量
交换两个变量时,必须先用第三个变量保存其中一个变量的原值。
int t;
t = a;
a = b;
b = t;
这三句代码应当熟练掌握,因为变量交换在排序、数组处理和算法题中经常使用。
4. 完整示例程序
#include <stdio.h>
int main(void)
{
int a;
int b;
int t;
printf("请输入两个整数:");
scanf("%d%d", &a, &b);
printf("交换前:a = %d, b = %d\n", a, b);
t = a; // 第一步:保存 a 的原值
a = b; // 第二步:把 b 的值赋给 a
b = t; // 第三步:把原来 a 的值赋给 b
printf("交换后:a = %d, b = %d\n", a, b);
return 0;
}
5. 程序执行过程分析
假设输入:
3 5
变量变化如下:
| 步骤 | 执行语句 | a | b | t | 说明 |
|---|---|---|---|---|---|
| 初始 | 输入后 | 3 | 5 | 未确定 | a 和 b 保存输入值 |
| 第 1 步 | t = a; |
3 | 5 | 3 | 用 t 保存 a 的原值 |
| 第 2 步 | a = b; |
5 | 5 | 3 | 将 b 的值赋给 a |
| 第 3 步 | b = t; |
5 | 3 | 3 | 将原来 a 的值赋给 b |
最终实现交换:
a = 5, b = 3
四、例 2:对三个整数从小到大排序
1. 问题描述
输入任意三个整数 a、b、c,要求按照从小到大的顺序输出。
例如:
输入:8 3 5
输出:3 5 8
这个问题的关键不是 printf 或 scanf,而是要先明确排序算法。
2. 基本算法思路
可以通过多次比较和交换完成排序:
-
如果
a > b,交换a和b,保证a <= b; -
如果
a > c,交换a和c,保证a是三个数中较小的; -
如果
b > c,交换b和c,保证b <= c; -
最终得到
a <= b <= c。
3. 完整示例程序
#include <stdio.h>
int main(void)
{
int a;
int b;
int c;
int t;
printf("请输入三个整数:");
scanf("%d%d%d", &a, &b, &c);
if (a > b)
{
t = a;
a = b;
b = t;
}
if (a > c)
{
t = a;
a = c;
c = t;
}
if (b > c)
{
t = b;
b = c;
c = t;
}
printf("从小到大排序结果:%d %d %d\n", a, b, c);
return 0;
}
4. 程序讲解
| 代码片段 | 功能 |
|---|---|
scanf("%d%d%d", &a, &b, &c); |
输入三个整数 |
if (a > b) |
判断 a 和 b 是否逆序 |
t = a; a = b; b = t; |
交换两个变量的值 |
if (a > c) |
保证 a 不大于 c |
if (b > c) |
保证 b 不大于 c |
printf(...) |
输出排序后的结果 |
5. 示例跟踪
输入:
8 3 5
执行过程:
| 步骤 | a | b | c | 说明 |
|---|---|---|---|---|
| 初始 | 8 | 3 | 5 | 输入原始数据 |
判断 a > b |
3 | 8 | 5 | 8 > 3,交换 a 和 b |
判断 a > c |
3 | 8 | 5 | 3 > 5 不成立,不交换 |
判断 b > c |
3 | 5 | 8 | 8 > 5,交换 b 和 c |
最终输出:
3 5 8
五、看懂程序的三步法
看懂程序和掌握程序不是同一个概念。看懂程序是掌握程序的前提,但仅仅看懂还不等于能够独立写出程序。
看懂一个程序,可以按三步进行。
1. 第一步:看流程
流程是指程序中语句的执行顺序,即先执行哪一句,后执行哪一句。
例如:
if (a > b)
{
t = a;
a = b;
b = t;
}
阅读这段程序时,应先明确流程:
-
先判断
a > b是否成立; -
如果条件成立,执行花括号中的三条交换语句;
-
如果条件不成立,跳过花括号中的语句;
-
程序继续执行后面的代码。
如果不清楚程序流程,就无法真正理解程序。
2. 第二步:看每条语句的功能
知道执行顺序之后,还要理解每条语句的具体作用。
例如:
t = a;
a = b;
b = t;
这三条语句不能只看作普通赋值,而要理解其功能:
| 语句 | 功能 |
|---|---|
t = a; |
保存 a 的原值 |
a = b; |
把 b 的值赋给 a |
b = t; |
把原来 a 的值赋给 b |
其中,= 是赋值运算符,表示把右边表达式的值赋给左边变量。
3. 第三步:代入数据试运行
如果仍然不理解程序,可以选择一组具体数据,逐句跟踪变量变化。
例如对三个数排序程序,可以代入:
a = 8, b = 3, c = 5
然后逐句分析每个 if 是否成立,以及变量值如何变化。通过代入数据,可以把抽象代码转化为具体过程,更容易发现程序逻辑。
六、看懂程序与掌握程序的区别
| 对比项 | 看懂程序 | 掌握程序 |
|---|---|---|
| 核心目标 | 明白程序为什么这样写 | 能够独立写出并调试程序 |
| 主要方式 | 阅读、分析、代入数据 | 修改、敲写、调试、复现 |
| 判断标准 | 能解释每条语句的作用 | 不看答案也能写出正确代码 |
| 常见问题 | 以为看懂就会写 | 实际敲代码时仍然出错 |
| 正确做法 | 先理解流程和语句功能 | 再通过多次练习形成熟练度 |
结论:看懂只是第一步,真正掌握必须经过实际敲代码和调试。
七、掌握一个小算法程序的六步法
对于涉及算法的小程序,建议按以下步骤学习。
1. 尝试独立解决
拿到题目后,先自己分析:
-
输入是什么;
-
输出是什么;
-
是否需要比较;
-
是否需要交换;
-
是否需要循环;
-
是否需要辅助变量;
-
程序流程如何安排。
如果能够独立写出程序,说明算法思路比较清晰。
2. 无法解决时查看答案
如果程序涉及算法,而自己短时间内没有思路,不必长时间死磕。此时可以查看参考答案。
重点不是抄答案,而是理解:
-
答案为什么这样设计;
-
每个变量起什么作用;
-
每个判断条件为什么这样写;
-
每次交换、赋值、循环的目的是什么;
-
代码执行后变量如何变化。
3. 把答案看懂
看答案时应按"三步法"分析:
-
看程序流程;
-
看每条语句的功能;
-
代入具体数据试运行。
例如两数交换程序,不仅要记住:
t = a;
a = b;
b = t;
还要明白为什么必须先执行 t = a;。
4. 尝试修改程序并观察结果
看懂答案后,不应马上闭着眼睛默写,而应尝试修改代码,观察输出变化。
例如可以修改排序程序中的条件:
if (a > b)
改为:
if (a >= b)
然后观察当两个数相等时,程序是否仍然正确。
也可以尝试去掉花括号:
if (a > b)
t = a;
a = b;
b = t;
这段代码看起来相似,但实际上只有 t = a; 受 if 控制,后两句会无条件执行,因此逻辑会出错。
5. 照着答案敲写并调试
理解答案后,要亲自敲一遍代码。
实际敲代码时可能出现:
-
拼写错误;
-
分号遗漏;
-
花括号不匹配;
-
scanf中少写&; -
条件判断写错;
-
变量名写错;
-
输出格式不匹配。
调试错误是学习 C 语言不可缺少的过程。程序能运行,不代表过程没有意义;程序出错时,正是理解语法细节和程序流程的机会。
6. 不看答案独立复现
最后一步是不看答案,独立把程序写出来。
如果当天能写出,说明已经初步掌握;但还需要隔几天再次练习。第一次复现通常最困难,第二次会明显轻松,后续通过复习逐步形成稳定记忆。
八、极少数无法理解的程序如何处理
如果某个程序经过分析、代入数据、修改实验和调试后,仍然无法完全理解,可以先记住其基本结构,后续学习更多语法和算法后再回头理解。
但这种情况不应太多。对于入门阶段的大多数程序,只要按以下顺序处理,通常都可以理解:
-
理清流程;
-
理解语句功能;
-
代入数据;
-
修改验证;
-
敲写调试;
-
独立复现。
九、在 VSCode 中练习本节代码的建议
使用 VSCode 配置好 C/C++ 环境后,可以按以下流程练习本节程序。
1. 新建 C 源文件
建议文件名:
swap.c
或:
sort_three_numbers.c
2. 编写代码
将示例代码复制到 .c 文件中,注意文件扩展名必须是 .c。
3. 使用终端编译
Windows 下,如果使用 GCC,可在 VSCode 终端中执行:
gcc swap.c -o swap.exe
或者:
gcc sort_three_numbers.c -o sort_three_numbers.exe
4. 运行程序
./swap.exe
或者:
./sort_three_numbers.exe
5. 修改程序并重新运行
建议尝试:
-
修改输入数据;
-
修改
if条件; -
故意去掉花括号,观察逻辑错误;
-
故意漏写
&,观察scanf的错误; -
调换交换语句顺序,观察变量值变化。
这种练习方式可以帮助理解"看懂"和"掌握"的区别。
十、本节要点总结
-
C 语言程序设计不能只学语法,更要先有算法思路。
-
对三个数排序、两个数交换等题目,核心都在于先明确处理步骤。
-
两个变量交换必须借助第三个变量,典型写法是:
t = a;
a = b;
b = t; -
看懂程序可分为三步:看流程、看语句功能、代入数据试运行。
-
看懂程序不等于掌握程序,掌握程序还需要修改、敲写、调试和独立复现。
-
学习小算法程序时,不必长时间盲目死磕;如果没有思路,应通过可靠答案学习算法。
-
调试错误不是浪费时间,而是加深理解的重要环节。
-
程序需要隔几天重复练习,才能真正形成稳定掌握。
参考出处
-
《C程序设计(第五版)》谭浩强,第 3 章"最简单的 C 程序设计------顺序程序设计"
-
《C程序设计(第五版)》谭浩强,第 4 章"选择结构程序设计"
-
郝斌《C语言自学入门教程》对应内容:算法意识、两数交换、三数排序、程序阅读方法与程序掌握方法。