C语言程序实践第四次实验报告
大意是写一个餐馆订餐系统,支持增删改查打印等基本功能,不过老师又提出了7点新需求
1、应该中午、晚上分别记最多接受订桌数。
2、应该按人名/手机号输入,不能按编号输入,
编号不要人工输入,应该自动编号;
应记录订桌时间。
3、查询功能不要按编号查询,
应该按人名、手机号码、时间等查询。
4、修改与查询一样不要按编号,
要先显示此条信息,再提示是否修改。
5、删除前也应显示此条信息,提示是否确定删除。
6、显示应该按日期/中午/晚上等分开列。
7、表格存到文件中,程序启动时先读文件,
程序结束时保存文件。
一开始我选择用链表来处理,由于我平时不是对链表操作不是很熟,所以调了半天,而且相比于结构体数组实现,功能比较单一,但基本操作都实现了,感觉有几个坑点,首先,修改和删除操作必须要用引用参数传入,因为指针可能会发生变化,scanf与gets对字符串处理的区别(都忘了),还有就是在查询功能时我判断字符串相等想当然地认为a=b,事实上不是这样的,应该用strcmp函数判断,事后回想起来应该是a=b可能不是简单的判断各个字符相等,还有一些小细节就是格式输出要对齐啦,左对齐,编号删除完了要更细一遍要不然比如说3号删除了原来的4号就要改为3号,后面的号数都要前进一位
然而最令人窒息的是文件操作
最初我是用freopen这样比较方便但是保存不了文件只能把控制台的输出放到一个out.txt文件中,
效果图是这样的
但是我的in.txt文件是一串指令,没有文字说明
后来换了个方式,存在“最终结果.dat”文件下,但是你直接打开二进制文件是不行的,肯定一堆乱码,怎么样验证自己的最终表单保存好了呢,可以在控制台检测,关键代码如下:
inline void save(Pointer Head)
{
FILE*fp;
if((fp=fopen("最终表单.txt","w"))==NULL)
{
cout<<"Cannot open file!"<<endl;
return ;
}
Pointer p=Head;
while(p)
{
if(fwrite(p,sizeof(*p),1,fp)!=1)
{
printf("File write error!");
return ;
}
//else cout<<p->Guest_name<<endl;
p=p->next;
}
fclose(fp);
}
inline void outshow(Pointer Head)
{
FILE*fp;
if((fp=fopen("最终表单.dat","rb"))==NULL)
{
cout<<"Cannot open file!"<<endl;
return ;
}
for(rg i=0;fscanf(fp,"%s%s%lld%lld",p[i].Guest_name,p[i].Time,&p[i].Phone_number,&p[i].people)!=EOF;i++)
{
// cout<<1<<endl;
printf("|编号 |姓名 |人数 |时间 |\n");//实现7、表格存到文件中,程序启动时先读文件,程序结束时保存文件。
printf("|%-11lld|",p[i].Num);
printf("%-16s|",p[i].Guest_name);
printf("%-10lld|",p[i].people);
printf("%-12s|\n",p[i].Time);
}
/* char ch=getc(fp);
while(!feof(fp))
{
putchar(ch);
ch=getc(fp);
}*/
fclose(fp);
}
之后进行的所有操作结束后都会保存在这个“最终结果.dat”二进制文件下,控制台调试的时候注释掉代码前两行
附源码
#include<bits/stdc++.h>
#define rg register long long
#define inf 2147483647
#define min(a,b) (a<b?a:b)
#define max(a,b) (a>b?a:b)
#define ll long long
#define maxn 205
#define endl "\n"
#define N 6000
const double eps=1e-8;
using namespace std;
inline ll read()
{
char ch=getchar();ll s=0,w=1;
while(ch<48||ch>57){if(ch=='-')w=-1;ch=getchar();}
while(ch>=48&&ch<=57){s=(s<<1)+(s<<3)+(ch^48);ch=getchar();}
return s*w;
}
inline void write(ll x)
{
if(x<0)putchar('-'),x=-x;
if(x>9)write(x/10);
putchar(x%10+48);
}
ll Maxsize_Noon,Maxsize_Evening,cnt;//tot为编号
typedef struct Guest_node
{
char Guest_name[100];
ll Num;//编号
char Time[100];//格式是xxxx.xx.xx.xx:xx(年月日时分)
ll Phone_number,people,time;//手机号码,,用餐人数
struct Guest_node*next;
}Guestlink,*Pointer;
Guestlink p[10005];
inline bool cmp(const Pointer &a,const Pointer &b)
{
if(a->time==b->time)return a->Guest_name<b->Guest_name;
return a->time<b->time;
}
inline void Insert_Guest(Pointer *Head)
{
Pointer node=(Pointer)malloc(sizeof(Guestlink));
if(node==NULL)
{
cout<<"动态内存申请失败,如果您还想再插入的话就在执行一次此功能吧"<<endl;
return ;
}
else
{
node->next=NULL;
cout<<"请输入姓名 预定时间 电话号码 用餐人数:(样例: glm 09:06 110 13 \n表示姓名为glm的客户在早上09:06下单,用餐人数为13,手机号为110)";
scanf("%s%s%lld%lld",node->Guest_name,node->Time,&node->Phone_number,&node->people);//实现新需求2.应该按人名/手机号输入,不能按编号输入,编号不要人工输入,应该自动编号;应记录订桌时间
string temp=node->Time;
//cout<<temp<<endl;
ll k=(temp[0]-48)*1000+(temp[1]-48)*100+(temp[3]-48)*10+temp[4]-48;
//cout<<k<<endl;
node->time=k;
if(k<1800&&k>=1200)
{
if(node->people<=Maxsize_Noon)
{
cout<<"下单成功!您是在中午点餐,取单号为"<<++cnt<<endl;
}
else
{
cout<<"本餐厅在中午可接受线上点餐单数已满,下单失败。";
return ;
}
}
else if(k>=1800&&k<=2400)
{
if(node->people<=Maxsize_Evening)
{
cout<<"下单成功!您是在晚上点餐,取单号为"<<++cnt<<endl;
}
else
{
cout<<"本餐厅在晚上可接受线上点餐单数已满,下单失败。";
return ;
}
}
else if(k>=0&&k<1200)
{
cout<<"下单成功!您是在早上点餐,取单号为"<<++cnt<<endl;
}
else if(k<0||k>2400)
{
cout<<"点餐时间输入有误!请再次确认!"<<endl;
return ;
}
}
Pointer p,q,Temp;
p=q=*Head,Temp=*Head;//q是p的前置指针,方便插入用
while(p)
{
//cout<<1<<endl;
if(p->Guest_name==node->Guest_name&&p->people==node->people&&p->Time==node->Time)
{
cout<<"您要插入的新订单已经存在,要插入请再次确认自己要插入的信息"<<endl;
return ;
}
else
{
q=p;
p=p->next;
}
}
if(q==NULL)
{
*Head=node;
(*Head)->Num=1;
}
else
{
q->next=node;
}
ll tot=0;
while(Temp)
{
Temp->Num=++tot;
Temp=Temp->next;
}
}
inline void Query_Guest(Pointer Head)//完成需求3、查询功能不要按编号查询, 应该按人名、手机号码、时间等查询。
{
char Ask_name[100];
memset(Ask_name,0,sizeof(Ask_name));
ll flag=0;
printf("请输入你要查询的客户姓名:");
scanf("%s",Ask_name);
//基本思想是客户姓名匹配即可
//printf("%s",Ask_name);
Pointer p=Head;
while(p)
{
//cout<<p->Guest_name<<endl;
if(!strcmp(p->Guest_name,Ask_name))//吐血点1
{
if(flag==0)
{
printf("已找到: 姓名是: 人数是: 时间是:\n %-13s%-14lld%-12s\n",p->Guest_name,p->people,p->Time);
flag=1;
p=p->next;
}
else
{
printf(" %-13s%-14lld%-12s\n",p->Guest_name,p->people,p->Time);
p=p->next;
}
}
else p=p->next;
}
if(!flag)
{
cout<<"没有找到!请再次确认你要查询的客户信息。"<<endl;
return ;
}
}
inline void Modify_Guest(Pointer Head)
{
string Ask_name,Ask_time;
ll Ask_phone_num,flag=0;
cout<<"请输入你想要查询的客户订单,由于客户安全信息保密问题,\n你必须输入客户姓名、下单时间、手机号码才能通过验证,(输入样例:glm 12:00 110),\n表示姓名为glm的客户在中午12:00下单,电话号码为110,注意下单时间必须按照xx:xx来输入,否则无效";
cin>>Ask_name>>Ask_time>>Ask_phone_num;//基本思想是客户姓名、下单时间、手机号码匹配即可
Pointer p=Head;
while(p&&flag==0)
{
if(p->Guest_name==Ask_name&&p->Time==Ask_time&&p->Phone_number==Ask_phone_num)
{
char Modify_name[100],Modify_time[100];
ll Modify_people;
cout<<"已找到:姓名是:"<<p->Guest_name<<" "<<"人数是"<<p->people<<" "<<"时间是:"<<p->Time<<endl;
cout<<"你确定要修改此条订单吗:扣1确认:,否则取消修改";
ll temp=read();
if(temp==1)
{
cout<<"请输入你要修改的信息:按照客户姓名,人数,时间来输入:\n";
cout<<"样例: glm 20 21:00 意思是修改订单为姓名为glm的客户在21:00下单,用餐人数为20\n";
cout<<"请注意时间输入参照xx:xx,其中:为英文输入";
//完成需求 4、修改与查询一样不要按编号,
//要先显示此条信息,再提示是否修改。
cin>>Modify_name>>Modify_people>>Modify_time;
strcpy(p->Guest_name,Modify_name),p->people=Modify_people,strcpy(p->Time,Modify_time);
flag=1;
cout<<"修改成功!"<<endl;
}
else
{
cout<<"取消修改成功!"<<endl;
return ;
}
}
else p=p->next;
}
if(!flag)
{
cout<<"没有找到你要修改的客户信息!请再次确认你要查询的客户信息。";
return ;
}
}
inline void Delete_Guest(Pointer *Head)
{
cout<<"请输入你想要删除的订单编号:(样例: 1,表示删除编号为1的订单)";
ll delete_num=read(),flag=0;
Pointer p=*Head,q=*Head;
while(p&&flag==0)
{
if(p->Num==delete_num)
{
cout<<"已找到:姓名是:"<<p->Guest_name<<" "<<"人数是"<<p->people<<" "<<"时间是:"<<p->Time<<endl;
cout<<"你确定要删除此条订单吗,扣1确认:,否则取消删除";//实现需求5:删除前也应显示此条信息,提示是否确定删除。
ll check=read();
if(check==1)
{
if(p==*Head)
{
*Head=p->next;
free(p);
}
else
{
q->next=p->next;
free(p);
}
cout<<"删除成功!"<<endl;
}
else
{
cout<<"取消删除成功!"<<endl;
return ;
}
flag=1;
}
else
{
q=p;
p=p->next;
}
}
if(!flag)
{
cout<<"没有找到你要修改的客户信息!请再次确认你要查询的客户信息。\n";
return ;
}
Pointer Temp=*Head;
ll tot=0;
while(Temp)
{
Temp->Num=++tot;
Temp=Temp->next;
}
}
inline void Show_Guest(Pointer Head)
{
cout<<"************************************************************"<<endl;
Pointer p=Head,q=Head;
if(p==NULL)
{
cout<<" 空清单,无待办事项!\n";
return;
}
printf("\n");
printf("|编号 |姓名 |人数 |时间 |\n");
while(p!=NULL) //列表显示
{
if(p->time<=1200)
{
printf("|%-11lld|",p->Num);
printf("%-16s|",p->Guest_name);
printf("%-10lld|",p->people);
printf("%-12s|(中午)\n",p->Time);
}
p=p->next;
//指向下一结点
}
cout<<"************************************************************"<<endl;//实现需求6、显示应该按日期/中午/晚上等分开列。
while(q!=NULL) //列表显示
{
if(q->time>1200&&q->time<=2400)
{
printf("|%-11lld|",q->Num);
printf("%-16s|",q->Guest_name);
printf("%-10lld|",q->people);
printf("%-12s|(晚上)\n",q->Time);
}
q=q->next;
//指向下一结点
}
}
inline void save_file(Pointer Head)
{
FILE*fp;
if((fp=fopen("最终表单.dat","wb"))==NULL)
{
cout<<"Cannot open file!"<<endl;
return ;
}
Pointer p=Head;
while(p)
{
//cout<<1<<endl;
if(fwrite(p,sizeof(*p),1,fp)!=1)
{
printf("File write error!");
return ;
}
//else cout<<p->Guest_name<<endl;
p=p->next;
}
fclose(fp);
}
inline void save(Pointer Head)
{
FILE*fp;
if((fp=fopen("最终表单.dat","w"))==NULL)
{
cout<<"Cannot open file!"<<endl;
return ;
}
Pointer q=Head; fprintf(fp,"************************************************************\n");
fprintf(fp," 欢迎使用线上点餐系统(V1.0,Author:@GLM) \n");
fprintf(fp,"************************************************************\n最终表单是:\n");
fprintf(fp,"|编号 |姓名 |人数 |时间 |\n");
while(q)
{
//cout<<1<<endl;
fprintf(fp,"|%s |%s |%lld |%lld |\n",q->Guest_name,q->Time,q->Phone_number,q->people);
//else cout<<p->Guest_name<<endl;
q=q->next;
}
fclose(fp);
}
inline void outshow(Pointer Head)
{
FILE*fp;
if((fp=fopen("最终表单.dat","r"))==NULL)
{
cout<<"Cannot open file!"<<endl;
return ;
}
printf("|编号 |姓名 |人数 |时间 |\n");//实现7、表格存到文件中,程序启动时先读文件,程序结束时保存文件。
for(rg i=0;fscanf(fp,"%s%s%lld%lld",p[i].Guest_name,p[i].Time,&p[i].Phone_number,&p[i].people)!=EOF;i++)
{
// cout<<1<<endl;
printf("|%-11lld|",i+1);
printf("%-16s|",p[i].Guest_name);
printf("%-10lld|",p[i].people);
printf("%-12s|\n",p[i].Time);
}
/* char ch=getc(fp);
while(!feof(fp))
{
putchar(ch);
ch=getc(fp);
}*/
fclose(fp);
}
int main()
{
/*freopen("in.txt","r",stdin);
freopen("output.txt","w",stdout);*/
//ios::sync_with_stdio(false);
Pointer Head=NULL;
ll x,flag=0;
do
{
cout<<"************************************************************"<<endl;
cout<<" 欢迎使用线上点餐系统(V1.0,Author:@GLM) "<<endl;
cout<<"************************************************************"<<endl;
if(flag==0)
{
cout<<" 请分别输入中午和晚上餐厅最多可接受的订单用餐人数\n(样例:100 200,表示中午和晚上最多可接受订单用餐人数分别为100,200):";//实现新需求1、应该中午、晚上分别记最多接受订桌数。
Maxsize_Noon=read(),Maxsize_Evening=read();
cout<<endl;
flag=1;
}
cout<<"1.新建一个客户信息"<<endl<<"2.查询一个历史客户信息"<<endl<<"3.修改一个历史客户信息"<<endl<<"4.删除一个已有客户信息";
cout<<endl<<"5.打印所有成功下单客户"<<endl<<"6.退出"<<endl;
cout<<"请输入一个数字代表你想实现的功能:";
x=read();
switch(x)
{
case 1: Insert_Guest(&Head);break;
case 2: Query_Guest(Head);break;
case 3: Modify_Guest(Head);break;
case 4: Delete_Guest(&Head);break;
case 5: Show_Guest(Head);break;
case 6:cout<<"最终表单:\n";Show_Guest(Head);save_file(Head);break;
default:cout<<"Input Error,try again!";
}
}while(x!=6);
save(Head);
/*if(Head)
outshow(Head);*/
cout<<"退出成功!"<<endl;
return 0;
}