一、输入与内存管理:scanf与sizeof的精准掌控
1. scanf的输入艺术
int num;
char str[20];
scanf("%d %19s", &num, str); // 注意字符串长度限制
关键要点:
- 安全输入:使用
%ns
限制字符串长度(如%19s
),防止缓冲区溢出 - 缓冲区残留问题:输入后使用
while(getchar() != '\n');
清空
2. sizeof的内存测量
int arr[5];
printf("数组大小:%zu", sizeof(arr)); // 输出20(假设int为4字节)
printf("元素个数:%zu", sizeof(arr)/sizeof(arr[0])); // 输出5
易错场景:
- 指针陷阱:
sizeof
返回指针大小(4/8字节),而非指向数据大小 - 字符串长度:
sizeof
包含\0
,strlen
不包含(如"hello"
:6 vs 5)
二、控制流语句:逻辑的指挥官
1. 分支结构:if与switch的精准选择
if-else链:
if (score >= 90) printf("A");
else if (score >= 80) printf("B"); // 条件顺序决定优先级
switch穿透与阻断:
switch (grade) {
case 'A': printf("优秀"); break; // 必须加break防止穿透
case 'B': printf("良好"); break;
default: printf("无效成绩"); // 处理未匹配情况
}
2. 循环结构:while、for、do-while的适用场景
for循环:
for (int i=0; i<10; i++) { // C99+支持循环内定义变量
if (i%2 == 0) continue; // 跳过偶数
printf("%d ", i); // 输出1 3 5 7 9
}
do-while特性:
int input;
do {
printf("输入1继续:");
scanf("%d", &input);
} while (input != 1); // 强制用户输入正确值
3. 循环控制关键字:break与continue
break示例:
for (int i=0; i<10; i++) {
if (i == 5) break; // 循环终止于i=5
}
continue示例:
int i=0;
while (i<5) {
i++;
if (i == 3) continue; // 跳过i=3的后续代码
printf("%d ", i); // 输出1 2 4 5
}
三、高频错误与调试技巧
1.switch的穿透陷阱
switch (day) {
case 1: printf("周一");
case 2: printf("周二"); // 未加break,输出"周一 周二"
}
修复方案:每个case
后加break
,或利用穿透特性实现多条件合并
2.do-while的分号遗漏
do {
// 代码...
} while (condition) // 错误!缺少分号
3.循环变量失控
for (int i=0; i<10; i++) {
if (i==5) i=8; // 可能导致逻辑混乱或死循环
}
4.sizeof误判数组长度
int arr[5] = {1,2,3,4,5};
int len = sizeof(arr); // 错误!应为 sizeof(arr)/sizeof(int)
四、实战案例:综合应用与代码规范
案例1:用户登录验证(含错误重试)
#include <stdio.h>
#include <string.h>
int main() {
char username[20], password[20];
int attempts = 3;
do {
printf("用户名:");
scanf("%19s", username);
printf("密码:");
scanf("%19s", password);
if (strcmp(username, "admin") == 0 && strcmp(password, "123456") == 0) {
printf("登录成功!\n");
break; // 正确时退出循环
} else {
printf("剩余尝试次数:%d\n", --attempts);
}
} while (attempts > 0);
return 0;
}
案例2:猜数字游戏(含循环控制)
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main() {
srand(time(NULL));
int target = rand() % 100 + 1;
int guess, count = 0;
printf("猜数字游戏(1-100)\n");
while (1) {
printf("请输入:");
scanf("%d", &guess);
count++;
if (guess == target) {
printf("恭喜!用了%d次\n", count);
break; // 正确时退出
} else if (guess < target) {
printf("猜小了!\n");
} else {
printf("猜大了!\n");
}
if (count >= 7) {
printf("次数用尽,答案是%d\n", target);
break; // 强制终止
}
}
return 0;
}
五、编程规范与学习建议
-
调试技巧
- 使用
printf
输出中间变量值(如printf("i=%d\n", i);
) - 分步执行:注释部分代码逐步排查问题
- 使用
-
代码规范
- 变量命名有意义(如
studentCount
而非a
) - 添加注释说明复杂逻辑(如
// 处理边界值
) - 缩进对齐,避免一行多语句
- 变量命名有意义(如
-
扩展学习
- 指针与内存管理(参考《C Primer Plus》)
- 数据结构基础(数组、链表实现)
原创声明:本文内容结合多校教学大纲与实战经验整理,代码均通过GCC测试。禁止抄袭,转载请注明出处。
讨论区:你在学习过程中遇到过哪些"匪夷所思"的错误?欢迎评论区交流!💡
资源推荐:
- C语言标准库手册
- 《C陷阱与缺陷》(Andrew Koenig著)
- CSDN社区「C语言」专栏(每日更新实战技巧)