20##级《C课程设计》大作业设计报告
设计题目:餐厅信息管理程序
小组参与人员:
姓名: 学号: 专业班级: 分工:
姓名: 学号: 专业班级: 分工:
姓名: 学号: 专业班级: 分工:
主函数及欢迎界面是一起完成的。
1. 题目:餐厅服务系统
系统功能设计
a.要求实现客户点菜的过程、客户结账、账目的管理、餐厅系统的维护四大功能模块,每个功能模块又分别对应一些不同操作子模块,从而完成一个餐厅信息管理信息系统。
b.可以使用三种不同的结构体来分别存储餐桌、菜以及订单信息。
b.使用文本文件完成数据的存储与读取,完成账单的管理。
界面要求
欢迎界面、登录界面、管理界面。
2. 设计方案说明
2.1 数据的存储结构
因为菜,餐桌信息均不只含有一项内容,所以使用结构体数组
typedef struct f //菜信息
{
char name[30]; //菜名
int price; //菜定价
}_food;
typedef struct t //餐桌信息
{
int flag; //定义变量名用于判断
int foo[30]; //餐桌编号
}_table;
struct r //订单信息
{
_food food[20]; //所选菜信息
_table table[30]; //所选餐桌信息
};
2.2 函数之间的调用关系说明
在主函数中通过case选择语句调用system("cls");menu(&restaurant);order(&restaurant);save(&restaurant);book(&restaurant);
bill(&restaurant);total_information(&restaurant);change_menu(&restaurant);entry(&restaurant);九个函数,其中各函数中又个别嵌套调用了其他函数。
2.3 各函数说明
①order(struct r*restaurant) 订餐的函数:
restaurant是指向struct r结构体的指针。输入餐桌号i,如果table[i].flag是1或2,则显示该桌已被选定,系统提示重新选择餐桌号,通过嵌套函数order(restaurant)再次选择。如果table[i].flag不是1或2,则该桌可用,同时使table[i].flag变为1防止重复选定。然后是for语句循环,直到输入999之前可以持续点餐,点餐通过输入菜对应的编号实现,想重复点同一道菜可以再次输入编号。
②book(struct r * restaurant) 预定餐桌和菜的函数:
restaurant是指向struct r结构体的指针。系统提示“请输入预定的桌子号码(1-30):”同order函数,若table[i].flag是1或2,则显示该桌已被选定,系统提示重新选择餐桌号,通过嵌套函数book(restaurant)再次选择。如果table[i].flag不是1或2,则该桌可预定,同时使table[i].flag变为2防止重复预定。 for(j=1;restaurant->table[i].foo[j-1]!=999;j++) {scanf("%d",&restaurant->table[i].foo[j]); }意思是只要输入的编号不是999就可以持续点菜(bill函数有设置,即使输入的编号超过菜单范围也不会被收费。特别注意for语句循环中是j-1而不是j,因为从第二次循环开始,先j++后判断)printf("预定成功!!\n");getchar();getchar();其中第一个getchar();用以接收回车键,第二个getchar();返回主界面。
③bill(struct r * restaurant) 用于结账的函数:
若table[i].flag是1,表示正被使用,可以结帐;若table[i].flag是2,表示已被预定,可以结账。如果不是1或2,则表示没人,不能结账。restaurant->food[restaurant->table[i].foo[j]].price表示第i张桌子点的菜的编号,bill+=restaurant->food[restaurant->table[i].foo[j]].price是把所有菜的价格相加。restaurant->table[i].foo[j]<21&&restaurant->table[i].foo[j]>0表示如果输入的编号不在菜单范围内就不能算入账单,否则会出错,这提高了容错性。结账后,若是输入1,由if(j==1)restaurant->table[i].flag=-1;知该桌位会被释放供其他客人使用,再按2 return返回界面。
④函数total_information(struct r *restaurant)
功能:显示所有进账和餐厅信息
实现方法:
此函数无返回值,首先定义并初始化变量,输出标题后通过for循环计算出进账金额及被使用的桌子和剩余桌子数
⑤函数save(struct r * restaurant)
功能:将记录存入磁盘中
实现方法:
参数为结构体指针
首先定义文件类型指针fp;
然后以只写方式打开“cxq.txt”文件 fp=fopen("cxq.txt","wb");
然后向restaurant所指内存区写入文件,一次写入一条,
长度为struct r的长度 fwrite(restaurant,sizeof(struct r),1,fp);
关闭文件 fclose(fp);
⑥函数load(struct r * restaurant)
功能:加载磁盘中文件
实现方法:
定义文件类型指针fp
以只读方式打开“cxq.txt”文件fp=fopen("cxq.txt","rb");
从restaurant所指内存区读取文件,一次读取一条
长度为struct r的长度 fread(restaurant,sizeof(struct r),1,fp);
关闭文件 fclose(fp);
⑦函数entry(struct r * restaurant)
功能:实现清空菜单
实现方法:
首先定义参数i
使用for循环,定义参数i初始量为1
当i小于21时,字符串 restaurant->food[i].name 替换函数并且清空菜名
直到i大于等于21后退出循环
⑧函数change_menue(struct r * restaurant)
功能:实现修改菜单功能
实现方法:
定义参数i,n
调用函数menue(restaurant) 输出修改前的全部列表
使用do while循环,分别输入编号、菜名、价格保存到n、restaurant->food[n].name、restaurant->food[n].price
判断用户是否需要继续修改 printf("1、继续修改\t2、返回\n");,
若要修改用if语句进行判断,否则返回
当用户需要继续进行修改即if(i==1)时 调用修改菜单函数change_menue(restaurant)进行修改
否则即else时 返回欢迎界面
3.调试分析
(1)刚开始定义bill和count时没有初始化,程序运行后,显示账目信息时价格显示为负数,通过上网查阅得知,变量没有初始化,所以变量的值是未知的,编译器会自动给变量赋值,而值是不定的。
(2)for语句循环中若条件里写的是j而不是j-1会出错。
(3)设置两个getchar(),第一个用于接收回车键,第二个用于返回主界面。
等等。
4.总结
组员是陈小巧,赵雯君,唐凯利。从一开始连怎么分工都不知道到后来能合作得很好,从什么都不会到大量阅读直到深入了解什么是数组、链表和结构体,从不想编程到渐渐爱上成功的喜悦,我们收获了很多。这次课程设计虽然花了我们不少时间,但正是这些时间,让我们见识到了C语言的重要性。这个餐厅管理系统都是在我们知识范围内完成的,所以界面清晰简单很实用!相信这次的课程设计为我们以后继续从事计算机工作打了一个小小的基础。
由于这是第一次进行设计,写报告,难免会有缺陷,请老师见谅!
5.程序源代码
#include<stdio.h> //定义输入/输出函数
#include<stdlib.h> //定义杂项函数及内存分配函数
#include<string.h> //字符串处理
typedef struct f //菜信息
{
char name[30]; //菜名
int price; //菜定价
}_food;
typedef struct t //餐桌信息
{
int flag; //定义变量名用于判断
int foo[30]; //餐桌编号
}_table;
struct r //订单信息
{
_food food[20]; //所选菜信息
_table table[30]; //所选餐桌信息
};
welcome() //欢迎界面
{
printf("\n\n\n\n\n 制作人:陈小巧\n");
printf(" 201200800393\n");
printf(" 制作人:唐凯利\n");
printf(" 201200800443\n");
printf(" 制作人:赵雯君\n");
printf(" 201200800490\n");
printf(" 12级机电与信息工程学院软件2班\n");
printf(" 餐厅管理系统\n");
printf(" 请按任意键继续...\n\n\n\n\n\n");
getchar(); //从键盘取走任意字符
printf("***********************************************************\n\n");
printf("\t\t\t餐厅服务系统\n");
printf("***********************************************************\n\n");
printf("1、点菜\n2、定菜\n3、结账\n4、进账和餐厅信息统计\n5、修改菜单\n6、退出\n7、清空菜单\n");
}
menu(struct r * restaurant) //显示菜单
{
int i;
printf("***********************************************************\n\n");
printf("\t\t\t菜 单\n\n");
printf("***********************************************************\n\n");
printf("序号 菜名\t 价格\t\t序号 \t 菜名\t 价格\n");
for(i=1;i<21;i++) //用for循环控制菜单按序号、菜名、价格、顺序显示
{
printf("%d、 %s\t\t%d\t",i,restaurant->food[i].name,restaurant->food[i].price);
if(i%2==0) //换行,使菜单以两列格式输出
putchar(10); //向屏幕输出一个换行符
}
}
order(struct r*restaurant) //实现点菜功能
{
int i,j;
printf("***********************************************************\n\n");
printf("\t\t\t 订 餐 \n\n");
printf("***********************************************************\n\n");
printf("请输入选择的桌子号码(1-30):");
scanf("%d",&i); //读入桌子号码
if(restaurant->table[i].flag==1||restaurant->table[i].flag==2)
{ //当餐桌为已有人或已被预订情况时提示重新选择
printf("%d号桌已经被定\n",i);
printf("按回车,请重新选择!!\n");
getchar();
order(restaurant); //调用order函数
return;
}
restaurant->table[i].flag=1;//将1赋值给flag,定义此时为
printf("请输入您要选择的菜号码(1-20),以空格分开,以999结束\n");
for(j=1;restaurant->table[i].foo[j-1]!=999;j++)
{ //当最后一位为999时结束for循环,否则全部读入内存
scanf("%d",&restaurant->table[i].foo[j]);
} //从键盘读入所选菜编号
printf("点菜成功!!\n");
}
book(struct r * restaurant) //实现预定功能,记录存入内存
{
int i,j;
printf("***********************************************************\n\n");
printf("\t\t\t 预 定 \n\n");
printf("***********************************************************\n\n");
printf("请输入预定的桌子号码(1-30):");
scanf("%d",&i); //读入桌子号码
if(restaurant->table[i].flag==1||restaurant->table[i].flag==2)
{ //当flag等于1或等于2时提示重新选择
printf("%d号桌已经被定\n",i);
printf("按回车,请重新选择!!\n");
getchar();
book(restaurant); //调用book函数
return;
}
restaurant->table[i].flag=2; //将2复制给flag,定义此时预定桌位及菜
printf("请输入您要预定的菜号码,以空格分开,以999结束\n");
for(j=1;restaurant->table[i].foo[j-1]!=999;j++)
{ //当最后一位为999时结束for循环,否则全部读入内存
scanf("%d",&restaurant->table[i].foo[j]);
} //从键盘读入菜编号
printf("预定成功!!\n");
getchar();
getchar();
}
bill(struct r * restaurant) //实现结账功能
{
int bill=0,i,j; //对bill初始化
printf("***********************************************************\n\n");
printf("\t\t\t 结 账\n\n");
printf("***********************************************************\n\n");
printf("请输入要结账的桌子号码:\n");
scanf("%d",&i); //读入餐桌号
if(restaurant->table[i].flag!=1&&restaurant->table[i].flag!=2)//如果为没有客人状态
{
printf("%d号桌没有客人,不能结帐!!\n",i);
getchar();
getchar();
return;
}
else
{
for(j=1;restaurant->table[i].foo[j]!=999;j++)
{ //读入该桌所选菜的信息
if(restaurant->table[i].foo[j]<21&&restaurant->table[i].foo[j]>0)//如果该道菜存在
bill+=restaurant->food[restaurant->table[i].foo[j]].price;//统计菜的总价
}
}
printf("%d号桌一共消费%d元.\n",i,bill);
printf("1、释放该桌位 2、返回上一层\n");
scanf("%d",&j);
if(j==1)
restaurant->table[i].flag=-1; //将-1赋值给flag,此时释放所选桌位
else
{
getchar();
return;
}
getchar();
getchar();
}
total_information(struct r *restaurant) //显示所有进账和餐厅信息
{
int bill=0,i,j,count=0; //初始化bill和count
printf("***********************************************************\n\n");
printf("\t\t\t进账和餐厅的信息\n\n");
printf("***********************************************************\n\n");
for(i=1;i<31;i++)
if(restaurant->table[i].flag==1||restaurant->table[i].flag==2)
{ //当餐桌被选择或预定时count增加
count++;
for(j=1;restaurant->table[i].foo[j-1]!=999;j++)
{
if(restaurant->table[i].foo[j]<31&&restaurant->table[i].foo[j]>0)
bill+=restaurant->food[restaurant->table[i].foo[j]].price;
}
}
printf("总共进账%d元\n",bill); //输出进账金额
printf("目前总共有%d个桌子被预定或有人\n",count);//输出预定或有人的桌子数量
printf("目前有%d个空桌子\n",30-count);//输出剩余桌子数量
getchar();
getchar();
}
save(struct r * restaurant) //将记录存入磁盘中
{
FILE * fp; //定义文件类型指针
fp=fopen("cxq.txt","wb"); //以只写方式打开“cxq.txt”文件
fwrite(restaurant,sizeof(struct r),1,fp);//写入文件,一次写入一条
fclose(fp); //关闭文件
}
load(struct r * restaurant) //加载磁盘中的文件
{
FILE * fp; //定义文件类型指针
fp=fopen("cxq.txt","rb"); //以只读方式打开“cxq.txt”文件
fread(restaurant,sizeof(struct r),1,fp);//写入文件,一次写入一条
fclose(fp); //关闭文件
}
entry(struct r * restaurant) //实现清空菜单
{
int i;
for(i=1;i<21;i++) //使用for循环
{
strcpy(restaurant->food[i].name,"空");//字符串替换函数,清空菜名
restaurant->food[i].price=0; //清空菜定价
}
}
change_menu(struct r * restaurant) //实现修改菜单功能
{
int i,n;
menu(restaurant); //首先输出修改前的全部列表
do //使用do while循环
{
printf("请输入要修改的菜名的号码: ");//输入编号
scanf("%d",&n);
printf("请输入修改后的菜名: ");//输入菜名
scanf("%s",restaurant->food[n].name);
printf("请输入修改后的价格: ");//出入定价
scanf("%d",&restaurant->food[n].price);
printf("1、继续修改\t2、返回\n");
scanf("%d",&i);
if(i==1) //继续修改
{
change_menu(restaurant); //调用修改菜单函数
return;
}
else //若输入2返回欢迎界面
return;
}while(1);
}
int main() //主函数
{
int i;
FILE * fp; //文件指针
struct r restaurant; //定义结构体
if((fp=fopen("cxq","rb"))==NULL) //如果文件已存在,以只读方式打开文件失败
{
fopen("cxq","wb"); //打开文件
entry(&restaurant); //清空之前记录
save(&restaurant); //保存结构体内全部记录
}
do
{
load(&restaurant); //加载全部记录
system("cls"); //调用清屏函数清屏
welcome(); //显示欢迎界面
scanf("%d",&i); //读入欢迎界面内的选择
switch(i) //switch选择函数
{
case 1: //先清屏,然后显示菜单,调用点菜函数,保存记录
system("cls");
menu(&restaurant);
order(&restaurant);
save(&restaurant);break;
case 2: //先清屏,然后显示菜单,调用预定函数,保存记录
system("cls");
menu(&restaurant);
book(&restaurant);
save(&restaurant);break;
case 3:
system("cls"); //清屏,调用结账函数,保存记录
bill(&restaurant);
save(&restaurant);break;
case 4: //清屏,调用显示全部信息函数
system("cls");
total_information(&restaurant);break;
case 5: //清屏,调用修改菜单函数,保存记录
system("cls");
change_menu(&restaurant);
save(&restaurant);break;
case 6: exit(0); //退出餐厅信息管理
case 7:entry(&restaurant); //调用清空所有信息函数
save(&restaurant);break; //调用保存函数
default:printf("输入有误,请重新输入!!\n");
}
}while(1);
return 0;
}