本文通过图书管理系统,不同版本的迭代完成,融入c语言的内容,达到快速学习c语言的目的
一、整体规划

二、本次内容
* ============================================================
* 阶段V0:基础语法版 - 单本书籍管理
* ============================================================
* 知识点:变量、输入输出、if-else分支、while循环
* 功能:管理单独一本书的借阅和归还
*变量定义与初始化:int、char数组、赋值操作
*输入输出:printf()格式化输出、scanf()输入
*字符串操作:scanf("%s")读取字符串、字符数组赋值
*算术运算:加减法 + -、比较运算 < > ==
*if-else分支:多条件判断、嵌套if
*while循环:循环控制、循环退出条件
*逻辑控制:int running作为开关变量
* ============================================================
三、本次代码
//
// Created by Administrator on 2026/6/24.
//
/**
* ============================================================
* 阶段V0:基础语法版 - 单本书籍管理
* ============================================================
* 知识点:变量、输入输出、if-else分支、while循环
* 功能:管理单独一本书的借阅和归还
* ============================================================
*/
#include <stdio.h>
int main() {
// ========================================
// 1. 定义变量(只管理一本书的数据)
// ========================================
int bookId = 1001;
char bookName[100] = "C程序设计语言";
char bookAuthor[50] = "Kernighan";
char bookIsbn[20] = "978-7-111-00101-0";
int stock = 5; // 总库存
int borrowed = 0; // 已借出数量
int choice;
int running = 1; // 循环控制变量:1继续运行,0退出
// ========================================
// 2. 主循环(菜单驱动)
// ========================================
while (running) {
// -------- 打印菜单 --------
printf("\n========================================\n");
printf(" 图书管理系统 V0(基础版)\n");
printf("========================================\n");
printf("当前管理图书:%s(ID: %d)\n", bookName, bookId);
printf("库存:%d 已借出:%d 可借:%d\n",
stock, borrowed, stock - borrowed);
printf("----------------------------------------\n");
printf("1. 修改图书信息\n");
printf("2. 借书\n");
printf("3. 还书\n");
printf("4. 显示图书信息\n");
printf("5. 退出程序\n");
printf("----------------------------------------\n");
printf("请选择操作(1-5):");
scanf("%d", &choice);
// -------- 分支处理 --------
if (choice == 1) {
// 修改图书信息
printf("\n--- 修改图书信息 ---\n");
printf("请输入新的书名:");
scanf("%s", bookName);
printf("请输入新的作者:");
scanf("%s", bookAuthor);
printf("请输入新的ISBN:");
scanf("%s", bookIsbn);
printf("请输入新的库存数量:");
scanf("%d", &stock);
// 如果修改库存时,已借出数量不能超过库存
if (borrowed > stock) {
printf("警告:已借出数量(%d)超过新库存(%d),已自动调整\n", borrowed, stock);
borrowed = stock;
}
printf("✓ 图书信息修改成功!\n");
} else if (choice == 2) {
// 借书操作
printf("\n--- 借书操作 ---\n");
if (borrowed < stock) {
borrowed = borrowed + 1;
printf("✓ 借书成功!当前已借出:%d 本\n", borrowed);
} else {
printf("✗ 借书失败!库存不足(库存:%d,已借出:%d)\n", stock, borrowed);
}
} else if (choice == 3) {
// 还书操作
printf("\n--- 还书操作 ---\n");
if (borrowed > 0) {
borrowed = borrowed - 1;
printf("✓ 还书成功!当前已借出:%d 本\n", borrowed);
} else {
printf("✗ 还书失败!没有借出的书可还(已借出:%d)\n", borrowed);
}
} else if (choice == 4) {
// 显示图书详细信息
printf("\n--- 图书详细信息 ---\n");
printf("图书ID :%d\n", bookId);
printf("书名 :%s\n", bookName);
printf("作者 :%s\n", bookAuthor);
printf("ISBN :%s\n", bookIsbn);
printf("总库存 :%d 本\n", stock);
printf("已借出 :%d 本\n", borrowed);
printf("可借数量 :%d 本\n", stock - borrowed);
printf("借阅状态 :");
if (borrowed == 0) {
printf("🟢 全部在库\n");
} else if (borrowed < stock) {
printf("🟡 部分借出\n");
} else {
printf("🔴 已全部借出\n");
}
} else if (choice == 5) {
// 退出程序
printf("\n感谢使用图书管理系统,再见!\n");
running = 0;
} else {
printf("\n✗ 无效选择!请输入 1-5 之间的数字\n");
}
}
return 0;
}
四、重点知识内容解析
字符串本质
> 核心本质:C 语言字符串是以 `\0`(空字符)结尾的字符数组。
> 头文件:绝大多数函数位于 `<string.h>`,数值转换函数位于 `<stdlib.h>`。
4.1字符串内容解析(常用功能)
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main() {
// 1. 安全拷贝
char buf[10];
strncpy(buf, "HelloWorld", sizeof(buf) - 1);
buf[sizeof(buf) - 1] = '\0';
// 2. 安全拼接
char dest[20] = "Hello";
strncat(dest, " World", sizeof(dest) - strlen(dest) - 1);
// 3. 比较
if (strcmp(dest, "Hello World") == 0) {
printf("匹配成功\n");
}
// 4. 查找子串
char *found = strstr(dest, "World");
if (found) printf("找到: %s\n", found);
// 5. 分割
char data[] = "one,two,three";
char *token = strtok(data, ",");
while (token) {
printf("token: %s\n", token);
token = strtok(NULL, ",");
}
// 6. 格式化
char fmt[64];
snprintf(fmt, sizeof(fmt), "Value: %d", 42);
// 7. 字符串转数字
long num = strtol("100", NULL, 10);
return 0;
}
4.2循环结构
| 循环类型 | 语法 | 执行次数 | 适用场景 |
|---|---|---|---|
| for | for(init; cond; update) { } |
0~N 次 | 计数循环 |
| while | while(cond) { } |
0~N 次 | 条件循环 |
| do-while | do { } while(cond); |
1~N 次 | 至少执行一次 |
| break | break; |
立即退出 | 提前终止循环 |
| continue | continue; |
跳过本次 | 忽略本次剩余逻辑 |
goto 破坏程序结构,除了跳出多层嵌套循环外,尽量避免使用! |
4.3scanf用法
scanf 是 C 标准库中最常用的输入函数,用于从标准输入(键盘)读取格式化数据。头文件:<stdio.h>
通用方式:使用格式:scanf("%d", &n);====【scanf("格式符", 变量地址);】
需要注意的是,后面n如果是数组的话或者是字符串的话就是:
使用格式:scanf("%d", n);
| 格式符 | 说明 | 对应类型 | 示例 |
|---|---|---|---|
%d |
十进制整数 | int |
scanf("%d", &num); |
%i |
自动识别进制(8/10/16) | int |
scanf("%i", &num); |
%u |
无符号十进制整数 | unsigned int |
scanf("%u", &num); |
%o |
八进制整数 | int |
scanf("%o", &num); |
%x / %X |
十六进制整数 | int |
scanf("%x", &num); |
%f |
浮点数(float) | float |
scanf("%f", &f); |
%lf |
双精度浮点数(double) | double |
scanf("%lf", &d); |
%Lf |
长双精度浮点数 | long double |
scanf("%Lf", &ld); |
%c |
单个字符(包括空白符) | char |
scanf("%c", &ch); |
%s |
字符串(不含空白符) | char[] |
scanf("%s", str); |
%p |
指针地址 | void* |
scanf("%p", &ptr); |
%[] |
字符集 | char[] |
scanf("%[^\n]", str); |
%* |
赋值抑制符(跳过) | 任意 | scanf("%*d %d", &num); |
%n |
已读取字符数(不消耗输入) | int* |
scanf("%d%n", &num, &n); |
五、项目总结
知识点目录结构
-
头文件包含
-
主函数定义
-
变量定义与初始化
-
数组(字符串)操作
-
基本输入输出
-
算术运算与赋值
-
分支结构(if-else-if)
-
循环结构(while)
-
逻辑控制(标志变量)
-
函数返回值
📚 详细知识点讲解
1. 头文件包含
#include <stdio.h>
| 知识点 | 说明 | 重点强调 |
|---|---|---|
| 预处理指令 | #include 是预处理命令,在编译前处理 |
⚠️ 必须以 # 开头,行末无分号 |
| 标准库 | stdio.h = Standard Input Output |
包含 printf、scanf 等函数 |
| 尖括号 | < > 表示从系统路径查找头文件 |
区别于双引号 " "(用户自定义头文件) |
2. 主函数定义
int main() {
// ...
return 0;
}
| 知识点 | 说明 | 重点强调 |
|---|---|---|
| 函数定义 | main 是程序入口,操作系统最先调用 |
⚠️ 一个程序只能有一个 main 函数 |
| 返回类型 | int 表示返回整数给操作系统 |
return 0 表示程序正常结束 |
| 函数体 | { } 包裹的代码块 |
所有语句必须在 { } 内部 |
3. 变量定义与初始化
int bookId = 1001;
int stock = 5;
int borrowed = 0;
int choice;
int running = 1;
| 知识点 | 说明 | 重点强调 |
|---|---|---|
| 变量声明 | 类型 变量名; |
⚠️ 使用前必须先声明 |
| 变量初始化 | 类型 变量名 = 值; |
定义时赋值称为初始化 |
| 整数类型 | int 存储整数(范围:-2^31 ~ 2^31-1) |
默认是有符号数 |
| 未初始化变量 | int choice; 未赋初值 |
⚠️ 包含随机值(垃圾值),使用前必须赋值 |
4. 数组(字符串)操作
char bookName[100] = "C程序设计语言";
char bookAuthor[50] = "Kernighan";
char bookIsbn[20] = "978-7-111-00101-0";
| 知识点 | 说明 | 重点强调 |
|---|---|---|
| 数组定义 | 类型 数组名[大小]; |
大小必须是常量表达式 |
| 字符数组 | char 类型数组用于存储字符串 |
每个字符占1字节 |
| 字符串初始化 | 用双引号 " " 直接赋值 |
⚠️ 自动在末尾添加 \0(结束符) |
| 数组大小 | 必须比实际字符串长度至少多1 | 要为 \0 预留空间 |
| 字符串结束符 | \0 是ASCII码为0的字符 |
⚠️ 不显示但占用内存,标志字符串结束 |
数组内存示意图:
bookName: [C][程][序][设][计][语][言][\0][?][?]...
0 1 2 3 4 5 6 7 8 9
↑ ↑
字符串内容 字符串结束符
5. 基本输入输出
// 输出
printf("当前管理图书:%s(ID: %d)\n", bookName, bookId);
// 输入
scanf("%d", &choice);
scanf("%s", bookName);
| 知识点 | 说明 | 重点强调 |
|---|---|---|
| printf | 格式化输出函数 | %d 整数,%s 字符串,\n 换行 |
| 格式占位符 | %d、%s、%c、%f 等 |
必须与参数类型严格匹配 |
| 转义字符 | \n 换行,\t 制表符 |
反斜杠 \ 开头 |
| scanf | 格式化输入函数 | ⚠️ 必须使用 & 取地址符(数组例外) |
| 取地址符 | & 获取变量的内存地址 |
⚠️ 数组名本身就是地址,不需要 & |
| 缓冲区 | 输入数据先存缓冲区 | ⚠️ scanf 遇到空格/Tab/换行会停止 |
scanf 常见陷阱:
// ❌ 错误:缺少 &
scanf("%d", choice); // 编译警告/运行崩溃
// ✅ 正确:加 &
scanf("%d", &choice);
// ✅ 数组不需要 &
scanf("%s", bookName); // bookName 本身就是地址
6. 算术运算与赋值
borrowed = borrowed + 1; // 等价于 borrowed++
stock - borrowed // 减法运算
borrowed > stock // 比较运算
| 知识点 | 说明 | 重点强调 |
|---|---|---|
| 赋值运算 | = 将右侧值赋给左侧变量 |
⚠️ 是赋值,不是数学等号 |
| 算术运算 | + - * / %(取余) |
整数除法会截断小数部分 |
| 复合赋值 | += -= *= /= |
borrowed += 1 等价于 borrowed = borrowed + 1 |
| 自增运算 | ++ 自增1,-- 自减1 |
borrowed++ 先用后加,++borrowed 先加后用 |
| 关系运算 | > < >= <= == != |
⚠️ == 是相等判断,= 是赋值(易混淆!) |
重点强调:
// 常见的错误写法
if (borrowed = stock) // ❌ 赋值操作,不是比较!
if (borrowed == stock) // ✅ 正确的比较
7. 分支结构(if-else-if)
if (choice == 1) {
// 修改图书信息
} else if (choice == 2) {
// 借书操作
} else if (choice == 3) {
// 还书操作
} else if (choice == 4) {
// 显示信息
} else if (choice == 5) {
// 退出程序
} else {
// 无效选择
}
| 知识点 | 说明 | 重点强调 |
|---|---|---|
| if 语句 | if (条件) { 语句块 } |
条件为真(非0)时执行 |
| else if | 多重条件判断 | 依次检查,命中后跳出 |
| else | 所有条件都不满足时执行 | 可选的,但建议加上处理异常 |
| 条件表达式 | choice == 1 返回 0 或 1 |
0 表示假,非0 表示真 |
| 代码块 | { } 包裹多条语句 |
⚠️ 只有单条语句时可省略花括号,但不建议 |
执行流程图:
choice == 1? → 是 → 修改信息
↓ 否
choice == 2? → 是 → 借书
↓ 否
choice == 3? → 是 → 还书
↓ 否
choice == 4? → 是 → 显示信息
↓ 否
choice == 5? → 是 → 退出
↓ 否
else → 无效选择
8. 循环结构(while)
int running = 1; // 循环控制标志
while (running) {
// 菜单显示和操作处理
if (choice == 5) {
running = 0; // 改变条件,退出循环
}
}
| 知识点 | 说明 | 重点强调 |
|---|---|---|
| while 循环 | while (条件) { 循环体 } |
⚠️ 先判断条件,再执行循环体 |
| 循环条件 | running 非0时继续循环 |
0 表示假,非0 表示真 |
| 标志变量 | running 控制循环是否继续 |
又称"哨兵变量"或"开关变量" |
| 循环退出 | 修改条件变量或使用 break |
必须确保条件最终会变为假 |
| 无限循环 | while(1) { } 永不停止 |
⚠️ 必须有退出机制(break 或修改条件) |
关键点:
// 本程序的循环控制逻辑
int running = 1; // 1 表示"运行中"
while (running) { // running 为 1(真),继续循环
// ...
if (choice == 5) {
running = 0; // 改为 0(假),下次条件判断时退出
}
}
// 循环结束,执行后面的代码
9. 逻辑控制(标志变量)
int running = 1; // 控制程序是否继续运行
| 知识点 | 说明 | 重点强调 |
|---|---|---|
| 标志变量 | 用于控制程序流程的变量 | 通常用 0/1 或 true/false |
| 布尔含义 | 0 表示假(停止),非0 表示真(继续) | C语言没有专门的 bool 类型(C99有) |
| 命名规范 | 常用 flag、running、isXXX |
命名应清晰表达含义 |
10. 函数返回值
return 0;
| 知识点 | 说明 | 重点强调 |
|---|---|---|
| 返回值 | 将结果返回给调用者 | main 返回给操作系统 |
| 返回 0 | 约定 0 表示程序正常结束 | 非0 表示异常结束 |
| return 作用 | 结束当前函数执行 | ⚠️ main 中的 return 结束整个程序 |
11. 代码中的关键知识点总结
| 序号 | 语法类别 | 具体内容 | 代码行数位置(行号) |
|---|---|---|---|
| 1 | 预处理 | #include <stdio.h> |
11 |
| 2 | 函数定义 | int main() |
14 |
| 3 | 变量定义 | int bookId = 1001; |
17-25 |
| 4 | 数组定义 | char bookName[100] = "C程序设计语言"; |
18 |
| 5 | 字符串初始化 | 用双引号赋值字符数组 | 18-20 |
| 6 | 输入函数 | scanf("%d", &choice); |
54 |
| 7 | 输入函数(字符串) | scanf("%s", bookName); |
60 |
| 8 | 输出函数 | printf("当前管理图书:%s(ID: %d)\n", ...); |
34 |
| 9 | 转义字符 | \n 换行 |
多处 |
| 10 | 算术运算 | borrowed = borrowed + 1; |
81 |
| 11 | 比较运算 | borrowed < stock |
80 |
| 12 | if-else-if分支 | if (choice == 1) { ... } else if ... |
56-101 |
| 13 | while循环 | while (running) { ... } |
28-104 |
| 14 | 标志变量 | int running = 1; |
25 |
| 15 | 修改循环条件 | running = 0; |
92 |
| 16 | return语句 | return 0; |
107 |
12.最容易犯的错误
-
==和=混淆if (choice = 5) // ❌ 不是比较,是赋值!永远为真 if (choice == 5) // ✅ 正确比较 -
scanf忘记&scanf("%d", choice); // ❌ 缺少 &,运行崩溃 scanf("%d", &choice); // ✅ 正确 -
数组越界
char name[5]; scanf("%s", name); // 输入 "abcdef" 会溢出! -
字符串数组大小不足
char bookName[10] = "C程序设计语言"; // ❌ 超过10字节,中文占用更多 char bookName[100] = "C程序设计语言"; // ✅ 足够大 -
中文编码问题
-
一个中文字符在 UTF-8 编码下占用 3 字节
-
数组大小要留足余量
-