#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <windows.h>
float total_price = 0,today_price=0;
FILE *fp;
// 菜品数据结构
struct dish
{
char name[20];//菜品名称
float price;//菜品单价
int quantity;//菜品剩余数量
int count;//用于记录销售数量
struct dish *left;
struct dish *right;
}records[100];
// 树结构体
struct tree
{
struct dish *root;
}t,hottree;//t用于存所有的菜品,hottree用于存热销菜品
// 初始化树
void init_tree(struct tree *t)
{
t->root = NULL;
}
// 插入节点
void insert_node(struct dish *p, struct dish *n)//p为t
{
if (strcmp(n->name, p->name) < 0) //按照字符串的大小来决定存储的顺序
{
if (p->left == NULL)
{
p->left = n;
}
else
{
insert_node(p->left, n);
}
}
else
{
if (p->right == NULL)
{
p->right = n;
}
else
{
insert_node(p->right, n);
}
}
}
// 插入菜品
void add_dish(struct tree *t)
{
struct dish *new_dish = (struct dish*) malloc(sizeof(struct dish));
printf("\t\t请输入菜品名称:");
scanf("%s", new_dish->name);
printf("\t\t请输入菜品价格:");
scanf("%f", &new_dish->price);
printf("\t\t请输入菜品数量:");
scanf("%d", &new_dish->quantity);
new_dish->count=0;
new_dish->left = NULL;
new_dish->right = NULL;
if (t->root == NULL)
{
t->root = new_dish;
}
else
{
insert_node(t->root, new_dish);
}
printf("\t\t菜品已成功添加\n\n");
}
// 将树按照中序的方式遍历并输出
void traverse_tree(struct dish *p)
{
if (p != NULL)
{
traverse_tree(p->left);
printf("\t\t%-12s\t单价:%-8.2f\t剩余储量%-10d\n", p->name, p->price,p->quantity);
traverse_tree(p->right);
}
}
// 显示菜单
void show_menu(struct tree *t)
{
if(t->root==NULL)
{
printf("\t\t该店铺还暂未拥有菜单\n\n");
return ;
}
printf("\t\t\t 欢迎来到好运来餐厅!\n");
printf("\t\t---------------------菜单---------------------\n");
traverse_tree(t->root);
printf("\t\t----------------------------------------------\n");
printf("\n");
}
// 查找树的节点(查找树的里存的菜单)
struct dish *find_node(struct dish *p, char *name)
{
if (p == NULL)
{
return NULL;
}
else if (strcmp(name, p->name) == 0)
{
return p;
}
else if (strcmp(name, p->name) < 0)
{
return find_node(p->left, name);
}
else
{
return find_node(p->right, name);
}
}
// 查找菜品
void find_dish(struct tree *t) {
char name[20];
printf("\t\t请输入要查找的菜品名称:");
scanf("%s", name);
struct dish *result = find_node(t->root, name);
if (result == NULL)
{
printf("\t\t未找到该菜品\n");
}
else
{
printf("\t\t菜品名称:%s,价格:%.2f元,数量:%d\n", result->name, result->price,result->quantity);
}
}
// 修改菜品信息
void modify_dish(struct tree *t)
{
char name[20];
printf("\t\t请输入要修改的菜品名称:");
scanf("%s", name);
struct dish *result = find_node(t->root, name);
if (result == NULL)
{
printf("\t\t未找到该菜品\n");
}
else
{
//将要修改的菜品名称与价格调整
printf("\t\t请输入新的菜品名称:");
scanf("%s", result->name);
printf("\t\t请输入新的菜品价格:");
scanf("%f", &result->price);
printf("\t\t请输入新的菜品数量:");
scanf("%d", &result->quantity);
result->count=0;
printf("\t\t菜品信息已成功修改\n");
}
}
//删除节点(将菜)
struct dish *delete_node(struct dish *p, char *name)
{
struct dish *temp;
if (p == NULL)
{
return NULL;
}
else if (strcmp(name, p->name) < 0)
{
p->left = delete_node(p->left, name);
}
else if (strcmp(name, p->name) > 0)
{
p->right = delete_node(p->right, name);
}
else //找到要删除的结点p了
{
if (p->left == NULL)
{
temp = p->right;
free(p);
return temp;
}
else if (p->right == NULL)
{
temp = p->left;
free(p);
return temp;
}
else //找到的菜品左右结点都不为空
{
temp = p->right;//指向p的右孩子
while (temp->left != NULL)
{
temp = temp->left;
}
strcpy(p->name, temp->name);
p->price = temp->price;
p->right = delete_node(p->right, temp->name);
}
}
return p;
}
// 将菜品从"树"里删除
void delete_dish(struct tree *t) {
char name[20];
printf("\t\t请输入要删除的菜品名称:");
scanf("%s", name);
t->root = delete_node(t->root, name);
printf("\t\t菜品已经成功删除\n\n");
}
// 计算账单
float calculate_bill(char order[20][20], int count, struct tree *t)
{
for (int i = 0; i < count; i++)
{
struct dish *result = find_node(t->root, order[i]);
if (result == NULL)
{
printf("\t\t%s不在菜单中\n", order[i]);
}
else if(result->quantity<=0)
{
printf("\t\t%s的存库不够\n",order[i]);
}
else
{
printf("\t\t已加入%s\t%.2f元\n", order[i], result->price);
result->quantity--;
total_price += result->price;
result->count++;
}
}
printf("\t\t总计:%.2f元\n", total_price);
return total_price;
}
//将热销菜品存入树
void add_hotdish(struct tree *hottree,struct dish *result)
{
struct dish *newhot_dish = (struct dish*) malloc(sizeof(struct dish));
newhot_dish->left = NULL;
newhot_dish->right = NULL;
newhot_dish->price = result->price;
newhot_dish->quantity = result->quantity;
strcpy(newhot_dish->name,result->name);
if (hottree->root == NULL)
{
hottree->root = newhot_dish;
}
else
{
insert_node(hottree->root,newhot_dish);
}
}
// 热推菜品
void hot_recommended()
{
int n;
char name[20];
printf("\t\t添加热推菜品回答1,删除热推菜品回答2\n\t\t");
scanf("%d",&n);
if(n==2)
{
printf("\t\t请输入要删除的菜品名称:");
scanf("%s", name);
hottree.root = delete_node(hottree.root, name);
printf("\t\t热推菜品删除成功!\n");
return ;
}
else if(n==1)
{
printf("\t\t请输入要推荐的菜品名称:");
scanf("%s", name);
struct dish *result = find_node(t.root, name);
if (result == NULL)
{
printf("\t\t未找到该菜品\n");
}
else
{
add_hotdish(&hottree,result);
printf("\t\t%s已成功加入热推菜单\n", name);
}
}
else printf("\t\t输入错误\n");
}
// 点餐
void Ordering(struct tree *t)
{
char order[20][20]; // 一桌最多上20份菜
int count = 0;
printf("\t\t请点餐:\n");
while (1)
{
printf("\t\t请输入要点的菜品名称(按q结束):");
char name[20];
scanf("%s", name);
if (strcmp(name, "q") == 0)
{
break;
}
else
{
strcpy(order[count], name);//将菜名保存
count++;
}
}
if (count > 0)
{
calculate_bill(order,count,t);
}
else
{
printf("\t\t你没有点任何菜品\n");
}
}
//顾客结账
void checkout()
{
printf("\t\t您一共消费%f元\n",total_price);
printf("\t\t请输入支付金额:");
float paid;
scanf("%f", &paid);
while (paid < total_price)
{
printf("\t\t支付金额不足,请重新输入:");
scanf("%f", &paid);
}
printf("\t\t找零:%.2f元\n", paid-total_price);
today_price+=total_price;
total_price=0;
printf("\t\t结账完成,欢迎再次光临!\n");
}
//补充菜品的数量
void supplement()
{
char name[20];//菜品名称
int n;
printf("\t\t请输入要补充菜品的名字:");
scanf("%s",name);
printf("\t\t请输入要补充菜品的数量:");
scanf("%d",&n);
struct dish *result = find_node(t.root, name);
if (result == NULL)
{
printf("\t\t未找到该菜品\n");
}
else
{
result->quantity+=n;
printf("\t\t菜品补充成功\n");
printf("\t\t%s剩余储量为%d\n",name,result->quantity);
}
}
//统计一次运行的总营销额度
void today_bill()
{
printf("\t\t今日总营销额度为%.2f元\n",today_price);
}
//希尔排序
void shell_sort(struct dish arr[], int n)
{
int gap, i, j;
struct dish temp;
for (gap = n / 2; gap > 0; gap /= 2)
{
for (i = gap; i < n; i++)
{
temp = arr[i];
for (j = i; j >= gap && arr[j - gap].count <temp.count; j-=gap)
{
arr[j] = arr[j - gap];
}
arr[j] = temp;
}
}
}
// 按销售额由大到小排序
void sort_sales_records(struct dish records[], int index)
{
if(index==0)
{
printf("\t\t还拥有菜单,无销售额\n");
}
shell_sort(records,index);
}
//将二叉树里的菜品暂时存储在数组
void sales_rank(struct dish *t,struct dish records[],int *index)
{
if (t)
{
sales_rank(t->left, records, index);
records[(*index)++] = *t;
sales_rank(t->right, records, index);
}
}
//按照销售额输出
void print(int index)
{
printf("\t\t***********************************\n");
printf("\t\t销售排行榜:\n");
for(int i=0;i<index;i++)
printf("\t\t%-20s%d\n",records[i].name,records[i].count);
printf("\t\t***********************************\n");
}
//管理员的操作选项函数
void manageDishes()
{
while (1)
{
int option;
printf("\t\t======================");
printf("\n\t\t请选择:\n");
printf("\t\t[1] 增加菜品\n");
printf("\t\t[2] 查找菜品\n");
printf("\t\t[3] 修改菜品信息\n");
printf("\t\t[4] 删除菜品\n");
printf("\t\t[5] 显示菜单\n");
printf("\t\t[6] 热推菜品\n");
printf("\t\t[7] 补菜数量\n");
printf("\t\t[8] 查看一天销售额统计\n");
printf("\t\t[9] 查看菜品销售排行榜\n");
printf("\t\t[10] 退出\n");
printf("\t\t======================\n\t\t");
scanf("%d", &option);
if(option==10) break;
switch (option)
{
case 1:
add_dish(&t);
break;
case 2:
find_dish(&t);
break;
case 3:
modify_dish(&t);
break;
case 4:
delete_dish(&t);
break;
case 5:
show_menu(&t);
break;
case 6:
hot_recommended();
break;
case 7://补菜的
supplement();
break;
case 8://统计一次运行程序的总营业额
today_bill();
break;
case 9://统计每一天菜品销售排行榜
{
int index=0;
sales_rank(t.root,records,&index);
sort_sales_records(records,index);
print(index);
break;
}
default:
printf("\t\t无效选项,请重新选择\n");
break;
}
}
}
//管理员的登入函数
void adminInterface()
{
int tag=0;
char password[20];
char newpassword[20];
char ch;
//文件里存放管理员登入密码
fp=fopen("password.txt","r");
//第一次使用将打开失败
if (fp == NULL)
{
printf("\t\t文件打开失败!\n");
return;
}
fscanf(fp, "%s", newpassword);
fclose(fp);
printf("\t\t请输入管理员密码:\n\t\t");
scanf("%s", password);
getchar();
while(strcmp(password,newpassword) != 0)
{
if(++tag==3)
{
printf("\t\t已经连续输错三次,安全系统启动\n");
printf("\t\t需要修改密码则回复q\n\t\t");
scanf("%c",&ch);
if(ch=='q')
{
printf("\t\t请输入您的新密码:\n\t\t");
scanf("%s",newpassword);
printf("\t\t密码修改成功\n");
break;
}
return ;
}
printf("\t\t密码错误,请重新输入\n\t\t");
scanf("%s", password);
getchar();
}
printf("\t\t成功进入管理员选项\n");
fp=fopen("password.txt","w");
fprintf(fp, "%s", newpassword);
fclose(fp);
manageDishes();
}
//消费者的操作选项函数
int customerInterface()
{
printf("\t\t成功进入就餐者选项\n");
while (1)
{
int option;
printf("\t\t======================\n");
printf("\t\t请选择:\n");
printf("\t\t[1] 查看菜单\n");
printf("\t\t[2] 点餐\n");
printf("\t\t[3] 结账离开\n");
printf("\t\t[4] 热销菜品\n");
printf("\t\t[5] 退出\n");
printf("\t\t======================\n\t\t");
scanf("%d", &option);
switch (option)
{
case 1:
show_menu(&t);
break;
case 2:
Ordering(&t);
break;
case 3:
checkout();
break;
case 4:
show_menu(&hottree);
break;
case 5:
if(total_price!=0)
{
printf("\t\t您还没有结账,请结账后再离开\n");
break;
}
printf("\t\t欢迎下次光临\n");
return 0;
default:
printf("\t\t无效选项,请重新选择\n");
break;
}
}
}
//按照先序读取文件到树里
void buildtree(struct dish **root)
{
char name[20];
float price;
int quantity;
int count;
//判断文件是否读到末尾
while(fscanf(fp, "%s%f%d%d", name, &price, &quantity,&count) == 4)
{
struct dish *newDish = (struct dish *)malloc(sizeof(struct dish ));
strcpy(newDish->name, name);
newDish->price = price;
newDish->quantity = quantity;
newDish->count= count;
newDish->left = newDish->right = NULL;
if(*root==NULL) *root=newDish;
else insert_node(*root,newDish);
}
}
//按照先序存储菜单到文件里
void saveDishes(struct dish *root)
{
if(root)
{
fprintf(fp, "%s %.2f %d %d\n", root->name, root->price, root->quantity, root->count);
saveDishes(root->left);
saveDishes(root->right);
}
}
//读取菜单文件
void loadDishes(struct tree *t)
{
//第一次使用将打开失败
fp = fopen("dishes.txt", "r");
if (fp == NULL)
{
printf("\t\t文件打开失败!\n");
return;
}
buildtree(&(t->root));
fclose(fp);
}
//按照先序存储热销菜单到文件里
void saveHotDishes(struct dish *root)
{
if(root)
{
fprintf(fp, "%s %.2f %d\n", root->name, root->price, root->quantity);
saveDishes(root->left);
saveDishes(root->right);
}
}
//读取热销菜单文件
void loadHotDishes(struct tree *hottree)
{
//第一次使用将打开失败
fp = fopen("hotdishes.txt", "r");
if (fp == NULL)
{
printf("\t\t文件打开失败!\n");
return;
}
buildtree(&(hottree->root));
fclose(fp);
}
// 主函数
int main()
{
system("color 9f");
system("cls");
init_tree(&t);
init_tree(&hottree);
loadDishes(&t);
loadHotDishes(&hottree);
int identity;//身份 1为管理者 2为就餐者
while(1)
{
printf("\t\t******************登录系统*****************\n");
printf("\t\t欢迎来到好运来餐厅!\n");
printf("\t\t请输入登录身份:\n");
printf("\t\t[1] 管理员\n");
printf("\t\t[2] 就餐者\n");
printf("\t\t[3] 退出\n");
printf("\t\t*******************************************\n\t\t");
scanf("%d", &identity);
if(identity==3)
{
printf("\n\t\t欢迎下次光临哦!!!!\n");
break;
}
switch (identity)
{
case 1:
adminInterface();break;
case 2:
customerInterface();break;
default:
printf("\t\t输入错误,请重新输入\n");
}
}
//因为存储菜品需要遍历树,所以在主函数就将文件指针fp打开
fp=fopen("dishes.txt","w");
saveDishes(t.root);
fclose(fp);
fp=fopen("hotdishes.txt","w");
saveHotDishes(hottree.root);
fclose(fp);
}