c语言项目驱动学习--实例化--001C的基础知识

本文通过图书管理系统,不同版本的迭代完成,融入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);

五、项目总结

知识点目录结构

  1. 头文件包含

  2. 主函数定义

  3. 变量定义与初始化

  4. 数组(字符串)操作

  5. 基本输入输出

  6. 算术运算与赋值

  7. 分支结构(if-else-if)

  8. 循环结构(while)

  9. 逻辑控制(标志变量)

  10. 函数返回值


📚 详细知识点讲解
1. 头文件包含
复制代码
#include <stdio.h>
知识点 说明 重点强调
预处理指令 #include 是预处理命令,在编译前处理 ⚠️ 必须以 # 开头,行末无分号
标准库 stdio.h = Standard Input Output 包含 printfscanf 等函数
尖括号 < > 表示从系统路径查找头文件 区别于双引号 " "(用户自定义头文件)

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有)
命名规范 常用 flagrunningisXXX 命名应清晰表达含义

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.最容易犯的错误
  1. === 混淆

    复制代码
    if (choice = 5)   // ❌ 不是比较,是赋值!永远为真
    if (choice == 5)  // ✅ 正确比较
  2. scanf 忘记 &

    复制代码
    scanf("%d", choice);  // ❌ 缺少 &,运行崩溃
    scanf("%d", &choice); // ✅ 正确
  3. 数组越界

    复制代码
    char name[5];
    scanf("%s", name);  // 输入 "abcdef" 会溢出!
  4. 字符串数组大小不足

    复制代码
    char bookName[10] = "C程序设计语言";  // ❌ 超过10字节,中文占用更多
    char bookName[100] = "C程序设计语言"; // ✅ 足够大
  5. 中文编码问题

    • 一个中文字符在 UTF-8 编码下占用 3 字节

    • 数组大小要留足余量