C: 实战:入门综合练习
学编程就像学游泳——看再多教材不如下水练。这节课把前面9课的知识串起来,动手写3个完整的小程序。
1. 项目一:摄氏度转华氏度
这个项目综合运用变量、算术运算、输入输出。公式为:
C
F = C × 9 / 5 + 32
(1) 需求分析
- 输入:摄氏温度(可以是小数)
- 输出:对应的华氏温度,保留1位小数
- 扩展:同时输出开尔文温度(K = C + 273.15)
(2) 关键知识点
double类型存储浮点数scanf("%lf")读取双精度浮点数printf("%.1f")控制小数位数- 算术运算符的优先级
▶ 示例
C
#include <stdio.h>
int main(void) {
double celsius;
printf("请输入摄氏温度: ");
scanf("%lf", &celsius);
double fahrenheit = celsius * 9.0 / 5.0 + 32.0;
double kelvin = celsius + 273.15;
printf("\n===== 温度转换结果 =====\n");
printf("摄氏度: %.2f°C\n", celsius);
printf("华氏度: %.2f°F\n", fahrenheit);
printf("开尔文: %.2fK\n", kelvin);
printf("========================\n");
return 0;
}
TEXT
📖 仅展示
请输入摄氏温度: 36.5
===== 温度转换结果 =====
摄氏度: 36.50°C
华氏度: 97.70°F
开尔文: 309.65K
========================
💡 写
9.0 / 5.0 而不是 9 / 5,因为整数除法 9/5 结果是1,不是1.8,会导致结果错误。
(3) 常见错误
- 整数除法:
celsius * 9 / 5中9/5截断为1 → 写成9.0/5.0 scanf用%f读取double:double必须用%lf,printf输出double用%f即可- 忘记
&:scanf("%lf", celsius)会崩溃 →scanf("%lf", &celsius)
(4) 扩展挑战
能不能反过来——输入华氏度,输出摄氏度?公式为 C = (F - 32) × 5 / 9。
2. 项目二:判断闰年
这个项目综合运用条件判断、逻辑运算符、取余运算。
(1) 闰年规则
- 能被4整除但不能被100整除 → 闰年
- 能被400整除 → 也是闰年
- 其他 → 平年
用逻辑表达式写就是:
C
(year % 4 == 0 && year % 100 != 0) || (year % 400 == 0)
(2) 需求分析
- 输入:一个正整数表示年份
- 输出:该年是闰年还是平年,以及2月的天数
- 防御:处理非法输入(负数或0)
(3) 关键知识点
- 取余
%判断整除 - 逻辑运算符
&&、||组合条件 if-else if-else多分支- 输入合法性验证
▶ 示例
C
#include <stdio.h>
int main(void) {
int year;
printf("请输入年份: ");
scanf("%d", &year);
if (year <= 0) {
printf("错误:年份必须为正整数\n");
return 1;
}
int is_leap = (year % 4 == 0 && year % 100 != 0) || (year % 400 == 0);
int feb_days = is_leap ? 29 : 28;
printf("\n===== 判断结果 =====\n");
printf("年份: %d\n", year);
printf("类型: %s\n", is_leap ? "闰年" : "平年");
printf("2月天数: %d天\n", feb_days);
printf("====================\n");
return 0;
}
TEXT
📖 仅展示
请输入年份: 2000
===== 判断结果 =====
年份: 2000
类型: 闰年
2月天数: 29天
====================
再测试几个边界年份:
| 年份 | 预期结果 | 原因 |
|---|---|---|
| 2000 | 闰年 | 能被400整除 |
| 1900 | 平年 | 能被100整除但不能被400整除 |
| 2024 | 闰年 | 能被4整除但不能被100整除 |
| 2023 | 平年 | 不能被4整除 |
(4) 逐步推导
初学者常搞错闰年条件,让我们一步步推导:
- 第一步:能被4整除 → 大概率是闰年
- 第二步:但能被100整除的"世纪年"通常不是闰年 → 附加条件"且不能被100整除"
- 第三步:但能被400整除的世纪年又是闰年 → 附加条件"或能被400整除"
💡 逐步推导比死记公式更可靠。遇到复杂条件,先写简单版本,再逐步添加修正。
3. 项目三:简易计算器
这个项目综合运用 switch-case、循环、输入输出、算术运算。
(1) 需求分析
- 输入:两个数字和一个运算符(+ - * /)
- 输出:计算结果
- 防御:除数为0时给出提示
- 循环:计算完一次后询问是否继续
(2) 关键知识点
switch-case处理运算符do-while实现重复计算- 除零检查
- 格式化输出对齐
continue跳过无效操作
▶ 示例
C
#include <stdio.h>
int main(void) {
double a, b;
char op;
char again;
do {
printf("\n===== 简易计算器 =====\n");
printf("请输入表达式(如 3 + 5): ");
scanf("%lf %c %lf", &a, &op, &b);
printf("--------------------\n");
switch (op) {
case '+':
printf("%.2f + %.2f = %.2f\n", a, b, a + b);
break;
case '-':
printf("%.2f - %.2f = %.2f\n", a, b, a - b);
break;
case '*':
printf("%.2f * %.2f = %.2f\n", a, b, a * b);
break;
case '/':
if (b == 0) {
printf("错误:除数不能为零!\n");
} else {
printf("%.2f / %.2f = %.2f\n", a, b, a / b);
}
break;
default:
printf("错误:不支持的运算符 '%c'\n", op);
break;
}
printf("--------------------\n");
printf("继续计算?(Y/N): ");
scanf(" %c", &again);
} while (again == 'Y' || again == 'y');
printf("再见!\n");
return 0;
}
TEXT
📖 仅展示
===== 简易计算器 =====
请输入表达式(如 3 + 5): 10 / 3
--------------------
10.00 / 3.00 = 3.33
--------------------
继续计算?(Y/N): Y
===== 简易计算器 =====
请输入表达式(如 3 + 5): 5 / 0
--------------------
错误:除数不能为零!
--------------------
继续计算?(Y/N): N
再见!
(3) 设计要点
- 输入格式:
scanf("%lf %c %lf", &a, &op, &b)一次读取三个值,空格分隔,简洁自然 - 除零保护:在
case '/'中先检查b == 0,避免运行时错误 - 循环控制:
do-while保证至少计算一次,用户选择是否继续 - 缓冲区处理:
scanf(" %c", &again)中%c前的空格跳过前次输入的残留回车
(4) 扩展挑战
给计算器添加取余运算 %(注意操作数需要是整数),以及幂运算提示(math.h 的 pow 函数)。
4. 综合知识回顾
这3个项目覆盖了前9课的核心知识:
| 项目 | 涉及知识点 |
|---|---|
| 温度转换 | 变量与类型、算术运算、printf格式化、scanf输入、整数除法陷阱 |
| 判断闰年 | 取余运算、关系运算符、逻辑运算符、if-else、条件运算符、输入验证 |
| 简易计算器 | switch-case、do-while循环、continue、缓冲区处理、除零检查 |
(1) 写好程序的通用步骤
- 理解需求:输入什么?输出什么?边界情况有哪些?
- 选择结构:用什么语句实现?if还是switch?for还是while?
- 写伪代码:先用自然语言描述逻辑,再翻译成C
- 编码实现:边写边测试,不要一次性写完再调试
- 测试验证:正常值、边界值、非法值都要测试
❓ 常见问题
Q 为什么
scanf 读 double 要用 %lf 而 printf 输出用 %f?A
scanf 需要知道参数的精确大小来正确写入内存,double 和 float 大小不同;printf 中 float 会被自动提升为 double,所以 %f 两者通用。Q 判断闰年用一条逻辑表达式好还是用嵌套if好?
A 逻辑表达式更紧凑,适合简单条件;嵌套if更易读,适合复杂条件。初学者建议先写嵌套if理解逻辑,再简化为逻辑表达式。
Q 计算器中浮点数比较
b == 0 可靠吗?A 严格来说浮点数不应该用
== 比较,但用户直接输入0时精确为0.0是可靠的。更严谨的做法是 fabs(b) < 1e-10,需要 math.h。Q 程序写到一半就错了,怎么调试?
A 在关键位置加
printf 输出中间变量值,逐步缩小错误范围。这叫"打印调试法",是最基本也最有效的调试手段。📖 小节
- 动手写完整程序是掌握C语言最快的方式,光看不练学不会
- 整数除法是浮点运算中最常见的坑,注意至少一个操作数写成小数形式
- 复杂条件要逐步推导:先写基础规则,再逐条添加修正条件
- switch-case 配合 do-while 是交互式菜单的经典模式
- 写程序的通用流程:理解需求 → 选结构 → 写伪代码 → 编码 → 测试
📝 作业
- 给温度转换程序添加反向功能:输入1选择摄氏转华氏,输入2选择华氏转摄氏,用 switch 或 if-else 实现。
- 改进闰年判断程序,输入起始年和结束年,输出该范围内所有闰年(用 for 循环遍历)。
- 给简易计算器添加取余运算
%和整数除法功能,注意取余要求操作数为整数,提示用户输入整数。