c语言中简易公交一卡通系统的实现
1.基本功能介绍:
系统启动则进入登陆菜单。
根据不同角色的选取来确定是普通用户还是管理员帐户
添加新卡
能够添加一张新卡,卡号按照自然数列向下自动产生,而用户名键盘输入,系统创建新卡用户,初始余额为0,状态为使用中。注销旧卡
由用户输入要注销的用户名,并输入要注销的卡号,若输入正确则显示卡用户注销成功!该卡状态为已注销。修改卡的信息
由用户输入自己的用户账号,如果输入正确的用户账号,则显示用户的旧用户名,然后由用户输入进行更改的用户名,并且输入两次,两次必须输入一致,若两次输入不一致,则需要重新输入,两次输入一致则显示用户名修改成功。查询所有用户信息及状态
系统显示目前的所有用户账号,用户名称,用户余额以及用户状态,状态显示为1则为可用,状态显示为0则为已注销。查询现有余额最多的用户
系统会自动找出目前余额最多的用户,并显示其全部信息。进入乘车读卡扣费界面
由用户输入自己的卡号,若输入卡号正确,则系统会要求输入乘坐的站数,站数为130站,10站以内1元,1115站2元,1620站3元,2125站4元,2630站5元。用户输入范围内的乘坐站数后显示交易成功,并扣除相应的金额,并显示本卡余额。若输入的站数不是130,则显示输入的站数非法,请重新刷卡。若输入的卡号不正确则会提示:该账户不存在,请联系管理员注册用户。公交一卡通充值
由用户输入要充值的卡号,若输入正确则显示账号名和用户名,用户再输入要充值的金额,出入完成后系统会显示充值成功;若输入的卡号不存在,则提示该账户不存在,请注册新用户。
2.设计思路
1.需要存储一定的信息,则考虑使用结构体进行存储,为了查找使用链表。
2.每次使用完程序关闭程序后将链表转存成进文件,下次打开该程序后将上次已经存入的数据转成链表进行相关操作。
3.代码
// An highlighted block/*编译项目:公交一卡通系统*//*编译环境:vs*//*编译人:李和平*/#define _CRT_SECURE_NO_WARNINGS#include<stdlib.h>#include<stdio.h>#include<Windows.h>#include<malloc.h>#include<time.h>#include<string.h>typedef struct Bus //自定义结构体{int num; //卡号从0开始依次上升char name[20]; //卡用户的姓名int money; //卡用户的余额默认为0int state;//用户状态默认为1(使用),状态为0(注销)struct Bus * pnext;//连接}Bus;static int NUMBER=0; //静态全局变量struct Bus * Head = NULL;//链表头指针struct Bus * End = NULL; //链表尾指针void Save()//存入板块{FILE * pfile=NULL;struct Bus * atemp=Head;if(atemp==NULL){return;}pfile=fopen("公交一卡通.dat","wb");//以二进制格式打开一个文件只用于写入。//如果该文件已存在则将其覆盖。//如果该文件不存在,创建新文件。if(pfile==NULL){printf("\n警告:用户数据丢失请检查!!!\n");}while(atemp!=NULL){fwrite(atemp,sizeof(struct Bus),1,pfile);/*是要输出数据的地址。要写入的字节数;要进行写入size字节的数据项的个数;目标文件指针。*/atemp=atemp->pnext; }fclose(pfile);}void Read()//读取板块{int count=0;FILE *fp;if ((fp = fopen("公交一卡通.dat", "rb")) == NULL ){printf("\n警告:用户数据丢失请检查!!!\n");return;}else{while(!feof(fp)){Bus * atemp=(struct Bus *)malloc(sizeof(struct Bus));fread(atemp, sizeof(struct Bus), 1, fp);count++;}fp = fopen("公交一卡通.dat", "rb");while(count!=1) {Bus * atemp=(struct Bus *)malloc(sizeof(struct Bus));fread(atemp, sizeof(struct Bus), 1, fp);if (NULL==Head||NULL==End) //排除只有头尾的情况{Head = atemp; //链表为空,新节点即是头也是尾End = atemp;}else{End->pnext =atemp; //新节点下一个指向尾End = atemp; //新节点变成尾}count--;}}fclose(fp);} void loading()//虚假的加载界面{int k=1;system("color 0c");for(;k<3;k++){system("cls");printf("| 请稍等. | \n");printf("| 加载中: -- | \n");Sleep(200);system("cls");printf("| 请稍等.. | \n");printf("| 加载中: \\ | \n");Sleep(200);system("cls");printf("| 请稍等... | \n");printf("| 加载中: || | \n");Sleep(200);system("cls");printf("| 请稍等....| \n");printf("| 加载中: // | \n");Sleep(200);system("cls");printf("| 请稍等..... | \n");printf("| 加载中: -- | \n");Sleep(200);system("cls");printf("| 请稍等...... | \n");printf("| 加载中: \\ | \n");Sleep(200);system("cls");printf("| 请稍等...... | \n");printf("| 加载中: || | \n");Sleep(200);system("cls");printf("| 请稍等...... | \n");printf("| 加载中: // | \n");Sleep(200);system("cls");}}void CreateList()//创建板块{Bus * atemp=(struct Bus *)malloc(sizeof(struct Bus));//空信息结点//struct Bus * temp =Head; //重新定义一个指针记住头strcpy(atemp->name,"--++--++");atemp->num =-1;atemp->state =-1;atemp->pnext =NULL;Head = atemp; //链表为空,新节点即是头也是尾End =atemp;//}void Add2() //回收板块{char name[20];struct Bus * atemp=Head;while(atemp!=NULL){if(atemp->state == 0){break;}atemp=atemp->pnext ;}printf("欢迎添加新用户:\n");Sleep(50);printf("请输入新用户的用户名\n");Sleep(50);scanf("%s",name);atemp->money =0;atemp->state =1;strcpy(atemp->name,name);printf("新卡用户创建成功!\n");Sleep(50);printf("卡号:%d\n",atemp->num );Sleep(50);printf("用户名:%s\n",atemp->name );Sleep(50);printf("余额:%d\n",atemp->money );Sleep(50);if(atemp->state ==1){printf("状态:使用中\n");Sleep(50);}else{printf("状态:已注销\n");Sleep(50);}system("pause");}void Add1() //添加板块{char name[20];Bus * atemp=(struct Bus *)malloc(sizeof(struct Bus));printf("欢迎添加新用户:\n");Sleep(50);printf("请输入新用户的用户名\n");Sleep(50);scanf("%s",name);atemp->money =0;atemp->state =1;atemp->num =NUMBER;strcpy(atemp->name,name);atemp->pnext =NULL;End->pnext = atemp; //新节点下一个指向尾End=atemp;//新节点变成尾printf("新卡用户创建成功!\n");Sleep(50);printf("卡号:%d\n",NUMBER);Sleep(50);printf("用户名:%s\n",atemp->name );Sleep(50);printf("余额:%d\n",atemp->money );Sleep(50);if(atemp->state ==1){printf("状态:使用中\n");Sleep(50);}else{printf("状态:已注销\n");Sleep(50);}NUMBER++;system("pause");}void Judge()//判断是否执行回收操作{struct Bus * atemp=Head->pnext ;int flag=0;while(atemp!=NULL){if(atemp->state ==0){Add2();flag=1;break;}atemp=atemp->pnext ;}if(flag==0){Add1();}}void Del(int i) //注销板块{struct Bus * atemp=Head;//把链表首节点地址给atempwhile(atemp!=NULL) //当指针没有指向空的时候就继续执行循环操作{if(atemp->num ==i) //判断卡号是否匹配{atemp->state =0;break;}atemp=atemp->pnext ;//指向指针的下一步}printf("卡用户注销成功!\n");Sleep(50);printf("卡号:%d\n",atemp->num );Sleep(50);printf("用户名:%s\n",atemp->name );Sleep(50);printf("余额:%d\n",atemp->money );Sleep(50);if(atemp->state ==1){printf("状态:使用中\n");Sleep(50);}else{printf("状态:已注销\n");Sleep(50);}system("pause");if(atemp->money !=0){printf("该卡注销成功!余额:%d\n",atemp->money );Sleep(50);printf("返还给卡主%d的余额\n",atemp->money );Sleep(50);atemp->money =0;system("pause");}}void Select(int i) //修改板块{char name[20],name1[20]; struct Bus * atemp=Head->pnext;//把有效信息的节点给atempwhile(atemp!=NULL) //指针没有指向空的时候继续执行循环操作 {if(atemp->num ==i){for(;;){printf("您好,您的旧用户名为:%s\n",atemp->name);Sleep(50);printf("请输入要进行更改的用户名:");Sleep(50);scanf("%s",name);printf("请再输入一遍:");Sleep(50);scanf("%s",name1);if(strcmp(name,name1)==0) //字符串比较函数{printf("两次输入一致,用户名修改成功!\n");Sleep(50);strcpy(atemp->name ,name); //把修改后的用户名给结构体system("pause");return ;}else{printf("两次输入不一致,请重新输入:\n");Sleep(50);system("pause");}}}atemp=atemp->pnext ;}}void TakeBus(int i,int j) //乘车板块{int k=0;struct Bus * atemp=Head->pnext;if(1<=j&&j<=10){k=1;}else if(11<=j&&j<=15){k=2;}else if(16<=j&&j<=20){k=3;}else if(21<=j&&j<=25){k=4;}else if(26<=j&&j<=30){k=5;}else if(j<=0||j>30){printf("您输入的站数非法,请重新刷卡!\n");system("pause");}while(atemp!=NULL){if(atemp->num ==i){switch (k){case 1:{if(atemp->money >=1){atemp->money =atemp->money -1;printf("交易成功!\n");Sleep(50);printf("您已成功扣费1元\n");Sleep(50);printf("本卡余额:%d 元\n",atemp->money );Sleep(50);system("pause");break;}else{printf("您的卡余额不足,余额:%d元,请使用现金支付。\n",atemp->money );Sleep(50);system("pause");return ;}}case 2:{if(atemp->money >=2){atemp->money =atemp->money -2;printf("交易成功!\n");Sleep(50);printf("您已成功扣费2元\n");Sleep(50);printf("本卡余额:%d 元\n",atemp->money );Sleep(50);system("pause");break;}else{printf("您的卡余额不足,余额:%d元,请使用现金支付。\n",atemp->money );Sleep(50);system("pause");return ;}}case 3:{if(atemp->money >=3){atemp->money =atemp->money -3;printf("交易成功!\n");Sleep(50);printf("您已成功扣费3元\n");Sleep(50);printf("本卡余额:%d 元\n",atemp->money );Sleep(50);system("pause");break;}else{printf("您的卡余额不足,余额:%d元,请使用现金支付。\n",atemp->money );Sleep(50);system("pause");return ;}}case 4:{if(atemp->money >=4){atemp->money =atemp->money -4;printf("交易成功!\n");Sleep(50);printf("您已成功扣费4元\n");Sleep(50);printf("本卡余额:%d 元\n",atemp->money );Sleep(50);system("pause");break;}else{printf("您的卡余额不足,余额:%d元,请使用现金支付。\n",atemp->money );Sleep(50);system("pause");return ;}}case 5:{if(atemp->money >=5){atemp->money =atemp->money -5;printf("交易成功!\n");Sleep(50);printf("您已成功扣费5元\n");Sleep(50);printf("本卡余额:%d 元\n",atemp->money );Sleep(50);system("pause");break;}else{printf("您的卡余额不足,余额:%d元,请使用现金支付。\n",atemp->money );Sleep(50);system("pause");return ;}}}}atemp=atemp->pnext ;}}void Search(int i) //查询板块{struct Bus * atemp=Head;while(atemp!=NULL){if(atemp->num ==i){printf("卡号:%d\n",atemp->num );Sleep(50);printf("用户名:%s\n",atemp->name );Sleep(50);printf("余额:%d\n",atemp->money );Sleep(50);if(atemp->state ==1){printf("状态:使用中\n");Sleep(50);}else{printf("状态:已注销\n");Sleep(50);}system("pause");return ;}atemp=atemp->pnext ;}}void Charge(int i) //充值板块 {int j;struct Bus *atemp=Head;while(atemp!=NULL){if(atemp->num ==i){for(;;){printf("您好!账号:%d 用户:%s\n",atemp->num ,atemp->name );Sleep(50);printf("请输入要充值的金额(最小单位为1元):\n");Sleep(50);scanf("%d",&j);if(j>=1){printf("提示:充值成功!\n");Sleep(50);atemp->money =atemp->money +j;system("pause");return ;}else{printf("提示:输入不合法!请重新输入\n");Sleep(50);system("pause");}}}atemp=atemp->pnext ;}}void Print()//打印板块 {struct Bus * btemp = Head->pnext ;printf("\n用户账号 用户名称 用户余额 用户状态(1为可用0为注销)\n");Sleep(50);while(btemp!=NULL){printf("%6d %8s %10d %10d \n",btemp->num,btemp->name ,btemp->money ,btemp->state );Sleep(50);btemp =btemp->pnext ;}system("pause");}void Choose() //统计板块{int i=-1,j=-1;struct Bus *atemp=Head;struct Bus *btemp=Head;while(atemp!=NULL){if(atemp->money >j&&atemp->state ==1){i=atemp->num ;j=atemp->money ;}atemp=atemp->pnext ;}printf("余额最多的用户为;\n");Sleep(50);while(btemp!=NULL){if(btemp->num ==i){printf("账号名称:%s\n",btemp->name );Sleep(50);break;}btemp=btemp->pnext ;}printf("账号:%d\n",i);Sleep(50);system("pause");}int Check(char name[20],int num)//身份认证板块{struct Bus * atemp=Head ;if(strcmp(name,"hp")==0&&num==123456){return 1;}while(atemp!=NULL){if((strcmp(atemp->name,name)==0)&&(atemp->num ==num )&&(atemp->state ==1)){return 2;}if((strcmp(atemp->name,name)==0)&&(atemp->num ==num )&&(atemp->state ==0)){return 3;}atemp=atemp->pnext ;}return 4;}int Checkbus(int num) //乘车身份认证{struct Bus * atemp=Head->pnext;while(atemp!=NULL){if(atemp->num ==num &&atemp->state ==1){return 4;}if(atemp->num ==num &&atemp->state ==0){return 5;}atemp=atemp->pnext ;}return 6;}void FreeLinkList() //释放链表板块{struct Bus * atemp = Head;while(Head !=NULL)//在没有到达尾部的时候{atemp=Head;//记录下一节点Head=Head->pnext ;//向后移动一个节点free(atemp);//释放上一节点}}void rem()//卡号计数器{struct Bus * atemp =Head->pnext ;while(atemp!=NULL){NUMBER++;atemp=atemp->pnext ;}}void menu()//菜单板块{int i=-1,j=-1,k=-1,m=-1,n=-1,p=-1,q=-1,num=0,busstation=-1;char name[20]={0};loading();/*CreateList();*/for(;;){system("cls");system("color 0c");printf("*******************************************\n");Sleep(50);printf("\n");Sleep(50);printf("您好!欢迎使用公交一卡通系统!\n");Sleep(50);printf("\n");Sleep(50);system("date/t");Sleep(50);system("time/t");Sleep(50);printf("\n");Sleep(50);printf("请选择你的身份:\n");Sleep(50);printf("\n");Sleep(50);printf("【1】公交一卡通 管理员\n");Sleep(50);printf("【2】公交一卡通 用户\n");Sleep(50);printf("【0】退出公交一卡通系统\n");Sleep(50);printf("\n");Sleep(50);printf("请选择要执行的操作:\n");Sleep(50);printf("\n");Sleep(50); scanf("%d",&i);switch (i){case 1:{printf("已选择:管理员。\n");Sleep(50);printf("请输入管理员账号:\n");Sleep(50);scanf("%s",name);printf("请输入管理员密码:\n");Sleep(50);scanf("%d",&j);if(Check(name,j)==1){for(;;){system("cls");system("color 0a");printf("*******************************************\n");Sleep(50);printf("欢迎 管理员:\n");Sleep(50);printf("请选择要执行的操作:\n");Sleep(50);printf("【1】添加新卡\n");Sleep(50);printf("【2】注销旧卡\n");Sleep(50);printf("【3】修改卡的信息\n");Sleep(50);printf("【4】查询所有用户信息及状态\n");Sleep(50);printf("【5】查询现有余额最多的用户\n");Sleep(50);printf("【6】进入乘车读卡扣费界面\n");Sleep(50);printf("【7】公交一卡通充值\n");Sleep(50);printf("【8】返回上一级\n");Sleep(50);printf("【0】关闭本系统\n");Sleep(50);scanf("%d",&k);switch (k){case 1:{Judge();break;}case 2:{printf("提示:请输入要注销的用户名\n");Sleep(50);scanf("%s",name);printf("请输入要注销的用户账号\n");Sleep(50);scanf("%d",&num);if(Check(name,num)==3) //已注销{printf("提示:该账户已注销\n");Sleep(50);printf("不能再次注销");Sleep(50);system("pause");}if(Check(name,num)==2) //未注销{Del(num); }else{printf("提示:该账户不存在\n");Sleep(50);printf("请核对后重新输入\n");Sleep(50);system("pause");}break;}case 3:{printf("请输入要修改的用户账号\n");Sleep(50);scanf("%d",&num);Select(num);break;}case 4:{Print();break;}case 5:{Choose();break;}case 6:{for(;;){system("cls");system("color 0b");printf("*******************************************\n");Sleep(50);printf("如需返回上一级请输入卡号为-1\n");Sleep(50);printf("欢迎 乘客:\n");Sleep(50);printf("请输入您的卡号:\n");Sleep(50);scanf("%d",&num);if(Checkbus(num)==4) //可用{printf("请输入您乘坐的站数(1-30):\n");Sleep(50);scanf("%d",&busstation);TakeBus(num,busstation);}else if(Checkbus(num)==5) //注销{printf("提示:该账户已注销\n");Sleep(50);printf("请联系管理员注册新用户\n");Sleep(50);printf("\n");Sleep(50);system("pause");}if(num==-1){break;}else if(Checkbus(num)==6) //帐户不存在{printf("提示:该账户不存在\n");Sleep(50);printf("请联系管理员注册用户\n");Sleep(50);printf("\n");Sleep(50);system("pause");}}break;}case 7:{printf("请输入要充值的卡号:\n");scanf("%d",&num);if(Checkbus(num)==4) //可用{Charge(num);}else if(Checkbus(num)==5) //注销{printf("提示:该账户已注销\n");Sleep(50);printf("请注册新用户\n");Sleep(50);printf("\n");Sleep(50);system("pause");}else if(Checkbus(num)==6) //帐户不存在{printf("提示:该账户不存在\n");Sleep(50);printf("请注册新用户\n");Sleep(50);printf("\n");Sleep(50);system("pause");}break;}}if(k==8){break;}if(k==0){break;}}}else{printf("提示:管理员密码或帐户输入错误\n");Sleep(50);printf("请核对身份信息后重试。\n");Sleep(50);printf("\n");Sleep(50);system("pause");}break;}case 2:{printf("已选择:用户。\n");Sleep(50);printf("请输入用户名称:\n");Sleep(50);scanf("%s",name);printf("请输入用户卡号:\n");Sleep(50);scanf("%d",&num);if(Check(name,num)==2){for(;;){system("cls");system("color 0e");printf("*******************************************\n");Sleep(50);printf("欢迎 用户:\n");Sleep(50);printf("请选择要执行的操作:\n");Sleep(50);printf("【1】查询本卡的信息\n");Sleep(50);printf("【2】修改公交一卡通账户名\n");Sleep(50);printf("【3】公交一卡通充值\n");Sleep(50);printf("【4】注销公交一卡通\n");Sleep(50);printf("【5】返回上一级\n");Sleep(50);printf("\n");Sleep(50);scanf("%d",&m);switch (m){case 1:{Search(num); break;}case 2:{Select(num); break;}case 3:{Charge(num); break;}case 4:{Del(num);printf("该卡注销成功,您已无权限使用,即将返回主界面\n");Sleep(50);m=5;system("pause");break;}}if(m==5){break;}}}else if(Check(name,num)==3){printf("提示:该账户已注销\n");Sleep(50);printf("请联系管理员注册新用户\n");Sleep(50);printf("\n");Sleep(50);system("pause");}else{printf("提示:用户账户名或卡号输入错误");Sleep(50);printf("请核对身份信息后重试。\n");Sleep(50);printf("\n");Sleep(50);system("pause");}break;}}if(k==0||i==0){break;}}printf("\n");Sleep(50);}int main(){Read();rem();menu();Save();FreeLinkList();return 0;}
4.运行截图
5.注意事项(一定要看)
1.本代码编译环境为vs,在Dev和vc6上均可运行,如果使用vs及以上的版本尝试关闭安全检查再运行。
2.(十分重要一定要看)该代码默认可执行文件夹下有用户数据的文件用来进行读取操作,如果代码能够运行但是警告丢失文件则是没有进行以下操作步骤,第一种方法(推荐):在可执行文件夹下新建一个“公交一卡通.dat”的文件(不包括引号,下同),文件内容写“–+±-++ 屯屯屯屯屯屯屯?繸? 尹明星 屯屯屯屯屯屯? e? [? 连凯歌 屯屯屯屯屯屯? €[? 拓靖 ? 屯屯屯屯屯屯? 郲? 郭锐智 屯屯屯屯屯屯? @? 李和平 屯屯屯屯屯屯? 燶? 李强 屯屯屯屯屯屯屯? ]? 李佳昊 屯屯屯屯屯屯? `]? 南嘉辉 屯屯屯屯屯屯? 繻? 聂志豪 屯屯屯屯屯屯? ^? 陈龙龙 屯屯屯屯屯屯? €^?
lq q 屯屯屯屯屯屯屯? ”(因为是二进制文件用记事本打开未初始化的会乱码,写入即可电脑会自动转换)第二种方法:将代码中的Read();和rem();注释掉,将代码中的CreateList();解除注释运行一次后恢复之前的状态即可。
3.用户余额为int型不易存储过多否则会崩溃,选择输入数字尽量合法未作合法性输入检查如果输入非法字符会死循环,每次运行结束不要点击x号退出,要根据程序提示逐层退出才能成功存入文件进行下一次读取。
4.如果有什么bug或者好的建议欢迎学习交流。谢谢~