本章所有代码都能直接编译运行。每行后面的
//注释解释这一行在干什么,照着敲一遍,比看十遍强。
输入格式按代码里的 scanf 来:有的用空格分隔,有的用逗号分隔,注释里都标了。
一、知识点代码
c
// ============ 1. if 单分支:求绝对值 ============
#include <stdio.h> // 包含输入输出头文件,才能用 scanf 和 printf
int main() // 主函数,程序从这里开始
{ // 主函数体开始
int x; // 定义整型变量 x,用来存放输入的数
scanf("%d", &x); // 从键盘读一个整数放进 x,& 表示取地址
if (x < 0) // 单分支:如果 x 小于 0,路牌为"真"
x = -x; // 真就走这一句:把 x 变成相反数
printf("%d\n", x); // 输出 x,%d 表示按整数输出
return 0; // 程序正常结束,向系统返回 0
} // 主函数体结束c
// ============ 2. if-else 双分支:判断奇数偶数 ============
#include <stdio.h> // 输入输出头文件
int main() // 主函数入口
{ // 函数体开始
int n; // 定义整型变量 n
scanf("%d", &n); // 读入一个整数
if (n % 2 == 0) // 条件:n 除以 2 的余数等于 0,即偶数
printf("even\n"); // 条件为真,走 if 这一支
else // 否则(余数不为 0)
printf("odd\n"); // 走 else 这一支
return 0; // 结束
} // 函数体结束c
// ============ 3. 多分支 if-else if:成绩分档 ============
#include <stdio.h> // 输入输出头文件
int main() // 主函数入口
{ // 函数体开始
int score; // 定义整型变量 score 存分数
scanf("%d", &score); // 读入分数
if (score >= 90) // 第一个路牌:90 分及以上
printf("A\n"); // 走 A
else if (score >= 80) // 否则再问:80 分及以上(此时必然小于 90)
printf("B\n"); // 走 B
else if (score >= 70) // 再问:70 分及以上
printf("C\n"); // 走 C
else if (score >= 60) // 再问:60 分及以上
printf("D\n"); // 走 D
else // 剩下的都不到 60
printf("E\n"); // 走 E
return 0; // 结束
} // 函数体结束c
// ============ 4. 关系、逻辑表达式与短路求值 ============
#include <stdio.h> // 输入输出头文件
int main() // 主函数入口
{ // 函数体开始
int a = 3, b = 2, c = 1; // 定义并初始化三个整数
int m = 1, n = 1; // m、n 用来观察短路,初值都设为 1
printf("%d\n", a > b); // 3>2 为真,关系表达式的值是 1
printf("%d\n", a > b > c); // 自左至右:(3>2)>1 即 1>1,值为 0
printf("%d\n", a && b); // 两个都非 0,逻辑与为真,值为 1
printf("%d\n", !a); // a 非 0 为真,取非得假,值为 0
printf("%d\n", 0 < a < 10); // 数学写法在 C 里恒真:(0<3)<10 即 1<10,值为 1
(m = a < b) && (n = c > b); // 左边 3<2 为假(0),&& 短路,右边不执行
printf("%d %d\n", m, n); // 所以 m 变成 0,n 仍是原来的 1
return 0; // 结束
} // 函数体结束c
// ============ 5. 条件运算符 ? : ============
#include <stdio.h> // 输入输出头文件
int main() // 主函数入口
{ // 函数体开始
int a, b, max; // 定义两个输入数和一个最大值
scanf("%d%d", &a, &b); // 两个整数用空格隔开输入
max = (a > b) ? a : b; // 条件表达式:a>b 为真取 a,否则取 b
printf("max=%d\n", max); // 输出较大值
printf("%d\n", (a > b) ? a - b : b - a); // 条件表达式也可以直接参与运算
return 0; // 结束
} // 函数体结束c
// ============ 6. 嵌套 if 与悬空 else ============
#include <stdio.h> // 输入输出头文件
int main() // 主函数入口
{ // 函数体开始
int x = 0, y = 1; // 定义并初始化两个整数
if (x > 0) // 外层 if:x 大于 0 吗?
if (y > 0) printf("A\n"); // 内层 if:y 大于 0 吗?
else printf("B\n"); // 这个 else 配内层 if(离它最近且未配对)
printf("----\n"); // 打印一条分隔线
if (x > 0) // 同样的问题,这次用花括号限定范围
{ // 外层 if 的复合语句开始
if (y > 0) printf("C\n"); // 内层 if 单独成一个块
} // 外层 if 的复合语句结束
else // 这个 else 配外层 if
printf("D\n"); // 外层条件不成立时走这里
return 0; // 结束
} // 函数体结束c
// ============ 7. switch 基本用法:等级转分数段 ============
#include <stdio.h> // 输入输出头文件
int main() // 主函数入口
{ // 函数体开始
char grade; // 定义字符变量存等级
scanf("%c", &grade); // 读一个字符(A、B、C、D 之一)
switch (grade) // 按 grade 的值直接跳到对应 case
{ // switch 语句体开始
case 'A': printf("85~100\n"); break; // 匹配 A,输出后 break 跳出
case 'B': printf("70~84\n"); break; // 匹配 B,输出后跳出
case 'C': printf("60~69\n"); break; // 匹配 C,输出后跳出
case 'D': printf("<60\n"); break; // 匹配 D,输出后跳出
default : printf("error\n"); // 都不匹配时走这里
} // switch 语句体结束
return 0; // 结束
} // 函数体结束c
// ============ 8. switch 的贯穿:故意不写 break ============
#include <stdio.h> // 输入输出头文件
int main() // 主函数入口
{ // 函数体开始
int n = 2; // 假设 n 等于 2
switch (n) // 按 n 的值找入口
{ // switch 语句体开始
case 1: printf("1"); // 不匹配,跳过
case 2: printf("2"); // 从这里进入,打印 2
case 3: printf("3"); break; // 没有 break,继续打印 3,然后才跳出
default: printf("4"); // 如果连 break 都没有,还会继续打印 4
} // switch 语句体结束
printf("\n"); // 输出换行
return 0; // 结束
} // 函数体结束二、课后题 · 代码题
c
// ============ 习题 4:输入 3 个整数,输出最大的数 ============
#include <stdio.h> // 输入输出头文件
int main() // 主函数入口
{ // 函数体开始
int a, b, c, max; // 三个输入数和一个最大值
scanf("%d%d%d", &a, &b, &c); // 空格分隔读入三个整数
max = a; // 先假定第一个是最大值(打擂台)
if (b > max) max = b; // b 来挑战,赢了就更新 max
if (c > max) max = c; // c 再来挑战,赢了再更新
printf("max=%d\n", max); // 输出最后的擂主
return 0; // 结束
} // 函数体结束c
// ============ 习题 5:求小于 1000 的正数的平方根(取整数部分)============
#include <stdio.h> // 输入输出头文件
#include <math.h> // sqrt 函数在这个头文件里
int main() // 主函数入口
{ // 函数体开始
double x; // 定义双精度变量存输入
scanf("%lf", &x); // 读一个双精度数
if (x > 0 && x < 1000) // 两个条件都要满足:正数且小于 1000
printf("%d\n", (int)sqrt(x)); // sqrt 求平方根,(int) 强制取整数部分
else // 输入不合法
printf("input error\n"); // 提示错误
return 0; // 结束
} // 函数体结束c
// ============ 习题 6:分段函数 ============
#include <stdio.h> // 输入输出头文件
int main() // 主函数入口
{ // 函数体开始
float x, y; // x 是自变量,y 是函数值
scanf("%f", &x); // 读入 x
if (x < 1) // 第一段:x 小于 1
y = x; // y = x
else if (x < 10) // 第二段:1 <= x < 10(前面的已排除)
y = 2 * x - 1; // y = 2x - 1
else // 第三段:x >= 10
y = 3 * x - 11; // y = 3x - 11
printf("x=%.2f,y=%.2f\n", x, y); // 输出,保留两位小数
return 0; // 结束
} // 函数体结束c
// ============ 习题 8:百分制转等级 A~E(switch 版)============
#include <stdio.h> // 输入输出头文件
int main() // 主函数入口
{ // 函数体开始
int score; // 定义分数
scanf("%d", &score); // 读入分数
switch (score / 10) // 用十位数当入口:90~99 得到 9,100 得到 10
{ // switch 语句体开始
case 10: // 100 分单独处理
case 9: printf("A\n"); break; // 90~100 都是 A
case 8: printf("B\n"); break; // 80~89 是 B
case 7: printf("C\n"); break; // 70~79 是 C
case 6: printf("D\n"); break; // 60~69 是 D
default: printf("E\n"); // 剩下的都是 E
} // switch 语句体结束
return 0; // 结束
} // 函数体结束c
// ============ 习题 10(1):按利润提成算奖金(if 版)============
#include <stdio.h> // 输入输出头文件
int main() // 主函数入口
{ // 函数体开始
double i, bonus; // i 是利润,bonus 是奖金
scanf("%lf", &i); // 读入利润
if (i <= 100000) // 第一段:10 万以内
bonus = i * 0.1; // 全额提 10%
else if (i <= 200000) // 第二段:10~20 万
bonus = 10000 + (i - 100000) * 0.075; // 前 10 万封顶 1 万,超出部分 7.5%
else if (i <= 400000) // 第三段:20~40 万
bonus = 17500 + (i - 200000) * 0.05; // 前面封顶 1.75 万,超出部分 5%
else if (i <= 600000) // 第四段:40~60 万
bonus = 27500 + (i - 400000) * 0.03; // 前面封顶 2.75 万,超出部分 3%
else if (i <= 1000000) // 第五段:60~100 万
bonus = 33500 + (i - 600000) * 0.015; // 前面封顶 3.35 万,超出部分 1.5%
else // 第六段:100 万以上
bonus = 39500 + (i - 1000000) * 0.01; // 前面封顶 3.95 万,超出部分 1%
printf("bonus=%10.2f\n", bonus); // 输出奖金,宽度 10、两位小数
return 0; // 结束
} // 函数体结束c
// ============ 习题 10(2):同样的奖金题,switch 版 ============
#include <stdio.h> // 输入输出头文件
int main() // 主函数入口
{ // 函数体开始
double i, bonus; // i 是利润,bonus 是奖金
int c; // c 是把利润按"十万"分段的编号
scanf("%lf", &i); // 读入利润
c = (int)(i / 100000); // 除以 10 万后取整,得到 0、1、2……
switch (c) // 按 c 跳到对应段
{ // switch 语句体开始
case 0: bonus = i * 0.1; break; // 0~10 万
case 1: bonus = 10000 + (i - 100000) * 0.075; break; // 10~20 万
case 2: // 20~30 万
case 3: bonus = 17500 + (i - 200000) * 0.05; break; // 30~40 万,与上共用
case 4: // 40~50 万
case 5: bonus = 27500 + (i - 400000) * 0.03; break; // 50~60 万,与上共用
case 6: // 60~70 万
case 7: // 70~80 万
case 8: // 80~90 万
case 9: bonus = 33500 + (i - 600000) * 0.015; break; // 90~100 万,四个共用
default: bonus = 39500 + (i - 1000000) * 0.01; // 100 万以上
} // switch 语句体结束
printf("bonus=%10.2f\n", bonus); // 输出奖金
return 0; // 结束
} // 函数体结束c
// ============ 习题 11:输入 4 个整数,按从小到大输出 ============
#include <stdio.h> // 输入输出头文件
int main() // 主函数入口
{ // 函数体开始
int a, b, c, d, t; // 四个数 + 一个交换用的临时变量
scanf("%d%d%d%d", &a, &b, &c, &d); // 空格分隔读入四个整数
if (a > b) { t = a; a = b; b = t; } // 保证 a <= b
if (a > c) { t = a; a = c; c = t; } // 保证 a <= c,此时 a 最小
if (a > d) { t = a; a = d; d = t; } // 保证 a <= d,a 确定为最小
if (b > c) { t = b; b = c; c = t; } // 保证 b <= c
if (b > d) { t = b; b = d; d = t; } // 保证 b <= d,b 确定为次小
if (c > d) { t = c; c = d; d = t; } // 保证 c <= d,全部排好
printf("%d %d %d %d\n", a, b, c, d); // 按序输出
return 0; // 结束
} // 函数体结束c
// ============ 习题 12:判断点落在哪个圆塔里,求建筑高度 ============
#include <stdio.h> // 输入输出头文件
int main() // 主函数入口
{ // 函数体开始
double x, y; // 点的横、纵坐标
scanf("%lf,%lf", &x, &y); // 两个坐标用逗号分隔输入
if ((x - 2) * (x - 2) + (y - 2) * (y - 2) <= 1 // 到圆心 (2,2) 的距离平方 <= 1
|| (x + 2) * (x + 2) + (y - 2) * (y - 2) <= 1 // 到圆心 (-2,2)
|| (x + 2) * (x + 2) + (y + 2) * (y + 2) <= 1 // 到圆心 (-2,-2)
|| (x - 2) * (x - 2) + (y + 2) * (y + 2) <= 1) // 到圆心 (2,-2)
printf("height=10\n"); // 落在任一塔内,高度 10 米
else // 四个都不满足
printf("height=0\n"); // 塔外高度为 0
return 0; // 结束
} // 函数体结束三、我出的题 · 随课练习
🔮 猜输出
c
// ============ 猜输出 1:if 到底管到哪一句 ============
#include <stdio.h> // 输入输出头文件
int main() // 主函数入口
{ // 函数体开始
int x = 5; // 定义并初始化 x 为 5
if (x > 3) // 条件成立时会怎样?
printf("A"); // 这一句受 if 控制
printf("B"); // 这一句呢?注意缩进不代表从属关系
printf("\n"); // 换行
return 0; // 结束
} // 函数体结束c
// ============ 猜输出 2:悬空 else ============
#include <stdio.h> // 输入输出头文件
int main() // 主函数入口
{ // 函数体开始
int x = 0, y = 1; // 初始化
if (x == 0) // 外层条件成立
if (y == 0) printf("A"); // 内层条件不成立
else printf("B"); // 这个 else 跟哪个 if 配对?
printf("\n"); // 换行
return 0; // 结束
} // 函数体结束c
// ============ 猜输出 3:短路求值 ============
#include <stdio.h> // 输入输出头文件
int main() // 主函数入口
{ // 函数体开始
int a = 1, b = 2, c = 3, d = 4; // 四个整数
int m = 1, n = 1; // m、n 初值都是 1
(m = a > b) && (n = c > d); // 先算左边,再看要不要算右边
printf("%d %d\n", m, n); // 输出 m 和 n
return 0; // 结束
} // 函数体结束🛠 变式题
c
// ============ 变式 1:输入两个数,按从大到小输出(补全交换)============
#include <stdio.h> // 输入输出头文件
int main() // 主函数入口
{ // 函数体开始
float a, b, t; // 两个数和临时变量
scanf("%f,%f", &a, &b); // 逗号分隔输入
if (a < b) // 前小后大,说明顺序反了
{ // 需要交换
// TODO:在这里写三句交换代码
} // 交换结束
printf("%5.2f,%5.2f\n", a, b); // 输出
return 0; // 结束
} // 函数体结束c
// ============ 变式 2:输入 1~7,输出星期英文名(补全 case)============
#include <stdio.h> // 输入输出头文件
int main() // 主函数入口
{ // 函数体开始
int day; // 1~7 的整数
scanf("%d", &day); // 读入
switch (day) // 按 day 跳转
{ // switch 体开始
case 1: printf("Monday\n"); break; // 已给样例
// TODO:补 case 2 到 case 7
default: printf("error\n"); // 其他数字
} // switch 体结束
return 0; // 结束
} // 函数体结束c
// ============ 变式 3:补全条件——能同时被 3 和 5 整除 ============
#include <stdio.h> // 输入输出头文件
int main() // 主函数入口
{ // 函数体开始
int n; // 待判断的整数
scanf("%d", &n); // 读入
if (1) // TODO:把 1 换成正确的复合条件
printf("yes\n"); // 满足时输出 yes
else // 否则
printf("no\n"); // 输出 no
return 0; // 结束
} // 函数体结束🐛 改错题
c
// ❌ 错误示例(故意)
// 错在哪:if 后面多了一个分号,if 管的是一个空语句,printf 变成无条件执行
// 怎么改:把 if (x > 0); 后面的分号删掉
#include <stdio.h> // 输入输出头文件
int main() // 主函数入口
{ // 函数体开始
int x = 10; // 定义 x
if (x > 0); // 这里多了分号
printf("positive\n"); // 这句其实和 if 无关
return 0; // 结束
} // 函数体结束c
// ❌ 错误示例(故意)
// 错在哪:if (a = 1) 是赋值,不是比较;a 被赋成 1,表达式值为 1,永远为真
// 怎么改:写成 if (a == 1),或者把常量写左边 if (1 == a)
#include <stdio.h> // 输入输出头文件
int main() // 主函数入口
{ // 函数体开始
int a = 0; // a 初值为 0
if (a = 1) // 赋值表达式,恒为真
printf("equal\n"); // 永远走这里
else // 永远走不到
printf("not equal\n"); // 本应输出这句
return 0; // 结束
} // 函数体结束c
// ❌ 错误示例(故意)
// 错在哪:case 90 只匹配 90 这个精确值,85 不等于 90,所以落到 default
// 怎么改:改成 switch (score / 10),用十位数匹配,case 9 管 90~99
#include <stdio.h> // 输入输出头文件
int main() // 主函数入口
{ // 函数体开始
int score = 85; // 分数 85
switch (score) // 用原始的分数当开关
{ // switch 体开始
case 90: printf("A\n"); break; // 只有正好 90 才匹配
case 80: printf("B\n"); break; // 只有正好 80 才匹配
default: printf("other\n"); // 85 落到这里
} // switch 体结束
return 0; // 结束
} // 函数体结束四、加练题
(暂无。想加练就说"再出几道 XX 题",我出的题会标上日期追加在这块。)