本文最后更新于 2025-03-11,学习久了要注意休息哟

第一章 程序流程控制概述

1.1 顺序结构

📌 三大特征

  1. ➡️ 单线程执行:代码像流水线一样逐行运行
  2. 不可跳跃A→B→C 严格顺序
  3. 🧩 基础结构:所有程序的默认执行方

🖥️ 代码演示

#include <stdio.h>
int main() {
    int a = 10;                 // 🎯 STEP 1
    int b = a * 2;              // ⚙️ STEP 2
    printf("结果:%d", b);       // 🖨️ STEP 3
    return 0;                   // 🏁 结束
}

📊 流程图表示

开始 → [操作1] → [操作2] → [操作3] → 结束
          ▼         ▼         ▼
        输出a     计算b     打印结果

1.2 选择结构

🔀 分支决策剧场

🧮 结构对比表

if-elseswitch-case
图标🔍条件检测🔢数值匹配
优势处理复杂逻辑多分支效率高
局限嵌套过多易混乱仅支持整型

⚠️ 经典错误

if(a = 5){...}  // ❌ 错误!应使用 == 
                // 💡 建议:if(5 == a) 防错写法

1.3 循环结构

🔁 循环三剑客

while循环:🤔条件→🔄执行  
do-while:🔄执行→🤔条件  
for循环:🔢计数循环专家

📈 性能对比

// 🐢 低效写法
int i=0;
while(i<10){
    printf("%d",i);
    i++;
}

// 🐇 高效写法
for(int i=0;i<10;i++){
    printf("%d",i);
}

1.4 结构化程序设计原则

🚫 三大禁忌

  1. 🍝 意大利面条代码:避免无节制的goto
  2. 🕳️ 黑洞函数:拒绝超过50行的代码块
  3. 🧩 碎片化逻辑:杜绝重复代码段

✅ 优质代码特征

清晰结构 → 🏗️ 模块化设计
可读性强 → 📖 见名知意变量
易于维护 → 🛠️ 低耦合高内聚

📚 复习加油站

🧮 速记口诀

顺序结构一条线,选择结构分两边
循环结构转圈圈,结构清晰好维护

🚫 错题本模板

错误现象原因分析解决方案
死循环条件未更新检查循环变量
分支失效条件覆盖不全补全else分支

这种设计方案的优点:

💻 兼容性强:所有平台完美显示

🎨 视觉层次:通过符号/缩进/分割线构建阅读节奏

📱 移动友好:无图片加载压力

✏️ 易于修改:直接复制粘贴即可调整样式

第二章 条件判断语句

🔍 本章目标:掌握程序分支决策的核心机制

2.1 if语句

🧱 结构框架

// 单分支结构  
if(条件) {  
    // 🎯 条件为真时执行  
}

// 双分支结构  
if(条件) {  
    // ✅ 真分支  
} else {  
    // ❌ 假分支  
}

// 多分支阶梯  
if(条件1) {  
    // 📌 情况1  
} else if(条件2) {  
    // 📌 情况2  
} else {  
    // 🧩 默认情况  
}

🚨 经典错误集

错误代码问题分析修正方案
if(a = 5)赋值替代比较if(5 == a)
if(1 < a < 5)逻辑表达式错误if(a>1 && a<5)
嵌套超过3层可读性降低改用switch或函数封装

🔄 执行流程图

graph LR
    A[条件判断] -->|Yes| B[代码块A]
    A -->|No| C[代码块B]

💡 实战技巧

  1. 防御性写法

    if(5 == a)  // ✅ 常量放左侧,避免写成赋值
    
  2. 简化嵌套

    // 嵌套写法 → 卫语句优化
    if(error) return;  // 🛑 提前返回
    // 正常流程代码
    

2.2 switch-case语句

🎛️ 标准结构

switch(表达式) {   // ⚠️ 仅支持整型/枚举
    case1:  
        // 操作1  
        break;    // 🛑 必须阻断穿透  
    case2:  
        // 操作2  
        break;
    default:      // 🧩 默认处理  
        // 未知情况
        break;  
}

⚔️ vs if-else 对比战

特性switch-caseif-else
匹配方式精确值匹配范围/逻辑判断
执行效率跳转表直接定位顺序判断
可读性多分支时更清晰简单分支时直观
限制条件仅支持整型无类型限制

💥 穿透现象演示

switch(level) {  
    case 3:  
        printf("奖励皮肤");  // 🎮 会继续执行case2  
    case 2:  
        printf("奖励金币");  // 💰 无break继续穿透  
    case 1:  
        printf("再接再厉");  // 🎯 最终输出三句话  
        break;  
}
// 💡 合理利用穿透:多条件共享代码块

📜 行业规范

default必须存在:即使当前用不到

case排序规则

  • 数字:从小到大
  • 字符:字母顺序
  • 特殊case置顶

注释要求

case VIP_USER:  // 会员用户特权处理

🧪 综合训练营

案例1:成绩等级判断

if(score >= 90) {
    grade = 'A';
} else if(score >= 75) {
    grade = 'B';
} else if(score >= 60) {
    grade = 'C';
} else {
    grade = 'D';
}

案例2:工作日判断

switch(weekday) {
    case 1: case 2: case 3: case 4: case 5:
        printf("工作日 💼");
        break;
    case 6: case 7:
        printf("休息日 🏖");
        break;
    default:
        printf("非法输入 🚨"); 
}

📌 速记口诀

if判断范围强,switch精准值考量  
break阻断穿透流,default保平安

🧠 脑图总结

graph TD
    A{{条件判断}} -->|分支逻辑| B[if家族]
    A -->|离散匹配| C[switch-case]
    
    B --> B1[/单分支/]
    B1 -->|条件过滤| D[简单过滤]
    
    B --> B2{双分支}
    B2 -->|true| E1[执行块A]
    B2 -->|false| E2[执行块B]
    
    B --> B3[[多分支]]
    B3 --> F1[条件1]
    B3 --> F2[条件2]
    B3 --> F3[...n]
    
    C --> C1>case穿透]
    C1 -->|未break| G1[连续执行]
    C1 -->|需break| G2[中断流程]
    
    C --> C2(整型限定)
    C2 --> H1[字符类型]
    C2 --> H2[枚举类型]
    
    classDef logic fill:#E1F5FE,stroke:#039BE5;
    class B,B1,B2,B3,C,C1,C2 logic;

第三章 循环控制语句

🔄 本章目标:掌握重复执行代码的核心方法与优化策略

3.1 while循环

🎯 核心特征

while(循环条件) {  
    // 条件为真时重复执行
    // 🔄 必须包含条件更新语句  
}

⚡ 执行流程图

graph TD
    A{条件判断为真} -- 是 --> B[执行循环体]
    B --> C[更新条件]
    C --> A
    A -- 否 --> D[结束循环]

🚨 典型错误

int i=0;  
while(i < 5) {  // ❌ 缺少条件更新
    printf("%d", i);  
}  
// 死循环警告!💀

💡 实战技巧

// 读取直到合法输入
while(scanf("%d",&n)!=1 || n<0){  
    printf("输入错误,请重试:");  
    while(getchar()!='\n'); // 清空输入缓冲区  
}

3.2 do-while循环

🎯 核心特征

do {  
    // 至少执行一次  
    // 🔄 结尾必须带分号  
} while(循环条件);  

⚡ vs while对比表

特性whiledo-while
执行顺序先判断后执行先执行后判断
适用场景0~N次执行1~N次执行
代码示例文件读取菜单交互系统

💡 实战案例

char choice;  
do {  
    printf("1.开始游戏\n2.设置\n3.退出\n");  
    scanf(" %c", &choice);  
    handleChoice(choice);  // 🎮 处理用户选择  
} while(choice != '3');    // 🏁 输入3退出

3.3 for循环

🧱 标准结构解析

for(初始化; 条件; 更新){  
    // 循环体  
}  
// 等效while写法:  
初始化;  
while(条件){  
    循环体;  
    更新;  
}

🔄 变形用法

for(;;){...}       // ✅ 合法无限循环  
for(int i=0,j=10; i<j; i++,j--){...}  // 多变量控制  
for(printf("Start"); i<5; i++){...}  // 初始化为输出语句

📊 性能优化建议

// 优化前:每次循环计算长度  
for(int i=0; i<strlen(s); i++){...}  

// 优化后:预先计算长度  
int len = strlen(s);  
for(int i=0; i<len; i++){...}  

3.4 循环嵌套

🎯 核心原则

for(int i=0; i<外循环次数; i++){    // 🌍 外层控制大流程  
    for(int j=0; j<内循环次数; j++){// 🔍 内层处理细节  
        // 注意变量作用域!  
    }  
}

💥 经典错误案例

for(int i=0; i<3; i++){  
    for(int i=0; i<5; i++){  // ❌ 内外层变量同名  
        printf("*");  
    }  
}  
// 实际输出:***** ***** *****

💡 实战案例:乘法表

for(int i=1; i<=9; i++){  
    for(int j=1; j<=i; j++){  
        printf("%dx%d=%-2d ", j, i, i*j);  
    }  
    printf("\n");  // 🧮 打印完一行换行  
}

🧠 脑图总结

循环结构  
├─ while → 先判断后执行  
├─ do-while → 先执行后判断  
├─ for → 精确控制循环次数  
└─ 嵌套循环 → 矩阵/多维数据处理  
   ├─ 外层控制行 → 内层控制列  
   └─ 注意变量作用域  

📌 速记口诀

while先判后执行,do-while保底行  
for循环三要素,嵌套注意作用域

🧪 综合训练营

案例1:素数判断

for(int num=2; num<=100; num++){  
    int isPrime = 1;  
    for(int i=2; i*i<=num; i++){  
        if(num%i == 0){  
            isPrime = 0;  
            break;  
        }  
    }  
    if(isPrime) printf("%d ", num);  
}

案例2:菱形打印

int n = 5;  
// 上半部分  
for(int i=1; i<=n; i++){  
    for(int j=1; j<=n-i; j++) printf(" ");  
    for(int j=1; j<=2*i-1; j++) printf("*");  
    printf("\n");  
}  
// 下半部分(略)

第四章 控制语句进阶

4.1 break语句

🎯 核心功能

// 在循环中立即终止当前层循环
while(1){
    if(条件) break;  // 🛑 紧急出口
    // ...
}

// 在switch中阻断case穿透
switch(n){
    case 1: ... break;
    case 2: ... break;
}

⚠️ 使用规范

  • 禁止在多重循环中跨层break(C语言不支持)

  • 推荐配合标志变量使用:

    int found = 0;
    for(...){
        if(...){
            found = 1;
            break;
        }
    }
    

4.2 continue语句

🔄 执行流程

      ┌───────────┐
      │  循环开始  │
      └─────┬─────┘
            ▼
      ┌───────────┐
      │ 条件判断   │←────┐
      └─────┬─────┘     │
      true  │ false     │
        ▼   ▼           │
    执行循环体 → [continue]
            │           │
            └───────────┘

💡 实战案例

for(int i=0; i<100; i++){
    if(i%2 == 0) continue;  // 跳过偶数
    processOdd(i);          // 仅处理奇数
}

4.3 goto语句

⚠️ 争议与规范

// 🚫 典型滥用案例
goto label;  
... // 复杂逻辑
label:  

// ✅ 允许使用场景
for(...){  
    for(...){  
        if(错误发生)  
            goto cleanup;  // 跳转到资源释放  
    }  
}  
cleanup:  
    free(resources);  

🚨 行业规范

  1. 跳跃方向:只允许向前跳转
  2. 跳跃范围:禁止跨函数跳转
  3. 命名规范:标签用全大写+下划线(如ERROR_HANDLE

4.4 return语句

📦 多返回值处理

// 通过指针参数返回多个值  
int parseInput(char* str, int* outVal){  
    if(错误) return -1;  // 🚩 返回状态码  
    *outVal = 计算结果;  
    return 0;  
}  

// 调用方  
int result;  
if(parseInput("123", &result) != 0){  
    // 错误处理  
}  

⏳ 资源释放责任链

void func(){  
    FILE* fp = fopen(...);  
    if(!fp) return;  // ❌ 忘记关闭文件  

    // 正确写法  
    if(!fp) goto CLEANUP;  
    ...  
CLEANUP:  
    if(fp) fclose(fp);  
}

4.5 exit语句

⚡ 执行特性

#include <stdlib.h>  

if(致命错误){  
    fprintf(stderr, "系统不可恢复错误");  
    exit(EXIT_FAILURE);  // 🔚 立即终止进程  
}  

🆚 exit与return对比

returnexit
作用范围退出当前函数终止整个进程
清理动作自动释放栈内存跳过未执行的清理代码
使用场景正常函数返回不可恢复的系统级错误

🧪 综合训练营

案例1:用户登录尝试限制

for(int i=0; i<3; i++){
    if(验证密码()){
        printf("登录成功!🎉");
        break;
    }else{
        if(i==2){
            printf("账户锁定!🔒");
            exit(EXIT_FAILURE);
        }
        continue;  // 继续下一次尝试
    }
}

案例2:资源泄漏风险

void dangerFunc(){  
    int* mem = malloc(1024);
    if(错误发生){
        exit(1);  // 💥 内存泄漏!
    }
    free(mem);
}

📌 速记口诀

break断当前循环,continue跳下次忙
goto争议需慎用,return回家exit亡

🧠 脑图总结

流程控制进阶
├─ break → 循环/switch阻断
├─ continue → 跳过本次迭代
├─ goto → 争议性跳转工具
├─ return → 函数返回出口
└─ exit → 进程强制终止
   ├─ 风险:资源泄漏
   └─ 适用:不可恢复错误

第五章 综合应用与调试

5.1 典型算法实现

1. 累加/累乘算法

// 累加(1~100求和)
int sum = 0;
for(int i=1; i<=100; i++) {
    sum += i;  // GDB调试点:观察sum变量变化
}

// 累乘(5!计算)
int product = 1;
for(int i=1; i<=5; i++) {
    product *= i;
}

GDB调试命令

(gdb) break 3               # 在循环体设置断点
(gdb) print sum             # 查看累加值
(gdb) watch product         # 监控乘积变化
(gdb) continue              # 继续执行直到下一个断点

2. 最大/最小值查找

int arr[] = {3,9,2,5,1};
int max = arr[0];
for(int i=1; i<5; i++){
    if(arr[i] > max) {      // 断点位置
        max = arr[i];
    }
}

GDB调试技巧

(gdb) break 4 if i==3      # 当i=3时触发断点
(gdb) x/5w arr             # 查看数组内存布局
(gdb) display max          # 持续显示最大值变量

3. 数字逆序处理

int num = 1234, reversed = 0;
while(num != 0) {          // 注意此处错误!
    reversed = reversed*10 + num%10;
    num /= 10;
}

GDB排错流程

  1. 编译时加-g选项:gcc -g reverse.c
  2. 启动调试:gdb a.out
  3. 定位错误:
(gdb) run                   # 运行程序报错
(gdb) backtrace             # 查看错误调用栈
(gdb) list                  # 显示错误代码位置
(gdb) break while循环行号    # 设置断点
(gdb) print num             # 观察变量异常值

5.2 调试技巧

📦GDB核心命令速查表

命令功能说明示例
break [行号/函数名]设置断点break main
watch 变量名监控变量写操作watch sum
next (n)单步跳过函数调用n
step (s)单步进入函数内部s
info locals显示当前栈帧的局部变量info locals
frame切换调用栈帧frame 2
x/[数量][格式] 地址查看内存数据x/10dw &array

💡 实战调试流程

  1. 启动调试

    gcc -g program.c -o program
    gdb program
    
  2. 定位段错误

    (gdb) run
    (gdb) backtrace         # 查看崩溃时的调用栈
    (gdb) frame N           # 切换到问题栈帧
    (gdb) print 可疑指针     # 检查指针地址合法性
    
  3. 追踪循环变量

    (gdb) break 10 if i==5  # 第5次循环时暂停
    (gdb) display j         # 每次暂停显示j的值
    (gdb) continue          # 持续执行
    

5.3 常见错误分析

1. 分号位置错误

for(int i=0; i<5; i++);  // ❌ 多写分号导致循环体为空
{
    printf("Hello");      // 实际只执行一次
}

GDB验证

(gdb) disassemble        # 查看汇编代码
(gdb) stepi              # 单步执行机器指令观察循环次数

2. 条件表达式错误

if(score = 60) {         // ❌ 赋值替代比较
    printf("及格");
}

GDB检测

(gdb) watch score        # 监控变量修改
(gdb) run                # 触发条件时暂停
(gdb) print score        # 发现值被意外修改

3. 循环控制变量错误

for(int i=0; i<=5; i++) {  // ❌ 循环6次越界
    arr[i] = i;          // 当i=5时越界
}

GDB内存检查

(gdb) break 2
(gdb) x/6w arr           # 显示数组内存区域
(gdb) print &arr[5]      # 确认数组边界

4. 作用域理解偏差

int i=5;
for(int i=0; i<3; i++){  // 内层i覆盖外层
    printf("%d",i);      // 输出0,1,2
}
printf("%d",i);          // 输出5(外层i)

GDB验证

(gdb) info locals        # 查看不同作用域变量
(gdb) break 4            # 在循环外设置断点
(gdb) print i            # 显示外层变量值

📌 调试口诀

编译必加-g选项,断点监控是核心  
next跳过step进,内存查看用x命令  
段错误先查指针,逻辑错要跟变量

🧠 脑图总结

综合调试  
├─ 算法实现 → 理解执行流程  
├─ GDB工具 → 掌握核心命令  
└─ 错误分析 → 定位修正技巧
   ├─ 语法错误 → 编译器警告
   └─ 逻辑错误 → 断点跟踪  

第六章 项目实战

6.1 学生成绩管理系统(菜单驱动)

6.2 简易ATM机交互程序

6.3 数字猜谜游戏

6.4 质因数分解工具

6.5 N位数拆分

6.6 二进制转换