C 练习实例91(一文讲透)
💡一则或许对你有用的小广告
欢迎加入小哈的星球 ,你将获得:专属的项目实战(已更新的所有项目都能学习) / 1v1 提问 / Java 学习路线 / 学习打卡 / 每月赠书 / 社群讨论
- 新开坑项目:《Spring AI 项目实战》 正在持续爆肝中,基于 Spring AI + Spring Boot 3.x + JDK 21..., 点击查看 ;
- 《从零手撸:仿小红书(微服务架构)》 已完结,基于
Spring Cloud Alibaba + Spring Boot 3.x + JDK 17...
,点击查看项目介绍 ;演示链接: http://116.62.199.48:7070 ;- 《从零手撸:前后端分离博客项目(全栈开发)》 2 期已完结,演示链接: http://116.62.199.48/ ;
截止目前, 星球 内专栏累计输出 100w+ 字,讲解图 4013+ 张,还在持续爆肝中.. 后续还会上新更多项目,目标是将 Java 领域典型的项目都整一波,如秒杀系统, 在线商城, IM 即时通讯,权限管理,Spring Cloud Alibaba 微服务等等,已有 3700+ 小伙伴加入学习 ,欢迎点击围观
前言
在编程学习的旅程中,实践是检验知识的唯一标准。本文将以 C 练习实例91 为例,带领读者深入理解结构体、文件操作以及排序算法的综合应用。这一实例不仅考察基础语法的掌握,更强调代码的逻辑设计能力。无论是编程初学者还是希望巩固基础的中级开发者,都能通过本文获得启发。
二级标题:实例概述与目标
C 练习实例91 的典型题目可能是这样的:
"编写一个程序,读取学生姓名、学号、成绩等信息,将其保存到文件中,并支持从文件读取数据后按成绩排序输出。"
这一实例的核心目标包括:
- 理解结构体(struct)的定义与使用
- 掌握文件的读写操作(fopen, fwrite, fread)
- 学习排序算法(如冒泡排序)的基本实现
- 综合运用上述知识点完成一个完整功能
通过解决这一实例,读者不仅能巩固基础语法,还能培养将现实问题转化为代码的逻辑思维能力。
二级标题:结构体:数据容器的"快递单"比喻
什么是结构体?
结构体(struct)可以看作是自定义的数据快递单。例如快递单需要记录收件人姓名、电话、地址等信息,结构体则允许我们将不同数据类型(如 char
, int
)组织成一个有意义的整体。
示例代码:
struct Student {
char name[50];
int id;
float score;
};
结构体变量的声明与使用
struct Student stu1;
strcpy(stu1.name, "张三"); // 注意:字符数组用strcpy赋值
stu1.id = 1001;
stu1.score = 89.5f;
常见误区提醒:
- 结构体名前必须带
struct
关键字(除非已用typedef
定义) - 字符数组需用
strcpy
等函数赋值,不可直接赋值(如stu1.name = "李四"
是错误的)
二级标题:文件操作:与硬盘对话的艺术
文件操作如同与"数据保险柜"的交互,需要遵循严格的流程:
- 打开保险柜(fopen)
- 存取数据(fwrite/fread)
- 关闭保险柜(fclose)
文件操作核心函数详解
函数名 | 功能描述 | 模式参数示例 |
---|---|---|
fopen | 打开文件 | "students.dat", "w+" |
fwrite | 写入二进制数据 | sizeof(struct Student) |
fread | 读取二进制数据 | &stu, 1, sizeof(struct Student) |
fclose | 关闭文件 | fp |
示例代码:写入数据
FILE *fp = fopen("students.dat", "wb");
struct Student stu = {"王五", 1002, 92.0};
fwrite(&stu, sizeof(struct Student), 1, fp);
fclose(fp);
关键点说明:
- 使用
wb
模式表示二进制写入,避免文本模式下的换行符转换问题 fwrite
的第三个参数是"元素个数",第四个是文件指针
二级标题:排序算法:让数据"排队"的智慧
冒泡排序的直观比喻
排序算法如同"整理书架":
- 比较相邻书籍的高度
- 交换位置更矮的书籍
- 重复操作直到有序
冒泡排序实现代码:
void bubbleSort(struct Student arr[], int n) {
for (int i = 0; i < n-1; i++) {
for (int j = 0; j < n-i-1; j++) {
if (arr[j].score < arr[j+1].score) { // 降序排列
struct Student temp = arr[j];
arr[j] = arr[j+1];
arr[j+1] = temp;
}
}
}
}
算法优化思路
- 提前终止:若某轮未发生交换,说明已有序
- 双向冒泡:同时处理最大和最小值
二级标题:完整代码实现与调试技巧
完整程序代码
#include <stdio.h>
#include <string.h>
struct Student {
char name[50];
int id;
float score;
};
void displayStudents(struct Student arr[], int count) {
for (int i = 0; i < count; i++) {
printf("Name: %s | ID: %d | Score: %.1f\n",
arr[i].name, arr[i].id, arr[i].score);
}
}
int main() {
struct Student students[100];
int count = 0;
char choice;
FILE *fp = fopen("students.dat", "wb+");
if (!fp) {
printf("文件打开失败\n");
return 1;
}
// 输入学生信息
do {
struct Student temp;
printf("输入姓名:");
fgets(temp.name, 50, stdin);
temp.name[strcspn(temp.name, "\n")] = 0; // 去除换行符
printf("输入学号:");
scanf("%d", &temp.id);
getchar(); // 清除缓冲区
printf("输入成绩:");
scanf("%f", &temp.score);
getchar();
fwrite(&temp, sizeof(struct Student), 1, fp);
count++;
printf("继续输入(Y/N)? ");
scanf("%c", &choice);
getchar();
} while (choice == 'Y' || choice == 'y');
// 读取并排序
fseek(fp, 0, SEEK_SET); // 移动文件指针到开头
count = 0;
while (fread(&students[count], sizeof(struct Student), 1, fp) == 1) {
count++;
}
bubbleSort(students, count);
displayStudents(students, count);
fclose(fp);
return 0;
}
调试与常见问题
- 文件写入后无法读取:检查
fopen
模式是否正确,确保写入后重置文件指针(fseek
) - 字符串显示异常:
fgets
输入时的换行符需处理,避免截断 - 排序结果错误:检查比较条件是否与预期一致(升序/降序)
二级标题:进阶思考与扩展方向
性能优化建议
- 二进制 vs 文本存储:二进制读写速度快但可读性差,文本存储更易调试
- 内存管理:对于大量数据,考虑分批读取而非一次性加载
功能扩展方向
- GUI界面:使用图形库(如Windows API或跨平台库)
- 数据库集成:用SQLite替代文件存储
- 网络通信:通过TCP/IP协议实现多用户协作
结论
通过 C 练习实例91 的实践,我们不仅掌握了结构体、文件操作和排序算法的核心知识,更理解了如何将离散知识点整合为完整解决方案。编程如同搭建积木,每个概念都是基础模块,而解决问题的过程就是将这些模块组合成有意义的"建筑"。建议读者在掌握本文内容后,尝试以下练习:
- 将排序算法改为快速排序
- 添加删除学生记录的功能
- 实现按学号查询功能
编程之路永无止境,每一次实践都是向高手进阶的阶梯。希望本文能成为您攻克 C 练习实例91 的有力工具,并激发更多探索的热情。