学生管理系统 添加文本存储读取; 文件读写复制练习
This commit is contained in:
parent
44331f7bba
commit
5408f0b622
43
day14/homework/h1.c
Normal file
43
day14/homework/h1.c
Normal file
@ -0,0 +1,43 @@
|
||||
// 随机生成10位学生的成绩并写入到score.txt文件中
|
||||
// 【要求】随机生成学号和成绩,每一行存储一位学生的成绩,学号与成绩之间用 ","逗号分隔。
|
||||
// 【提示】成绩范围[0, 100]
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
|
||||
typedef struct stu_s
|
||||
{
|
||||
int sid;
|
||||
char dh; // 逗号
|
||||
float score;
|
||||
|
||||
struct stu_s *next;
|
||||
} STU;
|
||||
|
||||
int main()
|
||||
{
|
||||
FILE *fp = fopen("score.txt", "w");
|
||||
srand(time(NULL));
|
||||
// float scorex = rand() % 101;
|
||||
for (int i = 0; i < 10; i++)
|
||||
{
|
||||
if (NULL == fp)
|
||||
{
|
||||
perror("fopen");
|
||||
return 1;
|
||||
}
|
||||
STU *stu = malloc(sizeof(STU));
|
||||
|
||||
stu->sid = i + 1;
|
||||
stu->dh = ','; // 间隔的逗号
|
||||
stu->score = rand() % 101;
|
||||
fwrite(stu, sizeof(STU), 1, fp);
|
||||
// fputc('\n', fp); // 添加换行
|
||||
|
||||
free(stu);
|
||||
}
|
||||
|
||||
fclose(fp);
|
||||
|
||||
return 0;
|
||||
}
|
48
day14/homework/h2.c
Normal file
48
day14/homework/h2.c
Normal file
@ -0,0 +1,48 @@
|
||||
// 按行读取score.txt文件的所有内容,打印成绩及格的学号和成绩。
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
|
||||
typedef struct stu_s
|
||||
{
|
||||
int sid;
|
||||
char dh; // 逗号
|
||||
float score;
|
||||
|
||||
struct stu_s *next;
|
||||
} STU;
|
||||
|
||||
int main()
|
||||
{
|
||||
FILE *fp = fopen("score.txt", "r");
|
||||
|
||||
if (NULL == fp)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
// 计算文件大小
|
||||
fseek(fp, 0, SEEK_END);
|
||||
long file_size = ftell(fp);
|
||||
printf("score.txt 文件大小: %ld B\n", file_size);
|
||||
|
||||
// 重置光标位置
|
||||
fseek(fp, 0, SEEK_SET); // 等同于使用 rewind(fp);
|
||||
// 按照 STU 的结构存储数据,计算出以存放学生数量
|
||||
int stu_num = file_size / sizeof(STU);
|
||||
printf("学生数量: %d\n", stu_num);
|
||||
|
||||
printf("\n学号\t成绩\n");
|
||||
for (int i = 0; i < stu_num; i++)
|
||||
{
|
||||
STU *s = calloc(1, sizeof(STU));
|
||||
fread(s, sizeof(STU), 1, fp);
|
||||
if (s->score > 60)
|
||||
printf("%d\t%.2f\n", s->sid, s->score);
|
||||
free(s);
|
||||
}
|
||||
|
||||
fclose(fp);
|
||||
|
||||
return 0;
|
||||
}
|
99
day14/homework/h3.c
Normal file
99
day14/homework/h3.c
Normal file
@ -0,0 +1,99 @@
|
||||
// 按行读取score.txt文件的所有内容,并生成有序的链表,且打印链表数据。
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
|
||||
typedef struct stu_s
|
||||
{
|
||||
int sid;
|
||||
char dh; // 逗号
|
||||
float score;
|
||||
|
||||
struct stu_s *next;
|
||||
} STU;
|
||||
|
||||
// 打印链表
|
||||
void show(STU *head)
|
||||
{
|
||||
if (NULL == head)
|
||||
{
|
||||
printf("数据为空,无法打印\n");
|
||||
return;
|
||||
}
|
||||
STU *tp = head;
|
||||
printf("\n学号\t成绩\n");
|
||||
while (NULL != tp)
|
||||
{
|
||||
printf("%d\t%.2f\n", tp->sid, tp->score);
|
||||
tp = tp->next;
|
||||
}
|
||||
}
|
||||
|
||||
// 添加学生
|
||||
STU *insert_stu(STU *head, STU *item)
|
||||
{
|
||||
// 如果头指针为空,说明链表为空,直接将新建的节点作为头指针
|
||||
if (head == NULL)
|
||||
{
|
||||
head = item;
|
||||
}
|
||||
else
|
||||
{
|
||||
// 如果头指针不为空,说明链表不为空,需要找到链表的尾部,将新建的节点插入到尾部
|
||||
STU *p = head; // 创建一个临时指针,用来保存头指针,防止头指针丢失
|
||||
while (p->next != NULL) // 当 p 的下一个节点不为空时,说明 p 不是尾部
|
||||
{
|
||||
p = p->next; // p 一直向后移动,直到找到尾部
|
||||
}
|
||||
p->next = item; // 将 item 插入到尾部
|
||||
}
|
||||
return head; // 返回头指针
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
FILE *fp = fopen("score.txt", "r");
|
||||
|
||||
if (NULL == fp)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
STU *head = NULL; // 建立链表头节点
|
||||
|
||||
// 计算文件大小
|
||||
fseek(fp, 0, SEEK_END);
|
||||
long file_size = ftell(fp);
|
||||
printf("score.txt 文件大小: %ld B\n", file_size);
|
||||
|
||||
// 重置光标位置
|
||||
fseek(fp, 0, SEEK_SET); // 等同于使用 rewind(fp);
|
||||
// 按照 STU 的结构存储数据,计算出以存放学生数量
|
||||
int stu_num = file_size / sizeof(STU);
|
||||
printf("学生数量: %d\n", stu_num);
|
||||
|
||||
// printf("\n学号\t成绩\n");
|
||||
for (int i = 0; i < stu_num; i++)
|
||||
{
|
||||
// 为新的链表节点分配内存空间
|
||||
STU *s = calloc(1, sizeof(STU));
|
||||
// 从文件中读取一个学生的数据
|
||||
fread(s, sizeof(STU), 1, fp);
|
||||
|
||||
head = insert_stu(head, s); // 插入链表节点
|
||||
}
|
||||
show(head); // 显示链表内容
|
||||
|
||||
// 最后循环释放动态申请的内存
|
||||
STU *free_tp = head;
|
||||
while (free_tp != NULL)
|
||||
{
|
||||
STU *to_free_this_p = free_tp;
|
||||
free_tp = free_tp->next;
|
||||
free(to_free_this_p);
|
||||
}
|
||||
|
||||
fclose(fp);
|
||||
|
||||
return 0;
|
||||
}
|
63
day14/homework/h4.c
Normal file
63
day14/homework/h4.c
Normal file
@ -0,0 +1,63 @@
|
||||
// 从score.txt中查找所有大于90分的学生信息(学号、成绩),并统计学生的数量和平均成绩。
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
|
||||
typedef struct stu_s
|
||||
{
|
||||
int sid;
|
||||
char dh; // 逗号
|
||||
float score;
|
||||
|
||||
struct stu_s *next;
|
||||
} STU;
|
||||
|
||||
int main()
|
||||
{
|
||||
FILE *fp = fopen("sxxx.dest", "rb");
|
||||
// FILE *fp = fopen("score.txt", "r");
|
||||
|
||||
if (NULL == fp)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
// 计算文件大小
|
||||
fseek(fp, 0, SEEK_END);
|
||||
long file_size = ftell(fp);
|
||||
printf("score.txt 文件大小: %ld B\n", file_size);
|
||||
|
||||
// 重置光标位置
|
||||
fseek(fp, 0, SEEK_SET); // 等同于使用 rewind(fp);
|
||||
// 按照 STU 的结构存储数据,计算出以存放学生数量
|
||||
int stu_num = file_size / sizeof(STU);
|
||||
printf("学生数量: %d\n", stu_num);
|
||||
|
||||
int above_90_stu_nums = 0; // 大于 90 分的学生数
|
||||
float sum_score_of_above_90_stus = 0.0f; // 大于 90 分学生的总成绩
|
||||
|
||||
// printf("\n学号\t成绩\n");
|
||||
for (int i = 0; i < stu_num; i++)
|
||||
{
|
||||
// 为新的链表节点分配内存空间
|
||||
STU *s = calloc(1, sizeof(STU));
|
||||
// 从文件中读取一个学生的数据
|
||||
fread(s, sizeof(STU), 1, fp);
|
||||
|
||||
if (s->score > 90)
|
||||
{
|
||||
above_90_stu_nums++;
|
||||
// printf("%.2f\n", s->score);
|
||||
sum_score_of_above_90_stus += s->score;
|
||||
}
|
||||
|
||||
free(s);
|
||||
}
|
||||
|
||||
float avg_score_of_above_90_stus = sum_score_of_above_90_stus / above_90_stu_nums;
|
||||
printf("\n大于 90 分的学生有 %d 位,他们的平均成绩为 %.2f\n", above_90_stu_nums, avg_score_of_above_90_stus);
|
||||
|
||||
fclose(fp);
|
||||
|
||||
return 0;
|
||||
}
|
35
day14/homework/h5.c
Normal file
35
day14/homework/h5.c
Normal file
@ -0,0 +1,35 @@
|
||||
// 设计函数, int filecpy(char *src_file, char *dst_file)的功能,实现文件src_file备份到dst_file, 如果成功返回 0, 失败返回 1
|
||||
#include <stdio.h>
|
||||
|
||||
int filecpy(char *src_file, char *dst_file)
|
||||
{
|
||||
FILE *aF = fopen(src_file, "rb");
|
||||
FILE *bF = fopen(dst_file, "wb");
|
||||
|
||||
if (NULL == aF)
|
||||
{
|
||||
perror("src_file fopen");
|
||||
return 1;
|
||||
}
|
||||
if (NULL == bF)
|
||||
{
|
||||
perror("dst_file fopen");
|
||||
return 1;
|
||||
}
|
||||
|
||||
int temp_c = fgetc(aF);
|
||||
while (temp_c != EOF)
|
||||
{
|
||||
fputc(temp_c, bF);
|
||||
temp_c = fgetc(aF);
|
||||
}
|
||||
fclose(aF);
|
||||
fclose(bF);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
filecpy("score.txt", "sxxx.dest");
|
||||
return 0;
|
||||
}
|
523
day14/homework/h6.c
Normal file
523
day14/homework/h6.c
Normal file
@ -0,0 +1,523 @@
|
||||
// 优化昨天的学生信息管理系统,将STU的数据持久化到stu.data文件中
|
||||
// 【提示】运行程序时,从文件中加载已有数据并生成链表,在退出程序时,将链表的数据更新到文件中。
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h> // malloc
|
||||
#include <string.h> // strcpy
|
||||
|
||||
typedef enum front_color_e
|
||||
{
|
||||
BLACK = 30, // 黑色
|
||||
RED, // 红色
|
||||
GREEN, // 绿色
|
||||
YELLOW, // 黄色
|
||||
BLUE, // 蓝色
|
||||
PURPLE, // 紫色
|
||||
CYAN, // 青色
|
||||
WHITE, // 白色
|
||||
} Front_Color; // 前景色
|
||||
|
||||
typedef enum back_color_e
|
||||
{
|
||||
BLACK_B = 40, // 黑色
|
||||
RED_B, // 红色
|
||||
GREEN_B, // 绿色
|
||||
YELLOW_B, // 黄色
|
||||
BLUE_B, // 蓝色
|
||||
PURPLE_B, // 紫色
|
||||
CYAN_B, // 青色
|
||||
WHITE_B, // 白色
|
||||
} Back_Color; // 背景色
|
||||
|
||||
typedef enum attr_e
|
||||
{
|
||||
BOLD = 1, // 加粗
|
||||
UNDERLINE = 4, // 下划线
|
||||
BLINK, // 闪烁
|
||||
REVERSE = 7, // 反显
|
||||
HIDE, // 隐藏
|
||||
} Attr; // 文本属性
|
||||
|
||||
// 定义学生信息结构体,链表的节点
|
||||
typedef struct stu_s
|
||||
{
|
||||
int sid;
|
||||
char name[32];
|
||||
int age;
|
||||
|
||||
struct stu_s *next;
|
||||
} STU;
|
||||
|
||||
// 节点交换
|
||||
void swap(STU *a, STU *b)
|
||||
{
|
||||
// 方法一: 直接通过临时指针交换数据
|
||||
// STU *tp = (STU *)malloc(sizeof(STU));
|
||||
// tp->sid = a->sid;
|
||||
// strcpy(tp->name, a->name);
|
||||
// tp->age = a->age;
|
||||
|
||||
// a->sid = b->sid;
|
||||
// strcpy(a->name, b->name);
|
||||
// a->age = b->age;
|
||||
|
||||
// b->sid = tp->sid;
|
||||
// strcpy(b->name, tp->name);
|
||||
// b->age = tp->age;
|
||||
// free(tp); // 释放临时指针
|
||||
|
||||
// 方法二: 通过结构体指针交换数据
|
||||
// 先换数据
|
||||
STU *tp = malloc(sizeof(STU));
|
||||
*tp = *a;
|
||||
*a = *b;
|
||||
*b = *tp;
|
||||
|
||||
// 再换指针的下一个节点指向
|
||||
tp->next = a->next;
|
||||
a->next = b->next;
|
||||
b->next = tp->next;
|
||||
|
||||
free(tp); // 释放临时指针
|
||||
}
|
||||
|
||||
// 添加学生
|
||||
STU *insert_stu(STU *head, STU *item)
|
||||
{
|
||||
// 如果头指针为空,说明链表为空,直接将新建的节点作为头指针
|
||||
if (head == NULL)
|
||||
{
|
||||
head = item;
|
||||
}
|
||||
else
|
||||
{
|
||||
// 如果头指针不为空,说明链表不为空,需要找到链表的尾部,将新建的节点插入到尾部
|
||||
STU *p = head; // 创建一个临时指针,用来保存头指针,防止头指针丢失
|
||||
while (p->next != NULL) // 当 p 的下一个节点不为空时,说明 p 不是尾部
|
||||
{
|
||||
p = p->next; // p 一直向后移动,直到找到尾部
|
||||
}
|
||||
p->next = item; // 将 item 插入到尾部
|
||||
}
|
||||
return head; // 返回头指针
|
||||
}
|
||||
|
||||
// 删除学生
|
||||
STU *delete_stu(STU *head, char sid)
|
||||
{
|
||||
if (NULL == head)
|
||||
{
|
||||
printf("\033[%dm无数据,无法删除\033[0m\n", RED);
|
||||
return NULL;
|
||||
}
|
||||
if (head->sid == sid)
|
||||
{
|
||||
// *tp 为临时指针,用来保存头指针
|
||||
STU *tp = head; // 保存头指针
|
||||
head = head->next; // 头指针指向下一个节点
|
||||
free(tp); // 释放头指针
|
||||
}
|
||||
else
|
||||
{
|
||||
STU *tp = head; // 保存头指针
|
||||
while (NULL != tp->next && sid != tp->next->sid) // 当 tp 的下一个节点不为空时,且下一个节点的学号不等于要删除的学号时,继续向后移动指针 tp
|
||||
{
|
||||
tp = tp->next; // tp 一直向后移动,直到找到尾部
|
||||
}
|
||||
if (NULL == tp->next) // 到达了链表尾部还是没有找到要删除的内容
|
||||
{
|
||||
printf("\033[%dm未找到 sid = %d 的学生,删除失败\033[0m\n", RED, sid);
|
||||
}
|
||||
else
|
||||
{
|
||||
STU *tpx = tp->next; // 保存要删除的节点
|
||||
tp->next = tpx->next; // 将链表位置指向要删除的节点的下一个节点
|
||||
free(tpx); // 释放要删除的节点
|
||||
printf("\033[%dm删除 sid = %d 的学生成功\033[0m\n", BLUE, sid);
|
||||
}
|
||||
}
|
||||
return head; // 返回头指针
|
||||
}
|
||||
|
||||
// 打印学生
|
||||
void shows(STU *head)
|
||||
{
|
||||
// 如果头指针为空,说明链表为空,直接返回
|
||||
if (head == NULL)
|
||||
{
|
||||
printf("\033[%dm无数据,无法打印\033[0m\n", RED);
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
// 如果头指针不为空,说明链表不为空,需要遍历链表,打印每一个节点的信息
|
||||
STU *p = head; // 创建一个临时指针,用来保存头指针,防止头指针丢失
|
||||
// 清屏
|
||||
// printf("\033[2J");
|
||||
printf("--------------------\n");
|
||||
printf("\033[%dm学号\t姓名\t年龄\033[0m\n", BLUE_B);
|
||||
while (p != NULL) // 当 p 不为空时,说明 p 不是尾部,则打印 p 的信息
|
||||
{
|
||||
printf("\033[%dm%d\t%s\t%d\033[0m\n", BLUE, p->sid, p->name, p->age); // 打印 p 的信息
|
||||
p = p->next; // p 一直向后移动,直到找到尾部
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 查询学生
|
||||
STU *find_stu(STU *head, char sid)
|
||||
{
|
||||
if (NULL == head)
|
||||
{
|
||||
printf("\033[%dm无数据,无法查询\033[0m\n", RED);
|
||||
return NULL; // 返回空指针,说明没有找到要查询的节点
|
||||
}
|
||||
|
||||
STU *tp = head; // 保存头指针
|
||||
while (NULL != tp->next && sid != tp->sid) // 当 tp 的下一个节点不为空时,且下一个节点的学号不等于要查询的学号时,继续向后移动指针 tp
|
||||
{
|
||||
tp = tp->next; // tp 一直向后移动,直到找到尾部
|
||||
}
|
||||
if (sid == tp->sid)
|
||||
return tp; // 返回当前节点的指针,即为要查询的节点
|
||||
return NULL; // 返回空指针,说明没有找到要查询的节点
|
||||
}
|
||||
|
||||
// 修改学生
|
||||
STU *update_stu(STU *head, char sid)
|
||||
{
|
||||
if (NULL == head)
|
||||
{
|
||||
printf("\033[%dm无数据,无法修改\033[0m\n", RED);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
STU *tp = find_stu(head, sid); // 查找要修改的节点
|
||||
if (tp == NULL)
|
||||
{
|
||||
printf("\033[%dm未找到 sid = %d 的学生\033[0m\n", RED, sid);
|
||||
}
|
||||
else
|
||||
{
|
||||
// 临时变量,用来保存要修改的学生信息
|
||||
char msid;
|
||||
char mname[32];
|
||||
int mage;
|
||||
|
||||
// 输入要修改的内容
|
||||
printf("输入要修改的学生的 学号 姓名 年龄: ");
|
||||
scanf("%hhd %s %d", &msid, mname, &mage);
|
||||
tp->sid = msid;
|
||||
strcpy(tp->name, mname);
|
||||
tp->age = mage;
|
||||
// 修改成功
|
||||
printf("\033[%dm修改 sid = %d 的学生成功\033[0m\n", BLUE, sid);
|
||||
}
|
||||
return head; // 返回头指针
|
||||
}
|
||||
|
||||
// 排序学生(选择排序,也可以使用归并排序)
|
||||
STU *sort_stu(STU *head)
|
||||
{
|
||||
if (NULL == head)
|
||||
{
|
||||
printf("\033[%dm无数据,无法排序\033[0m\n", RED);
|
||||
return NULL;
|
||||
}
|
||||
// 选择排序方式: 1) 按照sid 2)按照age
|
||||
int choose; // 选择排序方式
|
||||
printf("选择排序方式: 1) 按照sid 2)按照age: ");
|
||||
scanf("%d", &choose);
|
||||
if (1 == choose) // 按照sid排序
|
||||
{
|
||||
// 选择排序方式: 1) 升序 2)降序
|
||||
int choose2; // 选择排序方式
|
||||
printf("选择排序方式: 1) 升序 2)降序: ");
|
||||
scanf("%d", &choose2);
|
||||
if (1 == choose2) // 升序
|
||||
{
|
||||
// 按照sid升序排序
|
||||
STU *p = head; // 创建一个临时指针,用来保存头指针,防止头指针丢失
|
||||
while (p != NULL) // 相当于 for (int i = 0; i < len; i++)
|
||||
{
|
||||
STU *q = p->next; // 创建一个临时指针,用来保存头指针,防止头指针丢失
|
||||
while (q != NULL) // 相当于 for (int j = i + 1; j < len; j++)
|
||||
{
|
||||
if (p->sid > q->sid) // 相当于 if (arr[i] > arr[j])
|
||||
{
|
||||
swap(p, q); // 相当于 swap(arr[i], arr[j]
|
||||
}
|
||||
q = q->next;
|
||||
}
|
||||
p = p->next;
|
||||
}
|
||||
}
|
||||
else if (2 == choose2) // 降序
|
||||
{
|
||||
STU *p = head; // 创建一个临时指针,用来保存头指针,防止头指针丢失
|
||||
while (p != NULL)
|
||||
{
|
||||
STU *q = p->next; // 创建一个临时指针,用来保存头指针,防止头指针丢失
|
||||
while (q != NULL)
|
||||
{
|
||||
if (p->sid < q->sid)
|
||||
{
|
||||
swap(p, q);
|
||||
}
|
||||
q = q->next;
|
||||
}
|
||||
p = p->next;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// 选择错误
|
||||
printf("\033[%dm选择错误\033[0m\n", RED);
|
||||
}
|
||||
}
|
||||
else if (2 == choose) // 按照age排序
|
||||
{
|
||||
// 选择排序方式: 1) 升序 2)降序
|
||||
int choose2; // 选择排序方式
|
||||
printf("选择排序方式: 1) 升序 2)降序: ");
|
||||
scanf("%d", &choose2);
|
||||
if (1 == choose2) // 升序
|
||||
{
|
||||
STU *p = head; // 创建一个临时指针,用来保存头指针,防止头指针丢失
|
||||
while (NULL != p)
|
||||
{
|
||||
STU *q = p->next; // 创建一个临时指针,用来保存头指针,防止头指针丢失
|
||||
while (NULL != q)
|
||||
{
|
||||
if (p->age > q->age)
|
||||
{
|
||||
swap(p, q);
|
||||
}
|
||||
q = q->next;
|
||||
}
|
||||
p = p->next;
|
||||
}
|
||||
}
|
||||
else if (2 == choose2) // 降序
|
||||
{
|
||||
STU *p = head; // 创建一个临时指针,用来保存头指针,防止头指针丢失
|
||||
while (NULL != p)
|
||||
{
|
||||
STU *q = p->next; // 创建一个临时指针,用来保存头指针,防止头指针丢失
|
||||
while (NULL != q)
|
||||
{
|
||||
if (p->age < q->age)
|
||||
{
|
||||
swap(p, q);
|
||||
}
|
||||
q = q->next;
|
||||
}
|
||||
p = p->next;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// 选择错误
|
||||
printf("\033[%dm选择错误\033[0m\n", RED);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// 选择错误
|
||||
printf("\033[%dm选择错误\033[0m\n", RED);
|
||||
}
|
||||
return head; // 返回头指针
|
||||
}
|
||||
|
||||
// 反序学生(头变尾,尾变头)
|
||||
STU *reverse_stu(STU *head)
|
||||
{
|
||||
if (NULL == head)
|
||||
{
|
||||
printf("\033[%dm无数据,无法反序\033[0m\n", RED);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
STU *pi = head->next; // 当前节点的下一个节点地址
|
||||
head->next = NULL; // 把头节点的下一个节点置空,让头节点成为尾节点
|
||||
STU *tp = NULL; // 当前节点的下一个节点地址 pi 的下一个节点地址
|
||||
while (pi != NULL) // 当 pi 不为空时,说明 pi 不是尾部,则反序 pi 的信息
|
||||
{
|
||||
tp = pi->next; // 首先 tp 保存 pi 的下一个节点地址
|
||||
pi->next = head; // 然后把 pi 的下一个节点地址指向 head
|
||||
head = pi; // 然后让 hand 指向 pi
|
||||
pi = tp; // 最后找到新的 pi,即 tp
|
||||
}
|
||||
|
||||
printf("\033[%dm反序成功\033[0m\n", BLUE);
|
||||
return head; // 返回头指针
|
||||
}
|
||||
|
||||
// 保存数据到文件
|
||||
void saveToFile(STU *head, const char *filename)
|
||||
{
|
||||
FILE *file = fopen(filename, "w");
|
||||
if (file == NULL)
|
||||
{
|
||||
printf("\033[%dm无法打开文件, 保存数据失败\033[0m", RED);
|
||||
return;
|
||||
}
|
||||
|
||||
STU *current = head; // 定义临时指针,用来保存头指针,防止头指针丢失
|
||||
while (current != NULL) // 当 p 不为空时,说明 p 不是尾部,则打印 p 的信息
|
||||
{
|
||||
// 格式化存储数据,每个字段之间用逗号分隔
|
||||
fprintf(file, "%d,%s,%d\n", current->sid, current->name, current->age);
|
||||
current = current->next; // p 一直向后移动,直到找到尾部
|
||||
}
|
||||
printf("保存数据成功\n");
|
||||
fclose(file);
|
||||
}
|
||||
|
||||
// 从文件中读取数据
|
||||
STU *readFromFile(const char *filename)
|
||||
{
|
||||
FILE *file = fopen(filename, "r");
|
||||
if (file == NULL)
|
||||
{
|
||||
printf("\033[%dm无法打开文件, 加载数据失败\033[0m", RED);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
STU *head = NULL; // 定义头指针
|
||||
STU *prev = NULL; // 定义尾指针
|
||||
char line[100]; // 100 个字符的数组,用来保存每一行的数据
|
||||
|
||||
while (fgets(line, sizeof(line), file) != NULL) // 逐行读取文件内容
|
||||
{
|
||||
STU *node = (STU *)malloc(sizeof(STU)); // 申请一个节点的内存, 用来保存学生信息
|
||||
/*
|
||||
%d :表示读取一个整数,并将其存储在 &(node->sid)的地址中,即学生的学号。
|
||||
, :表示读取一个逗号,用于分隔学号和姓名之间的字段。
|
||||
%[^,] :表示读取一个字符串,直到遇到逗号为止,并将其存储在 node -> name 中,即学生的姓名。[^,] 表示匹配除逗号以外的任意字符。
|
||||
, :表示读取一个逗号,用于分隔姓名和年龄之间的字段。
|
||||
%d :表示读取一个整数,并将其存储在 &(node->age)的地址中,即学生的年龄。
|
||||
*/
|
||||
sscanf(line, "%d,%[^,],%d", &(node->sid), node->name, &(node->age)); // 将每一行的数据保存到节点中
|
||||
// fscanf() 每次执行后会丢失数据,所以需要使用 sscanf() 函数,原因是 fscanf() 函数会在每次执行后将文件指针向后移动,而 sscanf() 函数不会移动文件指针。
|
||||
// fscanf(file, "%d,%[^,],%d\n", &(node->sid), node->name, &(node->age)); // 将每一行的数据保存到节点中
|
||||
node->next = NULL; // 新建的节点的下一个节点指向空,因为是尾部插入
|
||||
|
||||
if (head == NULL) // 当头指针为空时,说明链表为空,直接将新建的节点作为头指针
|
||||
{
|
||||
head = node;
|
||||
}
|
||||
else // 否则,说明链表不为空,需要找到链表的尾部,将新建的节点插入到尾部
|
||||
{
|
||||
prev->next = node; // 将新建的节点插入到尾部
|
||||
}
|
||||
prev = node; // 将尾指针指向新建的节点
|
||||
}
|
||||
|
||||
fclose(file);
|
||||
printf("加载数据成功\n");
|
||||
return head;
|
||||
}
|
||||
|
||||
int main(int argc, char const *argv[])
|
||||
{
|
||||
STU *head = NULL; // 定义全局的头指针
|
||||
|
||||
// 声明临时变量,用来保存学生信息
|
||||
char tsid;
|
||||
char tname[32];
|
||||
int tage;
|
||||
|
||||
// // 创建几个学生信息,用于测试
|
||||
// STU *stu1 = (STU *)malloc(sizeof(STU));
|
||||
// stu1->sid = 1;
|
||||
// strcpy(stu1->name, "张三");
|
||||
// stu1->age = 18;
|
||||
// STU *stu2 = (STU *)malloc(sizeof(STU));
|
||||
// stu2->sid = 2;
|
||||
// strcpy(stu2->name, "李四");
|
||||
// stu2->age = 21;
|
||||
// STU *stu3 = (STU *)malloc(sizeof(STU));
|
||||
// stu3->sid = 3;
|
||||
// strcpy(stu3->name, "王五");
|
||||
// stu3->age = 15;
|
||||
// STU *stu4 = (STU *)malloc(sizeof(STU));
|
||||
// stu4->sid = 4;
|
||||
// strcpy(stu4->name, "赵六");
|
||||
// stu4->age = 13;
|
||||
// head = insert_stu(head, stu1);
|
||||
// head = insert_stu(head, stu2);
|
||||
// head = insert_stu(head, stu3);
|
||||
// head = insert_stu(head, stu4);
|
||||
|
||||
while (1)
|
||||
{
|
||||
// printf("\033[2J");
|
||||
// printf("--------------------\n");
|
||||
printf("\t\t \033[%d;%dm学生管理系统\033[0m\n\n", BOLD, CYAN_B);
|
||||
printf("\033[%d;%dm1) 添加学生 \t2) 删除学生 \t3) 打印 \n4) 查询 \t5) 修改 \t6) 排序 \n7) 反序 \t8) 加载数据 \t0) 退出(保存数据)\n请输入选项# \033[0m", BOLD, GREEN);
|
||||
int cmd = 0;
|
||||
scanf("%d", &cmd);
|
||||
switch (cmd)
|
||||
{
|
||||
case 0:
|
||||
// store_data(head); // 存储数据
|
||||
saveToFile(head, "stu.date");
|
||||
return 1;
|
||||
case 1:
|
||||
printf("输入学生的 学号 姓名 年龄: ");
|
||||
// 键盘收集数据并动态插入链表
|
||||
scanf("%hhd %s %d", &tsid, tname, &tage); // 键盘收集数据
|
||||
STU *item = (STU *)malloc(sizeof(STU)); // 申请一个节点的内存, 用来保存学生信息
|
||||
item->sid = tsid; // 保存学生学号到新建的节点
|
||||
strcpy(item->name, tname); // 保存学生姓名到新建的节点
|
||||
item->age = tage; // 保存学生年龄到新建的节点
|
||||
item->next = NULL; // 新建的节点的下一个节点指向空,因为是尾部插入
|
||||
head = insert_stu(head, item); // 将新建的节点插入到链表中
|
||||
break;
|
||||
case 2:
|
||||
printf("输入要删除的学生的学号: ");
|
||||
scanf("%hhd", &tsid);
|
||||
head = delete_stu(head, tsid);
|
||||
break;
|
||||
case 3:
|
||||
shows(head);
|
||||
break;
|
||||
case 4:
|
||||
printf("输入要查询的学生的学号: ");
|
||||
scanf("%hhd", &tsid);
|
||||
head = find_stu(head, tsid);
|
||||
if (head == NULL)
|
||||
{
|
||||
printf("\033[%dm未找到 sid = %d 的学生\033[0m\n", RED, tsid);
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("查询到的学生信息如下: \n");
|
||||
printf("\033[%dm学号\t姓名\t年龄\033[0m\n", BLUE_B);
|
||||
printf("\033[%dm%d\t%s\t%d\033[0m\n", BLUE, head->sid, head->name, head->age);
|
||||
}
|
||||
break;
|
||||
case 5:
|
||||
printf("输入要修改的学生的学号:");
|
||||
scanf("%hhd", &tsid);
|
||||
head = update_stu(head, tsid);
|
||||
break;
|
||||
case 6:
|
||||
printf("排序学生信息:\n");
|
||||
head = sort_stu(head);
|
||||
break;
|
||||
case 7:
|
||||
printf("反序学生信息:\n");
|
||||
head = reverse_stu(head);
|
||||
break;
|
||||
case 8:
|
||||
printf("加载数据......\n");
|
||||
head = readFromFile("stu.date");
|
||||
break;
|
||||
default:
|
||||
printf("\033[%dm选择错误\033[0m\n", RED);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
BIN
day14/homework/score.txt
Normal file
BIN
day14/homework/score.txt
Normal file
Binary file not shown.
2
day14/homework/stu.date
Normal file
2
day14/homework/stu.date
Normal file
@ -0,0 +1,2 @@
|
||||
4,赵六,13
|
||||
1,张三,14
|
BIN
day14/homework/stuManSys.out
Executable file
BIN
day14/homework/stuManSys.out
Executable file
Binary file not shown.
BIN
day14/homework/sxxx.dest
Normal file
BIN
day14/homework/sxxx.dest
Normal file
Binary file not shown.
BIN
day14/homework/xh1.out
Executable file
BIN
day14/homework/xh1.out
Executable file
Binary file not shown.
BIN
day14/homework/xh2.out
Executable file
BIN
day14/homework/xh2.out
Executable file
Binary file not shown.
BIN
day14/homework/xh3.out
Executable file
BIN
day14/homework/xh3.out
Executable file
Binary file not shown.
BIN
day14/homework/xh4.out
Executable file
BIN
day14/homework/xh4.out
Executable file
Binary file not shown.
BIN
day14/homework/xh5.out
Executable file
BIN
day14/homework/xh5.out
Executable file
Binary file not shown.
Loading…
x
Reference in New Issue
Block a user