这篇博客承接上一篇(https://blog.csdn.net/qq_41861442/article/details/99077592)加入了文件IO,每个简单程序都会面临这样的问题,数据无法保存,再次进入,数据全没了,那么我们就需要运用到文件IO的知识了,(没有数据库,bro)
在这里插入代码片#include<stdio.h>
#include<stdlib.h>
#include<stdbool.h>
#include<string.h>
typedef struct node
{
int id_num;//teacher or student's number
char status;//teacher : t , student : s
int chinese;
int math;
int English;
int passwd;
char address[64];
char sex;//man : m , women : w
struct node *next;
}*listnode;
listnode listnode_init()
{
listnode head = malloc(sizeof(struct node)); //申请头结点空间
if(head == NULL)
{
perror("list init error");
return NULL;
}
head->next = NULL;
return head;//返回头结点地址
}
void data_init(listnode newnode ,int id_num,char status,int chinese,int math ,int English , int passwd,char * address,char sex)
{
newnode->id_num = id_num;
newnode->status = status;
newnode->chinese = chinese;
newnode->math = math;
newnode->English = English;
newnode->passwd = passwd;
strcpy(newnode->address,address);
newnode->sex = sex;
}
bool add_node(listnode head,int id_num,char status,int chinese,int math ,int English , int passwd,char * address,char sex)
{
listnode newnode = malloc(sizeof(struct node));
if(newnode == NULL)
{
perror("malloc newnode error");
return -1;
}
//2、初始化节点数据
data_init(newnode ,id_num,status,chinese,math ,English,passwd,address,sex);
//3找到链表尾部
listnode p = head;
while(p->next != NULL) //如果p->next不等于 NULL,证明后面还有节点
{
p = p->next;
}
newnode->next = p->next;
p->next = newnode;
printf("尾插法所接入的数据 %d,%c\n", p->next->id_num,p->next->status);
return true;
}
listnode search_member_prev(listnode head ,int id_number)
{
listnode tmp = head ;
while(tmp->next != NULL)
{
if(tmp->next->id_num == id_number)
{
return tmp ;
}
tmp = tmp->next;
}
return NULL;
}
//传入头节点,和另一个节点
//函数中输入 id_num 和 passwd,若匹配,返回true
listnode login_in(listnode head,listnode newOne)
{
int passwdInput,id_num;
listnode new = head;
printf("please input your id_num(five Number): ");
if(scanf("%d",&(id_num)) == 1)
{
while(getchar() != '\n');
listnode tmp = search_member_prev(head,id_num);
if(tmp != NULL)
{
printf("please input your password :");
scanf("%d",&passwdInput);
while(getchar() != '\n');
if(tmp->next->passwd == passwdInput)
{
newOne = tmp;
return newOne;
}
}
}
return NULL;
}
int JudgeStuTea(listnode head ,listnode newOne)
{
printf("1");
int number = newOne->next->id_num ;
listnode tmp = search_member_prev(head,number);
if( tmp->next->status == 't')
{
printf("this is a teacher\n");
return 1;
}
else
return 0;
}
void show_grade(listnode newOne)
{
printf(" %d \n", newOne->next->id_num);
printf(" chinese : %d\n",newOne->next->chinese);
printf(" math : %d\n",newOne->next->math);
printf(" English : %d\n\n",newOne->next->English);
}
//修改密码
bool alter_passwd(listnode newOne)
{
char Judge;
int passwd;
printf("your password : %d\n",newOne->next->passwd);
printf("You are sure about changing Your pasword ? y/n : \n");
scanf("%c",&Judge);
while(getchar()!='\n');
if(Judge == 'y')
{
printf("please input your new password :\n");
scanf("%d",&passwd);
newOne->next->passwd = passwd;
printf("%d\n",newOne->next->passwd);
return true;
}
else
{
printf("don't waste my time , bitch !\n");
return false;
}
}
//学生操作
void StuMove(listnode head , listnode newOne)
{
int numberOption;
while(1)
{
printf(" hello ,%d \n",newOne->next->id_num);
printf(" press 0 : show your all grade \n\n");
printf(" press 1 : alter your passwd \n\n\n");
printf(" press 2 : exit\n\n");
printf(" Your option : \n");
scanf("%d",&numberOption);
while(getchar() != '\n');
switch(numberOption)
{
case 0:
show_grade(newOne);
break;
case 1:
alter_passwd(newOne);
break;
case 2:
info_save( head );
}
}
}
//打印所有的成员信息
void show_all(listnode head)
{
listnode tmp = head;
printf("\tI\tS\tC\tM\tE\tA\t\tSEX\n\n");
while(tmp->next != NULL)
{
printf("\t%d\t%c\t%d\t%d\t%d\t%s\t%c\t\n\n",tmp->next->id_num,tmp->next->status,tmp->next->chinese,tmp->next->math ,tmp->next->English ,tmp->next->address,tmp->next->sex);
tmp = tmp->next;
}
}
listnode add_grades(listnode head)
{
listnode tmp = head;
char addressInput[20];
while(tmp->next != NULL)
{
tmp = tmp->next;
}
listnode new = malloc(sizeof(struct node));
printf("\n\n");
printf("please input the student 's id : ");
scanf("%d",&(new->id_num));
while(getchar() != '\n');
printf("\n\n");
new->status = 's';
printf("please input the student 's chinese : ");
scanf("%d",&(new->id_num));
while(getchar() != '\n');
printf("\n\n");
printf("please input the student 's math : ");
scanf("%d",&(new->math));
while(getchar() != '\n');
printf("\n\n");
printf("please input the student 's English : ");
scanf("%d",&(new->English));
while(getchar() != '\n');
printf("\n\n");
printf("please input the student 's passwd : ");
scanf("%d",&(new->passwd));
while(getchar() != '\n');
printf("\n\n");
printf("please input the student 's address : ");
gets(addressInput);
strcpy(new->address,addressInput);
printf("\n\n");
printf("please input the student 's sex : ");
scanf("%c",&(new->sex));
while(getchar() != '\n');
tmp->next = new;
show_all(head);
return head;
}
//修改学生信息
bool alter_grades(listnode head,listnode newOne)
{
int id_num,grade,subject,judgeStu,teaSubject = 0;
printf("please input the student's id_num :");
scanf("%d",&id_num);
while(getchar() != '\n');
listnode tmp = search_member_prev(head ,id_num);
//根据id_num在学生列表中匹配学生,若匹配成功,且该id_num不是一个老师 tmp->next->status != 't'
//则进行下一步操作
if( ( tmp != NULL ) && (tmp->next->status != 't'))
{
printf("is he this guy ?(y:1,n:0)\n");
show_grade(tmp);
scanf("%d",&judgeStu);
while(getchar()!='\n');
if(judgeStu == 1)
{
//这里匹配登陆账号老师是教哪一科的,从而修改具体学生哪一科的成绩
if(newOne->next->math == -1)
{
printf(" how much about math : ");
scanf("%d",&(tmp->next->math));
show_grade(tmp);
return true;
}
else
if(newOne->next->chinese == -1)
{
printf(" how much about chinese : ");
scanf("%d",&(tmp->next->chinese));
show_grade(tmp);
return true;
}
else
if(newOne->next->English == -1)
{
printf(" how much about English : ");
scanf("%d",&(tmp->next->English));
show_grade(tmp);
return true;
}
}
}
return false;
}
//学生删除操作 参数:一个listnode 的头节点
void student_delete(listnode head)
{
int id_number,judgeStu;
listnode tmp = head;
listnode disap;
printf("who , delete :");
scanf("%d",&id_number);
//根据输入寻找学生,
tmp = search_member_prev(head ,id_number);
if(tmp != NULL)
{
printf("is he this guy ?(y:1,n:0)\n");
show_grade(tmp);
scanf("%d",&judgeStu);
if(judgeStu == 1)
{
disap = tmp->next;
tmp->next = tmp->next->next;
free(disap);
show_all(head);
printf("delete student successfully");
}
else
{
printf("delete failed");
}
}
}
//老师操作选项
//根据输入选择老师可以进行的功能
void TeaMove(listnode head,listnode newOne)
{
int options;
while(1)
{
printf(" welcome , %d",newOne->next->id_num);
printf(" press 0 : change your passwd\n");
printf(" press 1 : show the all grades\n");
printf(" press 2 : alter one student's grades\n");
printf(" press 3 : delete one student\n");
printf(" press 4 : add one student\n");
printf(" press 5 : exit\n\n");
scanf("%d",&options);
while(getchar()!= '\n');
switch(options)
{
case 0:
alter_passwd(newOne);
break;
case 1:
show_all(head);
break;
case 2:
alter_grades(head,newOne);
break;
case 3:
student_delete(head);
break;
case 4:
head = add_grades(head);
break;
case 5:
info_save( head );
}
}
}
void info_save( struct node *head )
{
int number = 0;
int i = 0 ;
struct node *tmpSave;
int ret;
FILE *fp = fopen("./stuInfo.txt","w+");
if(fp == NULL)
{
perror("fopen stuInfo.txt error");
return -1;
}
else
{
printf("fopen stuInfo.txt succeed\n");
}
listnode tmp = head;
while(tmp->next != NULL)
{
number++;
tmp = tmp->next;
}
tmp = head;
printf(" head : %d\n",number);
tmpSave = tmp->next;
for( i = 0 ; i < number ; i++ )
{
ret = fwrite(tmpSave,sizeof(struct node),1,fp);
tmpSave = tmpSave->next; //fseek(fp,sizeof(struct node),SEEK_CUR);
}
// printf(" end : %d\n",);
fclose(fp);
exit(0);
}
int main()
{
FILE *fp = fopen("./stuInfo.txt","r");
if(fp == NULL)
{
perror("fopen stuInfo.txt error");
return -1;
}
else
{
printf("fopen stuInfo.txt succeed\n");
}
int sizeOfStru = sizeof(struct node);
long sizeOfTXT ;
int struNumber;//stru number
if( fseek(fp,0,SEEK_END) == -1 )
{
perror(" set seek failed\n");
return -1;
}//get the size of txt
else
sizeOfTXT = ftell(fp);
printf(" number :%ld\n",sizeOfTXT);
rewind(fp);
struNumber =(int) (sizeOfTXT/sizeOfStru);// get how many strus
int i,ret;
printf(" fp : %ld\n",ftell(fp));
listnode head = listnode_init();
struct node tmp;
printf(" struNUmber : %d\n",struNumber);
for( i = 0 ; i < struNumber ; i++ )
{
ret = fread(&tmp,sizeOfStru,1,fp);
if( ret == 0 )
perror("fread txt file error\n");
add_node(head,tmp.id_num,tmp.status,tmp.chinese,tmp.math,tmp.English,tmp.passwd,tmp.address,tmp.sex);
printf(" fp : %ld\n",ftell(fp));
}
fclose(fp);
//先插入几个学生和老师的信息
/*
bool add_node(listnode head,int id_num,char status,int chinese,int math ,int English , int passwd,char * address,char sex)
{
add_node(head,20161,'t',-1,0,0,123456,"hubeijinghzou",'w');
add_node(head,20162,'t',0,-1,0,123457,"hubeiwuhan",'m');
add_node(head,20163,'t',0,0,-1,123458,"hubeixiaogan",'m');
add_node(head,20164,'s',59,60,61,123459,"hubeijingzhou",'w');
add_node(head,20165,'s',79,73,77,123450,"hubeijingzhou",'m');
add_node(head,20166,'s',99,83,87,223450,"hubeijingzhou",'m');
*/
//验证登陆信息
listnode newOne = head->next;
if(struNumber == 0)// if no member in txt , aumotically add a teacher information
{
add_node(head,20161,'t',-1,0,0,123456,"hubeijinghzou",'w');
}
while(1)
{
newOne = login_in(head,newOne);
if(newOne != NULL)
break;
}
//欢迎界面
printf("welcome to zhangke's school info manage system :\n\n");
//进行判断,如果是老师,进入 TeaMove
//如果是学生,进入StuMove
if( JudgeStuTea(head,newOne) == 1 )
TeaMove(head,newOne);
else
StuMove(head,newOne);
}
1数据读取部分,我们需要读取目标文件(我们数据存储的地方)的内容,有的话就读取到链表中,没有就自动先插入一个成员信息(用作登陆),
2最重要的部分:我们思考问题的时候尽量把问题简化,我们做这个系统如果每项功能都需要需要进行数据读取以及写入的话,那么我们的工作量就会急剧增加,这些数据我们函数运行的时候全部读取并放入到链表中,数据的增删改查结束后,再一次性全部写入到文件当中,这样在处理较小的数据量时,这样对我们的功能要求低一点