单向链表的学习
经验教训:
1. fflush(stdin);
scanf()函数接收输入数据时,遇以下情况结束一个数据的输入:(不是结束该scanf函数,scanf函数仅在每一个数据域均有数据,并按回车后结束)。
① 遇空格、“回车”、“跳格”键。
② 遇宽度结束。 ③ 遇非法输入。
键盘缓冲区就可能有残余信息问题。
scanf()函数应该只是扫描stdin流,这个残存信息是在stdin中
解决就要在scanf()函数之后加个fflush(stdin)。
2.删除节点后,由于之前建立或添加时申请了内存,此时应用free()函数释放内存。以免引起内存泄露,对内存失去控制,造成内存的浪费的不良影响。
3.转义字符
fp=fopen("F:\student.txt","w");
在该语句中\即代表,文件地址为F:student.txt,复制后应改为F:\student.txt。
fp=fopen("student.txt","w");
直接写地址,则在程序文件目录下添加student.txt文件。
4. fwrite 和fpintf 区别:
fwrite写的是二进制内容,fprintf写的是数字转换成ASCII码之后的字符。
例如:两者都把数字64写入一个文件,用记事本打开看下,fwrite写的打开是乱码,fprintf写入的是6和4这两个字符。因为fwrite写的是64的二进制表示(4个字节,前面全是0,最后八位是0100000),fprintf写入的实际内容是36H和34H(16进制表示的字符6和字符4的ASCII编码)。
fread 与fscanf同理。
代码如下:
#include <stdio.h> #include <stdlib.h> #include <string.h> #define NULL 0 struct student { char name[20]; int num; char sex; float score; struct student *next; }; struct student *head = NULL; //函数声明 void board();//界面 struct student *creat();//创建节点 void add();//添加学生信息 void add_tou();//从头插入 void add_wei();//从尾插入 void add_any();//插入指定位置 void delete_stu();//删除学生信息 void delete_name();//按姓名查找删除 void delete_num();//按学号查找删除 void find();//查找学生信息 void find_name();//按姓名查找 void find_num();//按学号查找 void display_all();//显示所有学生信息 struct student *save(struct student *head);//保存链表数据到文件 struct student *read();//从文件读取链表 int main() { int choice = -1; do { board(); printf("请选择功能(0-7): "); scanf("%d",&choice); switch(choice) { case 1: creat();break; case 2: add();break; case 3: delete_stu();;break; case 4: find();break; case 5: display_all();break; case 6: save(head);break; case 7: read();break; case 0: exit(0);break; default :break; } }while(choice); return 0; } void board()//界面 { printf(" 学生信息系统 "); printf(" 1.创建学生信息链表 2.添加学生信息 "); printf(" 3.删除学生信息 4.查找学生信息 "); printf(" 5.显示所有学生信息 6.保存链表数据到文件 "); printf(" 7.从文件读取链表 0.退出 "); } struct student *creat()//创建节点 { struct student *p1,*p2; int i,count; printf("输入几个学生信息? "); scanf("%d",&count); p1=p2=(struct student*)malloc(sizeof(struct student)); printf("请输入学生姓名 学号 性别 成绩 "); scanf("%s %d %c %f",p1->name,&p1->num,&p1->sex,&p1->score); fflush(stdin); head=p1; for(i=1;i<count;i++) { p1=(struct student*)malloc(sizeof(struct student)); scanf("%s %d %c %f",p1->name,&p1->num,&p1->sex,&p1->score); fflush(stdin); p2->next=p1; p2=p1; } p2->next=NULL; return head; } void add()//添加学生信息 { int choice = -1; printf("请选择添加位置:1.从头插入 2.从尾插入 3.插入指定位置 0.取消 "); scanf("%d",&choice); switch(choice) { case 1: add_tou();break; case 2: add_wei();break; case 3: add_any();break; case 0: break; default: add();break; } } void add_tou()//从头插入 { struct student *pnew; pnew = (struct student*)malloc(sizeof(struct student)); printf("请输入需添加的学生姓名 学号 性别 成绩: "); scanf("%s %d %c %f",pnew->name,&pnew->num,&pnew->sex,&pnew->score); pnew->next = head; head = pnew; } void add_wei()//从尾插入 { struct student *pnew,*pold; pnew = (struct student*)malloc(sizeof(struct student)); printf("请输入需添加的学生姓名 学号 性别 成绩: "); scanf("%s %d %c %f",pnew->name,&pnew->num,&pnew->sex,&pnew->score); pold = head; while(pold->next != NULL) pold = pold->next; pold->next = pnew; pnew->next = NULL; } void add_any()//插入指定位置 { int weizhi,i; struct student *pnew,*pold; pnew = (struct student*)malloc(sizeof(struct student)); printf("请输入需添加的学生姓名 学号 性别 成绩: "); scanf("%s %d %c %f",pnew->name,&pnew->num,&pnew->sex,&pnew->score); printf("请输入需插入的位置:"); scanf("%d",&weizhi); pold = head; for(i=0;i<weizhi-2;i++) { pold = pold->next; if(pold->next == NULL) //如位置超出人数 则插在队尾 break; } pnew->next = pold->next; pold->next = pnew; } void delete_stu()//删除学生信息 { int choice = -1; if(head == NULL) printf("无学生信息! "); else { printf("选择删除方式: 1.按姓名查找删除 2.按学号查找删除 0.取消 "); scanf("%d",&choice); switch(choice) { case 1: delete_name();break; case 2: delete_num();break; case 0: break; default:delete_stu();break; } } } void delete_name()//按姓名查找删除 { struct student *p1,*p2; char find_name[20]; int count = 0; printf("请输入需删除的学生姓名:"); scanf("%s",find_name); p1 = head; if(strcmp(find_name,head->name) == 0) { printf("学生 %s 信息已成功删除! ",head->name); p1 = head; head = head->next; free(p1);} //释放内存 else { while(p1 != NULL) { p2 = p1->next; if(strcmp(find_name,p2->name) == 0) { printf("学生 %s 信息已成功删除! ",p2->name); p1->next = p2->next;count++; free(p2);break;} //释放内存 p1 = p1->next; } if(count == 0) printf("无此学生信息! "); } } void delete_num()//按学号查找删除 { struct student *p1,*p2; int find_num,count = 0; printf("请输入需查找的学生学号:"); scanf("%d",&find_num); p1 = head; if(find_num == head->num) { printf("学生 %s 信息已成功删除! ",head->name); p1 = head; head = head->next; free(p1);} //释放内存 else { while(p1 != NULL) { p2 = p1->next; if(find_num == p2->num) { printf("学生 %s 信息已成功删除! ",p2->name); p1->next = p2->next;count++; free(p2);break;} //释放内存 p1 = p1->next; } if(count == 0) printf("无此学生信息! "); } } void find()//查找学生信息 { int choice = -1; if(head == NULL) printf("无学生信息! "); else { printf("选择查找方式: 1.按姓名查找 2.按学号查找 0.取消 "); scanf("%d",&choice); switch(choice) { case 1: find_name();break; case 2: find_num();break; case 0: break; default: find();break; } } } void find_name()//按姓名查找 { struct student *p; char find_name[20]; int count = 0; printf("请输入需查找的学生姓名:"); scanf("%s",find_name); p = head; while(p != NULL) { if(strcmp(find_name,p->name) == 0) { printf("%s %d %c %.2f ",p->name,p->num,p->sex,p->score); p = p->next; count++;} else p = p->next; } if(count == 0) printf("查无此人! "); } void find_num()//按学号查找 { struct student *p; int find_num,count = 0; printf("请输入需查找的学生学号:"); scanf("%d",&find_num); p = head; while(p != NULL) { if(p->num == find_num) { printf("%s %d %c %.2f ",p->name,p->num,p->sex,p->score); p = p->next; count++;} else p = p->next; } if(count == 0) printf("查无此人! "); } void display_all()//显示所有学生信息 { struct student *p; p=head; if(p == NULL) printf("无学生信息! "); else{ printf("学生姓名 学号 性别 成绩: "); while(p != NULL) { printf("%s %d %c %.2f ",p->name,p->num,p->sex,p->score); p=p->next; } } } struct student *save(struct student *head)//保存链表数据到文件 { struct student *p; FILE *fp; p=head; if((fp = fopen("student.txt","w")) == NULL)// 易错 \= printf("文件无法打开! "); else fp=fopen("student.txt","w"); while(p != NULL) { fprintf(fp,"%s %d %c %.2f ",p->name,p->num,p->sex,p->score); p=p->next; } fclose(fp); printf("保存成功! "); return head; } struct student *read()//从文件读取链表 { struct student *p1,*p2; FILE *fp; int flag = 1; fp=fopen("student.txt","r"); printf("学生姓名 学号 性别 成绩 "); while(!feof(fp)) { if(flag == 1) { p1=(struct student *)malloc(sizeof(struct student)); head=p1; p2=p1; fscanf(fp,"%s %d %c %f ",p1->name,&p1->num,&p1->sex,&p1->score); printf("%s %d %c %.2f ",p1->name,p1->num,p1->sex,p1->score); flag--; } else { p1=(struct student *)malloc(sizeof(struct student)); fscanf(fp,"%s %d %c %f ",p1->name,&p1->num,&p1->sex,&p1->score); printf("%s %d %c %.2f ",p1->name,p1->num,p1->sex,p1->score); p2->next=p1; p2=p1; } } p2->next = NULL; fclose(fp); return head; }