昨天忽然想写一个小型的信息管理系统了,用链表和文本文件存储信息,所以就回过头把链表看了一遍,下午的时候把框架打好了,学生信息只有学生姓名和学号。程序功能只具备:1、添加学生信息功能(内嵌查重功能),2、查找功能(根据学号查找),3、删除学生信息功能(内嵌一小小的登陆功能,登陆成功方可进行此操作)4、打印功能(把目前所有的学生信息打印出来)
对于添加信息这里,我采取的是用链表写入信息,每次写入一个学生信息,都会去检测是不是学号已经存在了。单次写完后将这条链的所有信息保存在文本内。每个学生占一行,姓名和学号用空格隔开。这里就有一个问题:如果我在这次写入操作时,写入的前后数据学号相同,它还是会当做有效的存储起来。(因为我可能这次写入了三个学生,在三个学生信息输入完成前,是没有保存的,所以输入后面那个学号,只是和已经保存好的信息比对,导致可能写入重复的学号。) 所以,在查重那里,我觉得可以直接加上保存的功能,如果当前的同学信息有效,直接保存。但是,重复的打开关闭文件肯定会导致运行效率降低的。
这里还有一个问题,也是以后写类似东西应该注意的地方:信息储存时,应该把最重要的东西放在前面。应该是 学号 姓名\n 而不是 姓名 学号\n。因为学号是唯一的,姓名可以重复,所以我们查找和删除都是通过学号进行,而放在前面有便于我们查找,可以节省很多操作和时间。
还有就是关于保存时回车键的保存,在每行信息后都应该是一个回车键,换到文件的下一行。但是在删除那里,我是通过一个二维数组来操作的,将每行数据都保存在二维数组内,如果找到学号了,那就跳到下一行,把本应放查找的学号的同学信息一行放下一行信息,最后将整个数组给重新写入替换原来的信息。在这里出现了一个Bug:如果删除的本身就是最后一行,那么就会导致文本内格式出现错误。所以:写文件,回车符使用一定要小心!回车符使用一定要小心!回车符使用一定要小心!
另外,字符串结尾的 \0 别忘了,二级和写项目这个都很重要!
有一个Bug是在首页的选择页面,我刚开始是用一个int型的变量来保存用户输入的选择项,用switch来控制选择的。但是用户如果不输入一个整数,输入一个文字、符号、或者是其他非数字,程序将出现不可预知的错误!所以我还是和以前一样,使用一个字符串(字符数组)保存用户的选择,如果长度大于1,那么提示错误,并按任意键返回首页,如果长度为1,将判断交给switch语句,里面的default语句可以帮助我提示用户错误信息,不至于让程序脱离掌控。
基本的代码如下:
#include <stdio.h>
#include <malloc.h>
#include <Windows.h>
#include <string.h>
/*函数声明*/
void shouye();
void AddMessage();
void chazhao();
void shanchu();
void duqu();
int panduan();
int denglu();
//定义一个学生的数据类型
struct Student
{
char name[20];
char num[20];
struct Student *next;
};
//主函数
int main(void)
{
shouye();
return 0;
}
//首页函数
void shouye(void)
{
char i[20] = {0};
while(1)
{
system("cls");
printf("********这是首页********\n");
printf("* 1、添加学生信息 *\n");
printf("* 2、查找学生信息 *\n");
printf("* 3、删除学生信息 *\n");
printf("* 4、打印学生信息 *\n");
printf("* 5、退出首页 *\n");
printf("************************\n");
scanf("%s",i);
if(strlen(i) > 1)
{
printf("输入错误\n");
system("pause");
continue;
}
switch(i[0])
{
case '1':AddMessage();break;
case '2':chazhao();break;
case '3':shanchu();break;
case '4':duqu();break;
case '5':return ;
default:printf("输入错误!\n");system("pause");break;
}
}
}
//添加信息函数
void AddMessage()
{
struct Student *pHead = NULL;
struct Student *p1,*p2;
char flag[2] = "0";
p1 = p2 = (struct Student*)malloc(sizeof(struct Student));
if(p1 == NULL || NULL == p2)
{
printf("内存分配失败\n");
return ;
}
printf("请输入学生的姓名,学号,用空格隔开,姓名为0时终止输入:");
scanf("%s%s",p1->name,p1->num);
while(strcmp(p1->name,"0") != 0 )
{
if(!panduan(p1))
break;
if(NULL == pHead)
pHead = p1;
else
p2->next = p1;
p2 = p1;
p1 = (struct Student*)malloc(sizeof(struct Student));
if(p1 == NULL)
{
printf("内存分配失败\n");
return ;
}
printf("请输入学生的姓名,学号,用空格隔开,姓名为0时终止输入:");
scanf("%s%s",p1->name,p1->num);
}
free(p1);
p1 = NULL;
p2->next = NULL;
system("pause");
return ;
}
//查找函数
void chazhao(void)
{
char temp[20] = {0},name[20] = {0},num[20];
FILE *fp = fopen("E:\\student.txt","r");
system("cls");
printf("请输入您想要查找的同学学号:");
scanf("%s",num);
while(fscanf(fp,"%s%s",temp,name)!=EOF)
{
if(strcmp(num,temp) == 0)
{
printf("您所查找的同学信息如下:\n");
printf("姓名:%s 学号:%s\n",name,temp);
system("pause");
fclose(fp);
return ;
}
}
printf("查无此人\n");
system("pause");
fclose(fp);
return ;
}
//删除操作时登陆函数
int denglu(void)
{
char zhanghao[20] = "唐小龙",zhanghao1[20] = {0};
int i;
printf("请输入管理员账号:");
scanf("%s",zhanghao1);
if(strcmp(zhanghao,zhanghao1) == 0)
{
printf("请输入密码:");
scanf("%d",&i);
if(520 != i)
{
system("cls");
printf("密码错误!\n");
system("pause");
return 0;
}
}
else
{
system("cls");
printf("账号错误!\n");
system("pause");
return 0;
}
printf("成功登陆!\n");
system("pause");
return 1;
}
//删除函数
void shanchu(void)
{
int i = 0,j = 0,k = 0,l = 0,flag = 0;
char temp[100] = {0},name[20] = {0},num[20],xin[500][50] = {0};
FILE *fp = fopen("E:\\student.txt","r");
if(!denglu())
return ;
duqu();
printf("\n请输入您想要删除的同学学号:");
scanf("%s",num);
while(fscanf(fp,"%s%s",temp,name)!=EOF)
{
l++;
i = j = 0;
if(strcmp(temp,num) == 0)
{
flag = 1;
continue;
}
else
{
while(temp[i] != '\0')
{
xin[k][i] = temp[i];
i++;
}
xin[k][i++] = ' ';
while(name[j] != '\0')
{
xin[k][i] = name[j++];
i++;
}
xin[k][i] = '\n';
xin[k][i+1] = '\0';
k++;
}
}
if(flag == 0)
{
printf("查无此人\n");
system("pause");
fclose(fp);
return ;
}
else
{
fclose(fp);
fp = fopen("E:\\student.txt","w");
for(i = 0;i <= k;i++)
{
fprintf(fp,"%s",xin[i]);
}
printf("删除完成!\n");
fclose(fp);
system("pause");
Sleep(1000);
}
duqu();
system("pause");
fclose(fp);
return ;
}
//打印信息函数
void duqu(void)
{
char num[20] = {0},name[20] = {0};
FILE *fp = fopen("E:\\student.txt","r");
if(fp == NULL)
{
printf("文件打开失败\n");
return ;
}
system("cls");
printf("\n目前已有的学生信息如下:\n");
while(fscanf(fp,"%s%s",num,name)!=EOF)
printf("姓名:%s 学号:%s\n",name,num);
fclose(fp);
printf("\n");
system("pause");
}
//判断函数,判断写入的学号是否已经存在
int panduan(struct Student *p2)
{
int i = 0,j = 0;
char temp[100] = {0},temp1[20] = {0};
FILE *fp = fopen("E:\\student.txt","r");
while(fgets(temp,100,fp) != NULL)
{
while(temp[i] != ' ')
{
temp1[j++] = temp[i++];
}
temp1[j] = '\0';
if(strcmp(p2->num,temp1) == 0)
{
printf("此学号已经存在,非法操作\n");
fclose(fp);
return 0;
}
i = j = 0;
}
fclose(fp);
fp = fopen("E:\\student.txt","a+");
fprintf(fp,"%s %s\n",p2->num,p2->name);
fclose(fp);
return 1;
}