大一C语言 课设(餐厅管理系统)

2 篇文章 0 订阅
1 篇文章 0 订阅
这是一个使用C语言编写的餐厅点餐系统,包括菜单选择、点餐、修改、后台管理等功能。系统涉及单链表、文件操作和排序算法,允许用户查看热卖菜品、选择不同菜系并进行账单结算,同时支持管理员对菜单进行增删改查。程序将用户订单以xls格式保存,并能动态更新菜品销量排行榜。
摘要由CSDN通过智能技术生成

在学习完C语言之后,写了一个小程序,涉及到单链表,文件,排序,等内容。

这个对新手指针,函数等方面的掌握有一定的要求。

一.程序开始界面

1.输入不同的数字,选择你要的操作,进行点菜,修改账单,结算等功能

2.热卖推荐中会默认打印当前餐厅热卖的各类食物排行前三位(可以自己选择查看前几位,因为懒,就没加这个功能,要加入这个功能,简单改一下就行)

3.输入0结算,系统会打印出菜单,并将数据以xls表格形式存到后台

二.点餐页面

1.此时我们选择凉菜类

2.选完后会打印出已选择菜单,并提示是否修改

三.后台文件

1.程序的菜类文件(名字 价格 销售量)都存于后台文件中。使用管理员登陆可以对其进行

修改,删除,添加等操作

2.每等一个用户下单,程序都会对后台菜类文件对应的销售额进行调整,并在下一次使用程序

时对其排序,以选出销量高的菜品

3.用户下单后生成的账单也会储存于后台(.xls)

以下是程序源代码:

#include<stdio.h>
#include<stdlib.h>
#include<io.h>
#include<string.h>
#include<time.h>
#define PATH "C:\\Users\\14765\\Desktop\\点餐系统"
//餐厅点餐程序
float SUM=0;	//消费总计 
FILE *CheckBills;	//账单 
char date[80];	//账单编号 

typedef struct Food{//销量 
	char name[50];
	float price;
	int sales;
}FOOD;

typedef struct Bill{
	char name[30];	
	float price;
	int num;
	int sign; 
	int sign_num;
	struct Bill *next;
}BILL;

typedef struct Dishes{
	char name[30];
	float price;
	int sales;
	struct Dishes *next;
}DISH; 
void printMenu(){//选择界面 
	printf("     -----------------------      \n");
	printf("     |        菜单         |      \n");
	printf("     -----------------------      \n");
	printf("     |      1.热卖推荐     |      \n");
	printf("     -----------------------      \n");
	printf("     |      2.凉菜         |      \n");
	printf("     -----------------------      \n");
	printf("     |      3.热菜         |      \n");
	printf("     -----------------------      \n");
	printf("     |      4.饮品         |      \n");
	printf("     -----------------------      \n");
	printf("     |      5.特产小吃     |      \n");
	printf("     -----------------------      \n");
	printf("     |      6.吃遍中国系列 |      \n");
	printf("     -----------------------      \n");
	printf("     |      0.退出并结算   |      \n");
	printf("     -----------------------      \n");
	printf("\n");
} 
void printDishes(FILE *fp){//打印菜单文件数据 
	char name[20];
	float price;
	int count=1;
	int a;//销量 
	while(fscanf(fp,"%s%f%d",name,&price,&a)!=EOF){
		getc(fp);
		printf("%2d.%-15s  %.1f\n",count++,name,price);
	}
	rewind(fp); 
}
void reviseDish(FILE *fp){//修改菜名,价格... 
	int snum;
	char cName[15];
	float price;
	printf("1.修改名称\n2.修改价格\n");
	do{
		scanf("%d",&snum);
	}while(snum!=1&&snum!=2);
	if(snum==1){
		printf("请输入要修改的名称:\n");
		scanf("%s",cName);
		fprintf(fp,"%-15s",cName);
	}else{
		printf("请输入要修改的价格:\n");
		scanf("%f",&price);
		fseek(fp,16,1);
		fprintf(fp,"%4.1f",price);//这儿应该有一个判断格式的函数,确保其输入到文件的格式(已解决) 
	}
	rewind(fp);
	
}
void printDishL(DISH *dish){//打印菜单(链表) 
	DISH *temp=dish;
	int count=1; 
	while(temp!=NULL){
		printf("%2d.%-15s%.1f\n",count++,temp->name,temp->price);
		temp=temp->next;
	} 
}
//先把管理部分做了
void reviseMenuDetail(char *setName){//修改菜单函数(具体实现)
	FILE *fp;
	int a;
	if((fp=fopen(setName,"r+"))==NULL){
		printf("Error!\n");
		exit(1);
	}
B:	printf("请选择:\n1.添加菜品\n2.删除菜品\n3.修改菜品\n0.退出\n"); 
	scanf("%d",&a);
	switch(a){
		case 1:{
			fp=fopen(setName,"a+");
			while(1){
				char name[30],c;
				float price;
				printf("请依次输入菜名,价格:\n");
				scanf("%s %f",name,&price);
			    fprintf(fp,"%-15s %4.1f%5d\n",name,price,0);
				printf("是否继续录入?(Y or N)\n");
				do{
					scanf("%c",&c);
				}while(c!='Y'&&c!='N');
				if(c=='N'){
					break;
				}
			}
			fclose(fp);
			goto B;
		}
		case 2:{
			int snum;
			fp=fopen(setName,"r+");
			char name[30];
			float price;
			int sales;
			DISH *dishes=NULL,*temp=NULL,*r;
			while(fscanf(fp,"%s %f%d\n",name,&price,&sales)!=EOF){
				r=(DISH*)malloc(sizeof(DISH));
				strcpy(r->name,name);
				r->price=price;
				r->sales=sales;
		//		printf("%-15s%.1f\n",name,price);
				if(dishes==NULL){
					temp=r;
					dishes=temp;
					r->next=NULL;
				}else{
					temp->next=r;
					temp=temp->next;
					r->next=NULL;
				}
			}
			rewind(fp);
			printf("请选择删除的内容:(输入-1退出)\n");
			printDishes(fp);
			while(1){
				scanf("%d",&snum);
				if(snum==-1){
					break;
				}
				DISH *tp=dishes,*t=NULL,*t1=NULL; 
				for(int i=1;i<snum;i++){
					t=tp;
					tp=tp->next;
				}
				if(t==NULL){
					t=dishes;
					dishes=dishes->next;
					free(t);
				}else{
					t1=tp;
					t->next=tp->next;
					free(t1);
				} 
				printDishL(dishes);	
			}
			fp=fopen(setName,"w+");
			temp=dishes;
			while(temp!=NULL){
				strcpy(name,temp->name);
				price=temp->price;
				fprintf(fp,"%-15s %.1f%5d\n",name,price,temp->sales);
				temp=temp->next;
			} 
			printf("删除完成!\n");
			fclose(fp);
//			fseek(fp,22*(snum-1),0);
			goto B;
		}
		case 3:{
			int snum;
B1:			fp=fopen(setName,"r+");
			printf("请选择修改的内容:\n");
			printDishes(fp);
			fseek(fp,0,2);
			int f=ftell(fp);
			int flimit=f/27;
			rewind(fp);
			scanf("%d",&snum);
			if(snum>flimit){
				printf("请输入正确的数字!\n");
				goto B1;
			}
			fseek(fp,27*(snum-1),0); 
			reviseDish(fp); 
			char c;
			printf("是否继续修改?(Y or N)\n");
			do{
				scanf("%c",&c);
			}while(c!='Y'&&c!='N');
			if(c=='Y'){
				goto B1;
			}
			fclose(fp);				
			goto B;
		}
		case 0:{
			break;
		}
		default:{
			goto B;
		}
	}
} 
void reviseMenu(){//修改菜单函数(方法) 
	char password[30];
	printf("请输入管理员密码:\n");
	scanf("%s",&password);
	if(!strcmp(password,"520521")){
		printf("登录成功!\n"); 
	}else{
		printf("密码错误!");
		return; 
	}
	int num;
A:	printf("请选择修改的菜类:(0退出后台管理系统)\n"); 
	scanf("%d",&num);
	switch(num){
		case 1:{
			printf("此选项不可更改,请重新选择\n");
			goto A; 
		}
		case 2:{
			char a[]="凉菜.txt";
			reviseMenuDetail(a);
			goto A;
		}
		case 3:{
			char a[]="热菜.txt";
			reviseMenuDetail(a);
			goto A;
		}
		case 4:{
			char a[]="饮品.txt";
			reviseMenuDetail(a);
			goto A;
		}
		case 5:{
			char a[]="特产小吃.txt";
			reviseMenuDetail(a);
			goto A;
		}
		case 6:{ 
			printf("尚未开放!\n"); 
			goto A;
		}
		case 0:{
			
			break;
		} 
		default:{
			printf("请重新输入!\n");
			goto A;
		}
	} 
}

void printBill(BILL *bill,char *dname){
	BILL *temp=bill;
	printf("—————————————%s—————————————\n",dname);
	float sum=0;
	int count=1;
	while(temp!=NULL){
		printf("|No.%d.%-15s%d(份) * %.1f(元)   小计:  %.1f(元)|\n",count++,temp->name,temp->num,temp->price,temp->num*temp->price);
		printf("————————————————————————————\n");
		sum+=temp->price*temp->num;
		temp=temp->next;		
	}
	printf("                                        共计:  %.1f(元)\n",sum); 
}
void reviseBill_D(BILL **bill,int n){//(***)
	BILL *temp,*r=NULL,*r0=NULL; 
	if(n==1){
		temp=*bill;
		*bill=(*bill)->next;
		free(temp);
	}else{
		int i=1;
		r=*bill;
		while(i<n){
			r0=r;
			r=r->next;
			temp=r->next;
			i++;
		}
		free(r);
		r0->next=temp;
	}
}
void revise_sales(FILE *fp,int num,int salenum,int aa){
	fseek(fp,27*(num-1),0);
	fseek(fp,20,1);
	fprintf(fp,"%5d",aa+salenum);
}
void reviseBill(BILL **bill_,FILE *fp){ //修改账单  ——————————要点(***) 
	int snum,num=0,snum1,snum2;
	BILL *bill=*bill_;
	while(1){
		BILL *temp=bill,*r;
		while(temp!=NULL){
			num++;			//num为链表内容数目 
			temp=temp->next;
		}
		printf("请选择修改的菜品(序号) 输入0退出:\n");
		scanf("%d",&snum);
		if(snum>0&&snum<=num){

			r=bill;
			int i=1;
			while(i<snum){
				r=r->next; //目标菜品
				i++; 
			}
			
			printf("1.修改数量 2.删除该菜品 0.返回\n");
			
			do{
				scanf("%d",&snum1);
				if(snum1==0){
					break;
				} 
			}while(snum1!=1&&snum1!=2);
			
			
			if(snum1==1){
				
				printf("请输入要修改的数量:\n");
				
				scanf("%d",&snum2);
								 				
				if(snum2==0){
					reviseBill_D(bill_,snum);
					
				}else{
					r->num=snum2;
				}
			
			
			}else if(snum1==2){
				reviseBill_D(bill_,snum);
				
			}
			
		}else if(snum==0){
			break;
		}else{
			printf("请重新输入!\n");
		}
		num=0; 
		revise_sales(fp,r->sign,r->num,r->sign_num);
		rewind(fp);
	}
	
} 


void checkDishes(FILE *fp,char *dName,char *dname){
	int s,num,num1,aa; 
	BILL *bill=NULL,*temp,*r;
	
	if((fp=fopen(dName,"r+"))==NULL){
		printf("系统错误,请联系工作人员");
		exit(1);
	}
	printf("请选择菜品和数量(用空格分开):(输入0返回)\n"); 
	printDishes(fp);
	fseek(fp,0,2);
	num=ftell(fp)/27;
	char name[30];
	float price;
	while(1){   //账单用链表来做 
		rewind(fp);
		scanf("%d",&s);
		if(s==0){
			break;
		}
		scanf("%d",&num1);
		if(s<=num&&s>0){
			fseek(fp,27*(s-1),0);
			
			fscanf(fp,"%s%f%d",name,&price,&aa);
			
			r=(BILL *)malloc(sizeof(BILL));
			
			strcpy(r->name,name);
			
			r->price=price;
			
			r->num=num1;
			
			r->sign=s;//链表带着菜在文件中的顺序 
			
			r->sign_num=aa;
			
			if(bill==NULL){
				bill=r;
				temp=bill;					
			}else{
				temp->next=r;
				temp=temp->next;						
			}
			r->next=NULL;
			printf("名称:%s 价格:%.1f 数量:%d\n",name,price,num1);
		}else{
			printf("请重新选择.\n");
			continue;
		}
		rewind(fp);
		revise_sales(fp,s,num1,aa);	
	} 
	rewind(fp);
	printBill(bill,dname);
	
	char c;
	while(1){
		printf("是否对已选菜品进行修改?(Y or N)\n");
		do{
			scanf("%c",&c);
		}while(c!='Y'&&c!='N');
		if(c=='Y'){
			reviseBill(&bill,fp);
			printBill(bill,dname); 
		}else{
			break;
		}
	}
//	if((CheckBills=fopen(date,"a+"))==NULL){
//		printf("Error!");
//		exit(1);
//	}
	
	//bill为目前账单链表,dname为菜系
	//先获取最后选择菜的数量
	int num_1=0,_count=1;
	
	BILL *temp1=bill,*temp2=bill;
	
	while(temp1!=NULL){
		num_1++;
		temp1=temp1->next; 
	} 
	
	float _sum=0;
	fprintf(CheckBills,"\t\t%s类\n",dname);
	
	fprintf(CheckBills,"序号\t   品名   \t单价(元/份)\t数量\t小计\n");// \n为换行符\r为回车符 
	for(int i=0;i<num_1;i++){
		fprintf(CheckBills," %d \t%s\t   %.1f   \t  %d  \t%.1f(元)\n",_count++,temp2->name,temp2->price,temp2->num,temp2->num*temp2->price);
		_sum+=temp2->num*temp2->price;		
		temp2=temp2->next;
	}
	SUM+=_sum;
	fprintf(CheckBills,"\t\t\t共计:\t%.1f(元)\n",_sum);

}
void check_out(){//结账 
	fprintf(CheckBills,"\t\t\t消费合计: %.1f(元)",SUM);
}


void sellB(FILE *fp,DISH **dp,int *n){//录入数据到链表 
	char s[30];float p;int sales;

	DISH *r,*temp;
	int n1=0;
	while(fscanf(fp,"%s%f%d",s,&p,&sales)!=EOF){
		r=(DISH *)malloc(sizeof(DISH));
		strcpy(r->name,s);
		r->sales=sales;
		r->price=p; 
		r->next=NULL;
		if(*dp==NULL){
			temp=r;
			*dp=r;
		}else{
			temp->next=r;
			temp=temp->next;
		}	
		n1++;
	} 
	

	rewind(fp);
	*n=n1;
//	printf("ceshi");
}
void sort(DISH *dp,int n,int *a){//将菜类的销量前五名在链表中的位置录入到数组 
	DISH *t=dp;
	int b[n];//销量数列 
	
	for(int i=0;i<n;i++){
		b[i]=t->sales;
		t=t->next; 
	}
	
	for(int i=0;i<n;i++){
		int max=i;
		for(int j=i;j<n;j++){
			if(b[j]>b[max]){
				max=j;
			}
		}
		a[i]=max+1;
		b[max]=0;
	}
}
void printSells(DISH *dp,char *name,int *a){
	DISH *temp=dp; 
	printf("%s类\n",name);
	
	for(int i=0;i<3;i++){
		for(int j=0;j<a[i]-1;j++){
			temp=temp->next; 
		}
		printf("No.%d    %s",i+1,temp->name);
		if(i==2){
			break;
		}
		printf("\n"); 
		temp=dp;
	}
	
	printf("\n");
}
void sellBriskly(){//热卖 
	FILE *fp,*fp1,*fp2,*fp3;
	if((fp=fopen("凉菜.txt","r"))==NULL){
		printf("Error!\n");
		exit(1);
	} 
	if((fp1=fopen("热菜.txt","r"))==NULL){
		printf("Error!\n");
		exit(1);
	} 
	if((fp2=fopen("饮品.txt","r"))==NULL){
		printf("Error!\n");
		exit(1);
	} 
	if((fp3=fopen("特产小吃.txt","r"))==NULL){
		printf("Error!\n");
		exit(1);
	} 
	DISH *d=NULL,*d1=NULL,*d2=NULL,*d3=NULL;//数据链表 
	int n,n1,n2,n3;
	
	sellB(fp,&d,&n);//文件,待录入链表,链表长度 
	sellB(fp1,&d1,&n1);
	sellB(fp2,&d2,&n2);
	sellB(fp3,&d3,&n3);
	
	DISH *temp=d1;	
	
	int a[n]={0},a1[n1]={0},a2[n2]={0},a3[n3]={0}; 
	
	sort(d,n,a);//目标链表,长度,待录入数组。 
	sort(d1,n1,a1);
	sort(d2,n2,a2);
	sort(d3,n3,a3);
		
	printf("————销量排行————\n");
	char c[]="凉菜",c1[]="热菜",c2[]="饮品",c3[]="特产小吃";
	printSells(d,c,a);
	printSells(d1,c1,a1);
	printSells(d2,c2,a2);
	printSells(d3,c3,a3);
		
}
int main(void){//可以设置一个管理员密码 
	printf("—————欢迎光临 西邮中餐厅—————\n\n");
	printMenu(); 
	int sNum;
	time_t t;
	time(&t);
	char str[64],str1[64];
	strftime(str,sizeof(str),"%Y-%m-%d %H:%M:%S",localtime(&t));
	//在文件命名时要注意部分英文字符不能用	
	strcpy(str1,str);
	strcat(str,".xls");
	strcpy(date,str); 
	
	if((CheckBills=fopen(date,"a+"))==NULL){
		printf("Error!\n");
		exit(1);
	}
	fprintf(CheckBills,"\t    %s 消费记录\n",str1);
	
A:	printf("请选择菜类:(输入0结算)\n"); 
	scanf("%d",&sNum);
	FILE *fp; 
	BILL *bill=NULL;
	switch(sNum){
		case 1:{//热卖推荐,要随着顾客点菜进行数据更新 
			sellBriskly();
			goto A;
		}
		case 2:{//计算菜的数目:1.flength(fno)/一行字节数   2.遍历
			char dname[]="凉菜";
			char dName[]="凉菜.txt"; 
			checkDishes(fp,dName,dname);			
			goto A;
		}
		case 3:{
			char dname[]="热菜";
			char dName[]="热菜.txt"; 
			checkDishes(fp,dName,dname); 
			goto A;
		}
		case 4:{
			char dname[]="饮品";
			char dName[]="饮品.txt"; 
			checkDishes(fp,dName,dname);
			goto A;
		}
		case 5:{
			char dname[]="特产小吃";
			char dName[]="特产小吃.txt"; 
			checkDishes(fp,dName,dname);
			goto A;
		}
		case 6:{
			printf("尚未开放!\n"); 
			goto A;
		}
		case 0:{
			check_out();
			break;
		}
		case -1:{
			reviseMenu();
			return 0;  
		}
		default:{
			printf("请重新输入.");
			goto A;
		}
	}
//fclose为什么会错?? OK!
	fclose(CheckBills);
	FILE *fp1;
	if((fp1=fopen(date,"r+"))==NULL){
		printf("Error!");
		exit(1);
	}
	char stre[100];
	while(fgets(stre,100,fp1)!=NULL){
		printf("%s",stre);
	}
	printf("\n————感谢惠顾,期待您下次光临!————");
}

有大佬有问题要指出的,欢迎指正!

有需要后台文件的私信...

  • 62
    点赞
  • 418
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 32
    评论
评论 32
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

做好事不留名_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值