《程序设计基础》实验题目2 c文件读取(反序列化?) 链表排序

题目:

  每个学生的信息卡片包括学号、姓名和成绩三项。定义存储学生信息的单向链表的结点类型;编写函 数,由文件依次读入 n(n≥0)个学生的信息,创建一个用于管理学生信息的单向链表;编写函数,对 该链表进行整理,保证该单向链表的结点顺序满足学号从小到大的顺序。

 算法的设计与分析:

  1.  定义学生类型结构体(含有分量id,name,score),定义链表节点结构体(含有分量student结构体stu和指向下一个节点的指针next)
  2.  从文件读取,采用fopen方法返回FILE指针,用fscanf方法读取数据并创建节点组成链表
    1. 还可以使用freopen的方法,直接scanf即可
    2. 或者用我一开始的土方法,用fgets函数读取一行,用stroke分割该行字符串,将字符串转化成int,创建结构体。比上面的方法复杂多了。
  3.  按学号排序,采用插入排序的方法,插入排序,以sorted(初始为第一个元素)为边界,将sorted后的一个节点插在前面已经排好的链表中,直到sorted后没有节点

注意:

  1. char* 结构体*等指针要用必须分配空间
    1. 分配空间通常使用malloc函数,A* a=(*A)malloc(sizeof(A))
  2. malloc申请的空间要free掉,free(a)
  3. malloc和free这一对与new和delete这一对非常像,c++里动态分配空间用new,c里要用malloc

源代码(talk is cheap,show me the code)(屁话少说,放码过来)

 

  1 #include <stdio.h>
  2 #include<malloc.h>
  3 #define NAME_MAX 20 //名字的最长长度
  4 
  5 typedef struct my_student {
  6     int id;
  7     char* name;
  8     int score;
  9 } student;
 10 typedef struct my_list_node {
 11     student stu;
 12     struct my_list_node *next;
 13 } Node;
 14 
 15 Node* getStuFromFile(char *path) {
 16     //从文件中读取学生数据创建单链表并返回头指针
 17     FILE *stu_file;
 18     stu_file = fopen(path, "r");
 19     if (stu_file == NULL) {//如果路径不正确
 20         printf("file path error!");
 21         return 0;
 22     }
 23     //循环从文件中读取数据创建节点
 24     Node* head = (Node*)malloc(sizeof(Node));//哨兵节点
 25     Node* current_node = head;//用于循环赋值时表示当前节点
 26     while (!feof(stu_file)) {
 27         Node* temp = (Node*)malloc(sizeof(Node));
 28         //id ,name,score分别表示临时节点的student的id等
 29         int* id =&( temp->stu.id);
 30         temp->stu.name = (char*)malloc(sizeof(char)*NAME_MAX);
 31         char* name = temp->stu.name;
 32         int* score = &(temp->stu.score);
 33         //从文件中读取临时节点的各个数据并赋值
 34         fscanf(stu_file, "%d %s %d", id, name, score);
 35         //将临时节点设为当前节点的子节点
 36         current_node->next = temp;
 37         current_node = current_node->next;
 38     }
 39     current_node->next = 0;
 40     fclose(stu_file);
 41     return head;
 42 }
 43 void showStuInfor(Node* node) {
 44     //递归打印每个学生的信息
 45     if (node != 0) {
 46         printf("%d %s %d\n", node->stu.id, node->stu.name, node->stu.score);
 47         if (node->next != 0) {
 48             //递归
 49             showStuInfor(node->next);
 50         }
 51     }
 52 }
 53 
 54 void insertNode(Node* preL, Node* preR) {
 55     //在preL节点后插入preR后的节点
 56     Node* insert= preR->next;
 57     preR->next = preR->next->next;
 58     insert->next = preL->next;
 59     preL->next = insert;
 60 }
 61 void sortListByStuId(Node *head) {
 62     //插入排序,以sorted为边界,将sorted后的一个节点插在前面已经排好的链表中,直到sorted后没有节点
 63 
 64     //初始化sorted有一个节点,算是已经排好序
 65     Node* sorted = head->next;
 66     //将sorted后的一个节点插到前面
 67     while (sorted->next != 0) {
 68         Node* insert = sorted->next;
 69         Node* loc = head;
 70         //从head开始遍历该插入到什么地方
 71         while (insert->stu.id > loc->next->stu.id) {
 72             loc = loc->next;
 73         }
 74         //如果loc与sorted不相等执行插入,如果相等说明要插入的元素比sorted之前的都大,直接让sorted后移即可
 75         if (loc != sorted) {
 76             insertNode(loc, sorted);
 77         }
 78         else {
 79             sorted = sorted->next;
 80         }
 81     }
 82 }
 83 void freeNodes(Node* head) {
 84     //递归释放malloc申请的空间
 85     if (head != 0) {
 86         if (head->next != 0) {
 87             //释放name占用的空间
 88             free(head->next->stu.name);
 89             //递归释放
 90             freeNodes(head->next);
 91         }
 92         free(head);
 93     }
 94 }
 95 void test() {
 96     //测试函数
 97     //从文件中读取学生数据并打印
 98     char path[] = "D:\\student.txt";
 99     Node* students = getStuFromFile(path);
100     showStuInfor(students->next);
101     printf("\n sorted:\n");
102     //按学号排序后打印学生数据
103     sortListByStuId(students);
104     showStuInfor(students->next);
105     freeNodes(students);
106 }
107 
108 int main() {
109     test();
110 }

 

The end

 

转载于:https://www.cnblogs.com/maxzheng/p/c_exam2.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
链表存入文件需要进行序列操作,即将链表中的数据转为二进制数据流,然后写入文件中。读取文件中的数据则需要进行序列操作,即将文件中的二进制数据流转链表中的数据。 下面是一个示例代码: ```c #include <stdio.h> #include <stdlib.h> #include <string.h> typedef struct node { char data[50]; struct node* next; } Node; void add(Node** head, char* data) { Node* new_node = (Node*)malloc(sizeof(Node)); strcpy(new_node->data, data); new_node->next = NULL; if (*head == NULL) { *head = new_node; } else { Node* cur = *head; while (cur->next != NULL) { cur = cur->next; } cur->next = new_node; } } void serialize(Node* head, char* filename) { FILE* file = fopen(filename, "wb"); Node* cur = head; while (cur != NULL) { fwrite(cur->data, sizeof(char), strlen(cur->data) + 1, file); cur = cur->next; } fclose(file); } Node* deserialize(char* filename) { FILE* file = fopen(filename, "rb"); Node* head = NULL; char data[50]; while (fread(data, sizeof(char), 50, file) != 0) { add(&head, data); } fclose(file); return head; } int main() { Node* head = NULL; add(&head, "hello"); add(&head, "world"); serialize(head, "data.bin"); Node* new_head = deserialize("data.bin"); Node* cur = new_head; while (cur != NULL) { printf("%s ", cur->data); cur = cur->next; } printf("\n"); return 0; } ``` 代码中,`add`函数用于向链表中添加节点,`serialize`函数用于将链表序列文件中,`deserialize`函数用于从文件序列链表。 在序列时,我们使用了`fwrite`函数将字符串数据写入文件中。 在序列时,我们使用了`fread`函数从文件读取字符串数据,并调用`add`函数将其添加到链表中。 需要注意的是,在序列序列时,我们需要使用二进制文件模式(`"wb"`和`"rb"`),以确保在写入和读取数据时,不会将文本中的换行符等字符转换为其他字符,从而导致数据失真。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值