C语言信息管理系统
目录
前言
一、注意事项
二、代码内容
1.建立链表
2.主函数
3.判断函数
4.菜单函数
5.函数:录入数据
6.函数:保存数据
7.函数:读取数据
8.函数:输出数据
9.函数:查询数据
10.函数:删除数据
11.函数:修改数据
12.函数:排序
13.函数:区间查找
三、总结
前言
在翻弄文件夹的时候突然发现大一时候用C语言写的信息管理系统,总共960多行,当地时学的并不深入,只包含C语言和数据结构的一些内容非常容易理解,代码注释不全,语言不够高级,还望多多包涵。
一、注意事项
这是一个游戏玩家信息管理系统,内部包含庄园等级、采集、制作、战斗等级等内容,其中账号文件保存在了C:\\file\\account.data,游戏数据内容保存在了C:\\file\\practice.data,有需要的话可以在代码中自行修改。本系统运用了C语言、数据结构一些浅知识。包括文件的修改、链表、循环、数组、函数等等。
二、代码内容
1.建立链表
代码如下(示例):
//建立链表//VSSTUDIO
typedef struct player// 玩家信息 数组
{
char name[20]; //昵称
int house; //进入时间
int fight; //战斗等级
int make; //制作等级
int collect; //采集等级
} player;
typedef struct point//链表 大链表
{
player er; //上面的链表
struct point *next;
}point;
point *head= NULL;
首先建立一个链表,里面包含本系统所需要的数据,集合起来便于访问。
2.主函数
代码如下:
int main() //主函数开始
{
void first(); //声明函数
int judge(int a, int b);
void save();
void input();
void choice(int z);
void print();
void read();
point* find();
void sort();
int part_sort();
void delet();
void change();
void findnum(); //全部声明完成
printf("1.我有管理员账号 ");//主程序开始 往下用于登录系统选择登录方式
printf("2.我没有账号");
printf("\n");
printf("(初始密码为123456)"); //避免忘记,管理员再此显示,如有必要可删去本行
printf("\n");
int b;
int acc = 0;
int pass = 0;
scanf("%d", &b);
if (b == 1)
{
printf("请输入管理员密码");
printf("\n");
int pass;
scanf("%d", &pass);
while (pass !=123456) //在此可以修改管理员密码
{
printf("密码错误请重试");
printf("\n");
scanf("%d", &pass);
}
}
else if (b == 2) //没有账号的情况,需要注册,并且写入account.data文件里
{
FILE* fp;
if ((fp = fopen("C:\\file\\account.data", "r")) == NULL)//确定是否有历史账号
{
fp = fopen("C:\\file\\account.data", "w"); //判断是否存在账号文件
fclose(fp);
}
system("cls"); //刷屏
fp = fopen("C:\\file\\account.data", "a");
while (1)
{
printf("请注册账号\n\n");
printf("请输入账号\n"); //注册账号
printf("\n");
scanf("%d", &acc);
printf("请输入密码\n");
scanf("%d", &pass);
//密码不同的情况
int passa;
printf("请再次输入密码\n");
scanf("%d", &passa);
if (pass == passa)
{
fprintf(fp, "%d %d\n", acc, pass);
printf("注册成功!\n");
fclose(fp);
break;
}
else
{
printf("两次密码输入不同,请重新注册\n"); //两次密码不一致
}
}
while (1) //准备登入系统
{
printf("==========欢迎您管理员!!==========");
printf("\n");
printf("请输入账号\n");
scanf("%d", &acc);
printf("请输入密码\n");
scanf("%d", &pass);
if (judge(acc, pass) == 1)
{
printf("======登录成功======");
}
if (judge(acc, pass) == -1) //judge是判断函数
{
printf("密码错误");
}
if (judge(acc, pass) == 0)
{
printf("此用户不存在!");
}
break;
}
}
else
{
printf("something is wrong"); //登入失败
printf("\n");
return 0;
}
system("pause");
system("cls");
while (1)//欢迎函数调用,包含菜单选项,无限循环。
{
first(); //主程序内容正式开始
int flag;
scanf("%d", &flag);
if (flag >= 0 && flag < 10) //假如输入了正确数字
{
//选项========================================对应菜单函数
switch (flag)
{
case 0: //录入游戏信息
input();
break;
case 1: //保存游戏信息
save();
break;
case 2: //删除游戏信息
delet();
break;
case 3: //查找游戏信息这个代码较简单,没有写作函数而是直接写在了下方
{ point* q;
q = find();
if (q == NULL)
{
printf("没有找到这个玩家!");
printf("\n");
}
else
{
printf("以下为本玩家信息:");
printf("\n");
printf("玩家昵称:%s 庄园等级:%d 战斗等级:%d 制作等级:%d 采集等级:%d\n", q->er.name, q->er.house, q->er.fight, q->er.make, q->er.collect);
}system("pause");
system("cls");//清屏
break; }
case 4: //修改游戏信息
change();
break;
case 5: //排序游戏信息
sort();
break;
case 6:
return 0;//退出管理系统
break;
case 7: //读取游戏信息
read();
break;
case 8: //打印游戏信息
print();
break;
case 9:
findnum();//查找区间
break;
}
}
else
{
printf("输入错误,请重新输入"); //输入了错误的数字
system("pause");
system("cls");
}
}
return 0;
} //此处主函数结束
主函数是来调用所有函数,根据输入的数字不同来运行不同的函数
3.判断函数
代码如下:
//判断函数
int judge(int f,int e) //有返回值,在主函数中再做判断
//匹配数据库中的账号密码
{
FILE* fp;
int n = 0, i = 0;
int zhanghao;
int password;
if ((fp = fopen("C:\\file\\account.data", "r")) == NULL)//不存在读者文件
{
printf("\n 还未存在用户!请新建账户");
}
fp = fopen("C:\\file\\account.data", "r");
for (; !feof(fp);) //循环读取判断
{
fscanf(fp, "%d %d", &zhanghao, &password);
if (f == zhanghao)
{
if (e == password) //判断正确
{
fclose(fp);
return 1;
}
else //密码错误
{
fclose(fp);
return -1;
}
}
}
fclose(fp);
return 0;
}
函数用于判断输入的账号和密码是否匹配,判断是否能进入菜单界面,返回值有0、1、-1分别对应三种情况
4.菜单函数
//菜单函数
void first()
{
printf("==========================================================\n");
printf("===========欢迎使用游戏玩家等级信息管理系统=================\n");
printf("=========0.录入游戏信息 1.保存游戏信息============\n\n");
printf("=========2.删除游戏信息 3.查找游戏信息============\n\n");
printf("=========4.修改游戏信息 5.排序游戏信息============\n\n");
printf("=========6.退出管理系统 7.读取管理信息============\n\n");
printf("=========8.打印管理信息 9.查询庄园等级区间========\n\n");
printf("=======================================================\n");
}
表示的内容和主函数里的数字相对应,分别代表10个功能,也对应后面的十个函数。
5.函数:录入数据
//录入函数
void input() //录入信息
{
point* p1 = (point*)malloc(sizeof(point));
p1->next = NULL;
if (head == NULL)//头插法输入(链表的一种插入方式)
{
head = p1;
}
else
{
p1->next = head;
head = p1;
}
printf("输入玩家昵称:\n"); //输入各种信息
scanf("%s", p1->er.name);
printf("输入玩家庄园等级:\n");
scanf("%d", &p1->er.house);
printf("输入玩家战斗等级:\n");
scanf("%d", &p1->er.fight);
printf("输入玩家制作等级:\n");
scanf("%d", &p1->er.make);
printf("输入玩家采集等级:\n");
scanf("%d", &p1->er.collect);
printf(" 玩家信息录入成功\n");
system("pause");//暂停 (使界面更简洁)
system("cls");//清屏
}
录入函数仅仅是通过手动输入把数据录入的链表之中,而不是放入文件,这样可以使录入更加高效、便捷。
6.函数:保存数据
//保存数据函数 只是保存文件,意思是把数组里的内容保存到文件中
void save()
{
FILE* fp = fopen("C:\\file\\practice.data","w");//文件
if (fp==NULL)
{
printf("打开文件失败");
printf("\n");//磁盘损坏、储存已满的情况
return ;
}
//遍历链表
point* p=head;
fp= fopen("C:\\file\\practice.data", "a");
while(p!=NULL)
{/* char name[20]; //名字
int house; //庄园等级
int fight; //战斗等级
int make; //制作等级
int collect; //采集等级 */
fprintf(fp, "%s %d %d %d %d\n", p->er.name, p->er.house, p->er.fight, p->er.make, p->er.collect);
p=p->next;
}
fclose(fp);
printf("保存成功"); //保存文件
printf("\n");
system("pause");
system("cls");
}
保存函数使录入函数的后一步,即把链表里的数据写入文件中。之所以把他俩分开是为了提高效率,在录入函数之后可以对链表进行操作,可以在得到最终结果的时候写入文件,而不是频繁的读取文件,造成时间和性能资源的浪费。
7.函数:读取数据
//读取函数
void read() {
FILE* fp = fopen("C:\\file\\practice.data", "r");
if (fp == NULL)
{
printf("读取文件失败\n"); //由于位置原因无法打开文件
return;
}
player p2;
head = NULL;//临时补加
for (; !feof(fp);)
{
fscanf(fp, "%s%d%d%d%d\n",p2.name, &p2.house, &p2.fight, &p2.make, &p2.collect);// 注意此处!!!!
//printf("%s %d %d %d %d\n", p2.name, p2.house, p2.fight, p2.make, p2.collect);对应关系,注意顺序不能乱
point* p1 = (point*)malloc((sizeof(point)));
p1->next = NULL;//转换位置
point* p1_a;
for (int i = 0; i < 20; i++) //循环拷贝
{
p1->er.name[i] = p2.name[i];
}
p1->er.house = p2.house;
p1->er.fight = p2.fight;
p1->er.make = p2.make;
p1->er.collect = p2.collect; //把p2的数据拷贝到p1
if (head == NULL) //头插法插入数据
{
head = p1;
p1->next = NULL;
}
else
{
p1->next = head;
head = p1;
}
}
fclose(fp);
printf("加载数据成功\n"); //提示全部录入完毕
system("pause");
system("cls");
}
读取函数是把文件里的内容完全读取到链表P1中,因为数据无法再辅存即文件里进行改变,只能读取到内存链表中才能进行后一步的操作。
8.函数:输出数据
//输出函数
void print() {
printf("===========================================================\n");
printf(" 昵称 庄园等级 战斗等级 制作等级 采集等级 \n");
printf("===========================================================\n");
//遍历列表
point* p1 =head;
while(p1!=NULL)//循环输出,直到为空
{
printf("%-14s%-12d%-12d%-12d%-12d\n", p1->er.name, p1->er.house, p1->er.fight, p1->er.make, p1->er.collect);
p1 = p1->next;
}
system("pause");
system("cls");
}
输出函数即输出链表里的内容,显示在屏幕上。
9.函数:查询数据
//查找函数
point* find()
{
char pname[20];
printf("请输入要查找玩家的昵称\n");
scanf("%s", pname);
//遍历链表
point* p1 = head; //便利链表搜寻所要查找的名字(可能包括重名的)
while (p1 != NULL)
{
if (strcmp(p1->er.name, pname) == 0)
return p1;
p1 = p1->next;
}
return NULL;
}
查询函数,简单的遍历链表查询,搜索输入的玩家名字。
10.函数:删除数据
//删除函数)/*
/*int delet_a(char a[], char b[]) //可能是简单的删除函数,还没有测试XD
{
for (int i = 0; i < 20; i++)
{
if (a[i]!=b[i])
{
return 0;
}
}
return 1;
}*/
void delet()// 正经的删除函数
{
char pname[20];
printf("请输入删除玩家的名字\n");
scanf("%s",pname);
//若为头节点
point* p1;
p1 = head;//备份头文件,防止头文件丢失
//printf("%d", strcmp(p1->er.name, pname));
if (strcmp(p1->er.name, pname)==0)
{
head = head->next;
free(p1);
printf("删除成功\n");
}point* p7;
//如果不是头节点
while (p1->next->next!= NULL)
{
//printf("%d", strcmp(p1->er.name, pname));
if (strcmp(p1->next->er.name, pname) == 0)
{
p7 = p1->next;
//接着备份
p1->next = p1->next->next;
free(p7);
printf("\n删除成功\n");
break;
}
p1 = p1->next;
}
//如果是尾节点
if (p1 ->next->next== NULL)
{
if (strcmp(p1->next->er.name, pname) == 0)
{
p1->next = NULL;
}printf("\n删除成功\n");
}
system("pause");
printf("\n是否确认删除文件内容\n");
printf("1.确认 0.取消\n");
int flag;
scanf("%d", &flag);
if (flag==1)
{
FILE* fp = fopen("C:\\file\\practice.data", "w");
point* p = head;
while (p != NULL)
{/* char name[20]; //名字
int house; //庄园等级
int fight; //战斗等级
int make; //制作等级
int collect; //采集等级 */
fprintf(fp, "%s %d %d %d %d\n", p->er.name, p->er.house, p->er.fight, p->er.make, p->er.collect);
p = p->next;
}
fclose(fp);
printf("文件删除成功"); //保存文件
printf("\n");
system("pause");
system("cls");
}
else
{
system("cls");
}
}
删除函数比较麻烦它分了三种情况:头节点、中间节点和尾节点,删除方法也不同需要三种方式,所以代码很长。
11.函数:修改数据
//修改玩家信息 修改前需要读取数据
void change()
{
char name2[20];
printf("请输入需要修改玩家的昵称\n"); //输入需要修改的名字(名字默认不允许相同)
scanf("%s", name2);
point* p1_c = (point*)malloc((sizeof(point)));
p1_c = head;
while (p1_c != NULL) //循环寻找此人
{
if (strcmp(p1_c->er.name, name2) == 0)
{
printf("请输入修改后的玩家信息,依次为庄园等级,战斗等级,制作等级,采集等级\n");
scanf("%d,%d,%d,%d", &p1_c->er.house, &p1_c->er.fight, &p1_c->er.make, &p1_c->er.collect); //把修改后的数据计入链表
printf("修改成功!\n");
system("pause");
system("cls");
break;
}
p1_c = p1_c->next;
}
if (p1_c == NULL) //没有找到相关名字
{
printf("未找到相关玩家");
system("pause");
}
else //找到之后直接把现在的链表存入数据
{
//存入文件
system("pause"); //当时忘记上面写了保存函数,又在这傻傻的写了一遍
printf("\n是否确认修改文件内容\n");
printf("1.确认 0.取消\n");//最后判断是否输入到文件,因为输入到文件之后是不可逆的
int flag;
scanf("%d", &flag);
if (flag == 1)
{
FILE* fp = fopen("C:\\file\\practice.data", "w");
point* p = head;
while (p != NULL)
{
fprintf(fp, "%s %d %d %d %d\n", p->er.name, p->er.house, p->er.fight, p->er.make, p->er.collect);//输入数据
p = p->next;
}
fclose(fp);
printf("修改成功"); //保存文件
printf("\n");
system("pause");
system("cls");
}
}
}
修改函数起初只是修改了链表内的内容,所以运行修改函数之前必须读取数据,以至于为何要分开,还是为了避免过多的文件文件读取,毕竟内存读取速度可以达到辅存读取速度的500倍。在修改完链表内容后会让你判断是否写入文件或者继续修改。大大节省了运行时间。
12.函数:排序
//部分排序函数
int part_sort()
{
printf("请输入需要排序的数据\n");
printf("1.庄园等级 2.战斗等级\n");
printf("3.制作等级 4.采集等级\n");
int flag_1;
scanf("%d", &flag_1);
printf("请选择排序方式\n");
printf("1.正序 2.倒序\n");
int flag_2;
scanf("%d", &flag_2);
int flag_3;
flag_3 = flag_1 * 10 + flag_2;
return(flag_3);
}
//排序函数
void sort()
{
int flag_1;
int flag_2;
int flag_3;
flag_3 = part_sort();
flag_1 = flag_3 / 10;
flag_2 = flag_3 % 10;
//此时需要提前读取信息
//此时文本信息已经在链表内了
point* p3 ;
point* p4 ;
//第一种选项=========================================
if (flag_1 == 1 && flag_2 == 1)
{
p3 = head;
p4 = head->next;
while (p3->next!=0)
{
while (p4!=0)
{
if (p3->er.house > p4->er.house)
{
point* p5 = (point*)malloc((sizeof(point)));
/*5->er.house = p3->er.house;
p5->er.collect = p3->er.collect;
p5->er.fight = p3->er.fight;
p5->er.make = p3->er.make;
p5->er.name[20] = p3->er.name[20];
//比较麻烦但是简洁的替换方式
p3->er.house = p4->er.house;
p3->er.collect = p4->er.collect;
p3->er.fight = p4->er.fight;
p3->er.make = p4->er.make;
p3->er.name[20] = p4->er.name[20];
//第二遍
p4->er.house = p5->er.house;
p4->er.collect = p5->er.collect;
p4->er.fight = p5->er.fight;
p4->er.make = p5->er.make;
p4->er.name[20] = p5->er.name[20];*/
p5->er = p3->er;
p3->er = p4->er;
p4->er = p5->er;
//替换完成
free(p5);
}
p4 = p4->next;//后进;
}
//继续后进
p3 = p3->next;
p4 = p3->next;
}
printf("排序成功!请输出!");
printf("\n");
system("pause");
system("cls");
}
部分排序函数是用来判断想要查询的方法,即足足有八种情况,需要分别排序。(当时应该是为了完成作业凑字数,如果不需要的话留一种排序方法就行)
注释里是对排序的拆分,更加清晰如何变换数据(冒泡排序yyds),代码过于冗长,以上只放了第一种排序既庄园等级正序,便于观看。
以下是排序函数的剩余内容(剩余的7排序种方法)
//开始第二种情况
if (flag_1 == 2 && flag_2 == 1)
{
p3 = head;
p4 = head->next;
while (p3->next != NULL)
{
while (p4 != NULL)
{
if (p3->er.fight > p4->er.fight)
{
point* p5 = (point*)malloc((sizeof(point)));
p5->er = p3->er;
p3->er = p4->er;
p4->er = p5->er;//替换完成
free(p5);
}
p4 = p4->next;//后进;
}
//继续后进
p3 = p3->next;
p4 = p3->next;
}
printf("排序成功!请输出!");
printf("\n");
system("pause");
system("cls");
}
//开始第三种选项
if (flag_1 == 3 && flag_2 == 1)
{
p3 = head;
p4 = head->next;
while (p3->next != NULL)
{
while (p4 != NULL)
{
if (p3->er.make > p4->er.make)
{
point* p5 = (point*)malloc((sizeof(point)));
p5->er = p3->er;
p3->er = p4->er;
p4->er = p5->er;
//替换完成
free(p5);
}
p4 = p4->next;//后进;
}
//继续后进
p3 = p3->next;
p4 = p3->next;
}
printf("排序成功!请输出!");
printf("\n");
system("pause");
system("cls");
}
//第四种选项
if (flag_1 == 4 && flag_2 == 1)
{
p3 = head;
p4 = head->next;
while (p3->next != NULL)
{
while (p4 != NULL)
{
if (p3->er.collect > p4->er.collect)
{
point* p5 = (point*)malloc((sizeof(point)));
p5->er = p3->er;
p3->er = p4->er;
p4->er = p5->er;
//替换完成
free(p5);
}
p4 = p4->next;//后进;
}
//继续后进
p3 = p3->next;
p4 = p3->next;
}
printf("排序成功!请输出!");
printf("\n");
system("pause");
system("cls");
}
//第五种选项
if (flag_1 == 1 && flag_2 == 2)
{
p3 = head;
p4 = head->next;
while (p3->next != NULL)
{
while (p4 != NULL)
{
if (p3->er.house < p4->er.house)
{
point* p5 = (point*)malloc((sizeof(point)));
p5->er = p3->er;
p3->er = p4->er;
p4->er = p5->er;
//替换完成
free(p5);
}
p4 = p4->next;//后进;
}
//继续后进
p3 = p3->next;
p4 = p3->next;
}
printf("排序成功!请输出!");
printf("\n");
system("pause");
system("cls");
}
//第六种选项
if (flag_1 == 2 && flag_2 == 2)
{
p3 = head;
p4 = head->next;
while (p3->next != NULL)
{
while (p4 != NULL)
{
if (p3->er.fight < p4->er.fight)
{
point* p5 = (point*)malloc((sizeof(point)));
p5->er = p3->er;
p3->er = p4->er;
p4->er = p5->er;
//替换完成
free(p5);
}
p4 = p4->next;//后进;
}
//继续后进
p3 = p3->next;
p4 = p3->next;
}
printf("排序成功!请输出!");
printf("\n");
system("pause");
system("cls");
}
//第七种选项
if (flag_1 == 3 && flag_2 == 2)
{
p3 = head;
p4 = head->next;
while (p3->next != NULL)
{
while (p4 != NULL)
{
if (p3->er.make < p4->er.make)
{
point* p5 = (point*)malloc((sizeof(point)));
p5->er = p3->er;
p3->er = p4->er;
p4->er = p5->er;
//替换完成
free(p5);
}
p4 = p4->next;//后进;
}
//继续后进
p3 = p3->next;
p4 = p3->next;
}
printf("排序成功!请输出!");
printf("\n");
system("pause");
system("cls");
}
//第八种选项
if (flag_1 == 4 && flag_2 == 1)
{
p3 = head;
p4 = head->next;
while (p3->next != NULL)
{
while (p4 != NULL)
{
if (p3->er.collect < p4->er.collect)
{
point* p5 = (point*)malloc((sizeof(point)));
p5->er = p3->er;
p3->er = p4->er;
p4->er = p5->er;
//替换完成
free(p5);
}
p4 = p4->next;//后进;
}
//继续后进
p3 = p3->next;//
p4 = p3->next;
}
printf("排序成功!请输出!");
printf("\n");
system("pause");
system("cls");
}
}
所用方法和第一种一样。没有做过多解释。
13.函数:区间查找
void findnum()//区间查找//只能进行庄园等级查找
{
int a, b;
printf("请输入查询庄园等级的下限");
scanf("%d", &a);
printf("请输入查询庄园等级的上限");
scanf("%d", &b);
//需要提前遍历链表 一定要提前读取数据
point* p1 = head;
point* p2= (point*)malloc(sizeof(point));
point* head_a=NULL;
while (p1!=NULL)
{
if (((p1->er.house)>a)&&((p1->er.house)<b))//判断是否在区间内
{
point* p3 = (point*)malloc(sizeof(point));
p3->er = p1->er;
p3->next = NULL;
if (head_a == NULL)//头文件为空
{
head_a = p2;
p2->er= p3->er;
p2->next = NULL;
printf("%d", p2->er.house);
}
else//头文件不为空
{
p2->next= p3;
printf("%d", p2->er.house);
}
p2 = p2->next;
}
p1 = p1->next;
}
printf("区间提取成功\n");
printf("按任意键输出\n");
system("pause");
point* p4 = head_a;
if (head_a==NULL)
{
printf("没有找到相关项");
}
while (p4 != NULL) //输出在区间内的玩家信息
{
printf("===========================================================\n");
printf(" 昵称 庄园等级 战斗等级 制作等级 采集等级 \n");
printf("===========================================================\n");
printf("%-14s%-12d%-12d%-12d%-12d\n", p4->er.name, p4->er.house, p4->er.fight, p4->er.make, p4->er.collect);
p4 = p4->next;
}
system("pause");
system("cls");
}
区间查找前必须读取数据,因为只能查找链表里的数据,查找过后输入到P4链表并且输出。
三、总结
本章系统是玩家信息管理系统,可实现对玩家信息的各种修改,其中涉及到对数据修改或查找的务必要提前读取数据到链表,无法直接从文件中查找、修改信息。文中提到的两个文件在不存在的情况下会自动生成。其中排序函数过于繁琐,可以适当删去。把以上所有的代码按照顺序放在一起既可以运行。
内容有些过于简单,没有运行用高级代码,还望多多包涵;如有错误,还希望各位指正。文章来源:https://www.toymoban.com/news/detail-502664.html
全代码文件https://download.csdn.net/download/weixin_52582099/85815994文章来源地址https://www.toymoban.com/news/detail-502664.html
到了这里,关于非常简单的C语言 信息管理系统 (内含源代码)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!