其实,用链表与文件写学生管理系统内容可分为两大模块:
模块一:一个完整的创建、遍历、添加、删除、修改的链表;
模块二:读取/写入数据到文件。
模块一
一个链表,主要是malloc的正确使用。
定义一个带有结构指针的结构体,用malloc()动态开辟一个该结构体大小的内存用来作为节点,储存多个平行数据并且每动态开辟一个内存就要用这个内存里面的结构指针指向下一个开辟的内存(如果停止动态开辟内存,则需让这个指针指向NULL,作为Programmer都知道指针的潜在危险)。这个节点数量需用循环控制。malloc原型是 void* 类型,但在这里需要强制转换成结构类型使用。而且动态开辟内存不是每次都会成功,不成时mallco()会返回NULL,所以我们需要规范使用malloc()
1 typedef struct stu //定义结构体变量
2 {
3 ... //其他变量
4 struct stu* pnext; //结构体的内部指针
5 }STU; 6 STU* pNew 7 if(NULL == (pNew = (STU*)malloc(sizeof(STU)))) 8 /*请使用if来判断,这是有必要的*/ 9 { 10 perror("error..."); 11 exit(1); 12 } 13 pNew->pnext = NULL; 14 .../*其它代码*/ 15 free(pNew); 16 pNew = NULL;/*请加上这句*/
另外有一点不能直接看出的区别是,malloc 只管分配内存,并不能对所得的内存进行初始化,所以得到的一片新内存中,其值将是随机的。
关于添加、删除、修改需要对指针的灵活运用。
如果在头部添加/删除,则要注意head的移动;
在中间添加/删除,则注意利用循环定位准确;
在尾部添加/删除,则要注意新/末尾结构体里的pnext(结构指针)指向NULL。
模块二
主要在于如何把链表写进指定文件里和如何把文件里的内容如何读取到链表里。
可直接单独写一个模块函数用fprintf格式化向文件里写入
1 void PrintToTxt()
2 { 3 STU* pTemp = pStu->pnext; //pStu为头指针pTemp为移动指针 4 5 if ((fp = fopen("学生信息管理.txt", "w")) == NULL) //打开文件准备写入 6 { 7 printf("cannot open this file!\n"); 8 _getch(); 9 return; 10 } 11 12 while (pTemp != NULL) //开始写入,pTemp为NULL时停止写入 13 { 14 fprintf(文件指针, "输出格式", 附加参数列表); 15 pTemp = pTemp->pnext; 16 } 17 fclose(fp); 18 printf("out save!"); //写入成功 19 exit(0); 20 }
但是若要从文件中读取并且形成链表的形式,则需要先建立链表再从文件中读取数据
1 void ScanfTxt()
2 { 3 pStu = (STU*)malloc(sizeof(STU)); //动态开辟内存,创建链表 4 pStu->pnext = NULL; 5 6 STU* pTemp = pStu; 7 STU* pNew = NULL; 8 9 if ((fp = fopen("学生信息.txt", "r")) == NULL) 10 { 11 printf("cannot open this file\n!"); 12 _getch(); 13 exit(0); 14 } 15 16 while (1) //读取数据,直到数据为空是跳出 17 { 18 pNew = (STU*)malloc(sizeof(STU)); 19 pNew->pnext = NULL; 20 if (fscanf(文件指针, "格式字串符", 21 输入列表)==EOF) 22 { 23 free(pNew); //释放多余开辟的内存 24 break; 25 } 26 27 pTemp->pnext = pNew; 28 pTemp = pTemp->pnext; 29 } 30 fclose(fp); 31 32 } 33
这里并没有用到fread和fwrite
fread、fwrite是对二进制文件进行以二进制形式读写,以字节位计算长度,按照指定的长度和次数读取数据,遇到结尾或完成指定长度读取后停止。对于向文件里写入数据时所有字符都可以无效果的写入,比如遇见换行符则直接写入换行符并不会执行换行。
而fscanf、fprintf是从磁盘文件中读取数据,可以是二进制,也可以是其他形式,并且进行格式化读写。比如遇见换行符则会执行换行读写并不会读出或写入换行符。
这里用fscanf、fprintf主要利用可进行换行、格式化读写。