技术文档和源代码在阿里云盘分享
密码:29wi
文件失效可联系
主函数:
#define _CRF_SECURE_NO_WARNINGS
#include "shop.h"
//当时的问题:①多运行几次就出错 ②分多个源程序就无法在用户登录时看到管理者操作后的数据
int main()
{
struct goods shangpin[300];//商品最多300件
int x , m , quit = 0,quit1 = 1,quit2 = 1;//x,m为使用者输入的导航数字,quit控制退出系统,分1,2是因为加入执行完管理操作并退出时会导致quit变为 0而影响下一步执行用户操作时的quit判断,导致用户操作完一个操作后就直接退出登录界面
while(1)
{
quit = 0;
menu_1();//选择登录方式的菜单
scanf("%d",&m);//得到登录方式的导航数字
getchar();//消去数字后的回车符,避免下次n读为回车
switch(m)
{
case 1://管理界面
while(1)
{
quit1 = 1;
menu_2();//管理登录后的菜单
scanf("%d",&x);//得到管理选择的操作导航数字
getchar();//避免回车影响以下函数中的scanf
switch(x)
{
case 1:
raise(shangpin);//增加商品
break;
case 2:
reduce(shangpin);//减少商品
break;
case 3:
revise(shangpin);//修改商品
break;
case 4:
profit(shangpin);//查看盈利
break;
case 5:
stock(shangpin);//查看库存
break;
case 0:
quit1 = 0;//quit1 = 0时会退出登录
break;//break出 33行的switch
default:
printf("请输入正确的数字!!n");
printf("按任意键重新输入!");
getchar();
}
if(quit1 == 0)//控制退出登录
{
printf("即将退出登录!!n");
printf("按任意键退出登录!!n");
getchar();
break;//break出 27行的while,到 66行
}
}
break;//接着 break出 24行的switch
case 2://用户界面
while(1)
{
quit2 = 1;
menu_3();//用户登录后的菜单
scanf("%d",&x);//得到用户选择的操作导航数字
getchar();//避免回车影响以下函数中的 scanf
switch(x)
{
case 1:
showall(shangpin);//显示所有商品
break;
case 2:
sousuo(shangpin);//搜索某个商品
break;
case 3:
buy(shangpin);//购买商品
break;
case 0:
quit2 = 0;//quit2 = 0时退出登录
break;//break出 74行的switch
default:
printf("请输入正确的数字!!n");
printf("按任意键重新输入!");
getchar();
}
if(quit2 == 0)//quit2 = 0时退出登录
{
printf("即将退出登录!!n");
printf("按任意键退出登录!!n");
getchar();
break;//break出 68行的 while,到 101行
}
}
break;//继续 break出 24行的 switch
case 0://在选择登录方式时输入 0直接关闭程序
quit = 1;//因为 quit 初始化为 0,所以这时候要将 quit 的值改为 1
break;
default:
printf("请输入正确的数字!!n");
printf("按任意键重新输入!");
getchar();
break;//break出 24行的 switch,这里不用 goto ,因为最外层是 while(1),所以这里break出去后会再次从 19 行开始执行
}
if(quit == 1)//只要前面 103行没有执行 quit = 1 的赋值操作,就不会执行该判断语句,也就是选择登录方式的程序会一直执行,由此来满足管理者修改的数据到用户登录时同样可用
{
printf("程序即将结束!!n");
printf("按任意键结束程序!!n");
getchar();//起按任意键继续的作用
return 0;//return就会结束程序
}
}
return 0; //这个 return可以不要,因为 while(1)一直执行,程序不会运行到这里
}
//有时间就增加用户评论功能 、管理查看评论功能
shop.h函数:
#define _CRF_SECURE_NO_WARNINGS #ifndef SHOP //测试SHOP是否被宏定义过,避免重新使用 #define SHOP #include#include #include #define RRR printf("%-10s%-10s%-10s%-10sn","序号", "名称", "价格", "库存") #define LLL printf("%-10s%-10s%-10s%-10s%-10s%-10sn","序号", "名称", "价格", "库存", "销售量", "盈利额") static int n ; //全局变量n控制、记录商品总数 struct goods { int i;//商品序号 char name[20];//商品名称 float price;//商品价格 int stock;//商品库存 int sum;//销售量 float yingli;//盈利额 }; void menu_1();//登录方式菜单 void menu_2();//管理登录后的菜单 void menu_3();//用户登录后的菜单 void raise(struct goods sp[]);//增加商品 void reduce(struct goods sp[]);//减少商品 void revise(struct goods sp[]);//修改商品 void profit(struct goods sp[]);//查看盈利 void stock(struct goods sp[]);//查看库存 void showall(struct goods sp[]);//显示所有商品 void sousuo(struct goods sp[]);//搜索商品 void buy(struct goods sp[]);//购买商品 void show1(struct goods sp[], int i); void show2(struct goods sp[], int i); #endif
shop.c函数:
#define _CRF_SECURE_NO_WARNINGS
#include "shop.h"
void raise(struct goods sp[])
{
char goods_name[20];//存储商品的名字
int i = 0;//控制结构体数组下标变量变化
char quit; //保存是否退出的选择
int m;//获得总记录数 n,如果直接使用 n--作后面的 while循环条件,就会导致总记录数改变
do
{
loop://对应 37行,起重新输入商品作用
i = 0;// 避免第二次及以上次删除商品时i为第一次删除商品结束后的i
m = n;//不能直接使用 n
printf("商品名称:");
scanf("%s", goods_name);
getchar();//清楚回车符
while(m -- > 0)//相当于 n-- 以此来依次查找是否有相同的商品,总共执行 n 次
{
if (strcmp(goods_name,sp[i].name) == 0) //查找名称相同的商品
{
printf("此商品存在!n");
again://对应 48行
printf("是否重新输入?(Y/y/N/n)n");
scanf("%c",&quit);
getchar();
if(quit == 'Y' || quit == 'y')//不用 &&是因为 Y和 y二者满足其一就可以执行
{
printf("按任意键重新输入商品!");
getchar();
goto loop;//跳至 loop处(18行),重新输入商品名称,使用 break和 return都不合理
}
else if(quit == 'N' || quit == 'n')//同理上
{
printf("按任意键退出!");
getchar();
return;//如果用户不重新输入就直接退出登录
}
else
{
printf("请输入正确的操作字符!");
goto again;//跳回 29行重新选择是否重新输入
}
}
i++;//控制结构体数组 sp的下标变化,依次调出每一个商品进行比较
}
printf("商品序号为:%dn",i + 1);
sp[i].i = n + 1;//不能用 i,因为上面查找是否有相同的商品时,i一直增加,如果选择 106行重新输入商品,就会导致sp[i].i等于一直增加的i,从而新增的商品的序号不是接着上一个有效商品的连续序号
strcpy(sp[i].name , goods_name);//将字符串 goods_name赋值给 sp[i].i
printf("商品价格:");
scanf("%f", &sp[i].price);//此处要用 &,因为 price是非数组和字符串指针,如 22 行 goods_name是字符数组,所以可以不用&
printf("商品库存:");
scanf("%d", &sp[i].stock);
getchar();//因为下面一个 scanf 中有 %c ,回车是字符,所以要先消除回车符
n++; //总商品数加 1
printf("是否继续添加?(Y/y/N/n)n");
scanf("%c", &quit);
getchar();
} while (quit != 'N' && quit != 'n');//do-while 先执行后判断
printf("按任意键退出!!n");
getchar();
}
void reduce(struct goods sp[])
{
char goods_name[20];//存储商品的名字
int i = 0;//控制结构体数组下标变量变化
char quit,again; //quit保存是否退出的选择,again再次确认是否删除该商品
int m;//获得总记录数n,如果直接使用n--作后面的while循环条件,就会导致总商品数改变
do
{
again://对应 121行,起继续删除作用
i = 0;// 避免第二次及以上次删除商品时i为第一次删除商品结束后的i
m = n;
printf("商品名称:");
scanf("%s", goods_name);
getchar();
while(m -- > 0)//同理raise函数
{
if (strcmp(goods_name,sp[i].name) == 0)//strcmp比较两个字符串,如果相同就返回 0
{
printf("找到该商品信息如下:n");
LLL;
show2(sp,i);//只显示出一件商品的信息
YYY://对应 113行,起重新输入的作用
printf("是否确定要删除该商品?(Y/y/N/n)n");
scanf("%c",&again);
getchar();
if(again == 'Y' || again == 'y')
{
for(; i < n; i++)//所有商品信息都前移一位(后一位商品信息替代前一位商品信息)
{
sp[i] = sp[i+1];
(sp[i].i) -- ;//使删除后序号都向前减一
}
n -- ;//总商品数减一
printf("删除成功!n");//提高界面友好性
}
else if(again == 'N' || again == 'n')
{
printf("取消删除成功!n");
}
else
{
printf("请输入正确的操作符号!n按任意键重新输入!");
getchar();
goto YYY;//跳到 91行重新输入
}
again2://对应 132行,起重新输入操作字符的作用
printf("是否需要删除其它商品?(Y/y/N/n)n");
scanf("%c",&quit);
getchar();
if(quit == 'Y' || quit == 'y')//不用 &&是因为 Y和 y二者满足其一就可以执行
{
goto again;//跳到 78行继续删除
}
else if(quit == 'N' || quit == 'n')//同理上
{
printf("按任意键退出!n");
getchar();
return;//如果没找到,且选择了退出,则直接return,否则会输出 138 行的信息,出现错误提示
}
else
{
printf("请输入正确的操作字符!n");
goto again2;//跳到 115行,重新输入操作字符
}
}
i++;//使结构体数组 sp下标变化
}
printf("未找到该商品信息!!n");//以下语句只有未找到商品信息时才会执行
printf("是否继续查找删除?(Y/y/N/n)n");
scanf("%c", &quit);
getchar();
} while (quit != 'N' && quit != 'n');
printf("按任意键退出!!n");
getchar();
}
void revise(struct goods sp[])
{
char goods_name[20];//存储商品的名字
int i;//控制循环、结构体数组下标变量变化
char quit,again; //quit保存是否退出的选择, again再次确认是否删除该商品
do
{
printf("商品名称:");
scanf("%s", goods_name);
getchar();
for(i = 0; i < n; i++)
{
if (strcmp(goods_name,sp[i].name) == 0) //同理上两个函数
{
printf("找到该商品信息如下:n");
LLL;
show2(sp,i);
printf("是否确定要修改该商品信息?(Y/y/N/n)n");
scanf("%c",&again);
getchar();
if(again == 'Y' || again == 'y')
{
printf("商品序号为:%dn",i + 1);//此处商品序号不可改*************************若要实现可改,可以scanf要改为的序号,然后依次比较是否有重复的序号,如果有就修改失败
printf("商品名称修改为:");
scanf("%s", sp[i].name);
printf("商品价格修改为:");
scanf("%f", &sp[i].price);
printf("商品库存修改为:");
scanf("%d", &sp[i].stock);
printf("修改成功!");//提高界面友好性
}
printf("按任意键退出!n");
getchar();
return;
}
}
printf("未找到该商品信息!!n");
printf("是否继续查找修改?(Y/y/N/n)n");
scanf("%c", &quit);
getchar();
} while (quit != 'N' && quit != 'n');
printf("按任意键退出!!n");
getchar();
}
void profit(struct goods sp[])
{
char goods_name[20];//存储商品的名字
int i;//控制循环、结构体数组下标变量变化
char quit,choice;//quit保存是否退出的选择 ,choice确定查找全部商品还是部分商品
chance://对应 257行
printf("您需要查找所有的盈利(A)还是单一商品的盈利(S)?n");//分全部和部分,丰富功能
scanf("%c",&choice);//将选择存入choice
getchar();
if(choice == 'A')
{
printf("%-10s%-10s%-10s%-10sn","序号", "名称", "销售量", "盈利额");
for(i = 0; i < n; i++)
{
printf("%-10d%-10s%-10d%-10fn",sp[i].i, sp[i].name, sp[i].sum, sp[i].yingli);
}
}
else if(choice == 'S')
{
do
{
loop://对应 232行
printf("商品名称:");
scanf("%s", goods_name);
getchar();
for(i = 0; i < n; i++)//查找输入的商品
{
if (strcmp(goods_name,sp[i].name) == 0)
{
printf("找到该商品的序号为:n");
printf("%dn", sp[i].i);
printf("销售量为:n");
printf("%dn", sp[i].sum);
printf("盈利额为:n");
printf("%fn", sp[i].yingli);
again://对应 244行
printf("是否继续查找?(Y/y/N/n)n");
scanf("%c", &quit);
getchar();
if(quit == 'Y' || quit == 'y')
{
goto loop;//跳至 212行继续查找
}
else if(quit == 'N' || quit == 'n')
{
printf("即将退出!n按任意键退出!");
getchar();
return;
}
else
{
printf("请输入正确操作数字!n按任意键重新输入!");
getchar();
goto again;//跳至 226行重新输入操作字符
}
}//这里不是用的 while循环,所以不需要另外加 i++,因为 i++已经在 for循环括号里了
}
printf("未找到该商品信息!!n");
printf("是否继续查询?(Y/y/N/n)n");
scanf("%c", &quit);
getchar();
} while (quit != 'N' && quit != 'n');
}
else
{
printf("请输入正确的操作符号!n");
goto chance;//跳到 Chance位置(196行)再进行选择
}
printf("按任意键退出!!n");
getchar();
}
void stock(struct goods sp[])
{
char goods_name[20];//存储商品的名字
int i;//控制循环、结构体数组下标变量变化
char quit;//quit保存是否退出的选择
char choice;//选择查找所有还是单一商品
chance://对应 328行
printf("您需要查找所有的库存(A)还是单一商品的库存(S)?n");//同理profit函数
scanf("%c", &choice);
getchar();
if(choice == 'A')
{
printf("%-10s%-10s%-10sn","序号", "名称", "库存");
for(i = 0; i < n; i++)
{
printf("%-10d%-10s%-10dn",sp[i].i,sp[i].name,sp[i].stock);
}
}
else if(choice == 'S')
{
do
{
loop://对应 303行,起继续查找作用
printf("商品名称:");
scanf("%s", goods_name);
getchar();
for(i = 0; i < n; i++)
{
if (strcmp(goods_name,sp[i].name) == 0)
{
printf("找到该商品的序号为:n");
printf("%dn", sp[i].i);
printf("库存为:n");
printf("%dn", sp[i].stock);
again://对应 315行,起重新输入作用
printf("是否继续查找?(Y/y/N/n)n");
scanf("%c", &quit);
getchar();
if(quit == 'Y' || quit == 'y')
{
goto loop;//跳至 280行
}
else if(quit == 'N' || quit == 'n')
{
printf("即将退出!n按任意键退出!");
getchar();
return;
}
else
{
printf("请输入正确操作数字!n按任意键重新输入!");
getchar();
goto again;//跳至 297行
}
}//i++已经在for循环括号里了
}
printf("未找到该商品信息!!n");
printf("是否继续查询?(Y/y/N/n)n");
scanf("%c", &quit);
getchar();
} while (quit != 'N' && quit != 'n');
}
else
{
printf("请输入正确的操作符号!n");
goto chance;//跳到 Chance位置(269行)再进行选择
}
printf("按任意键退出!!n");
getchar();
}
void showall(struct goods sp[])
{
int i;//控制商品一个个输出
RRR;
for (i = 0; i < n; i++)
{
show1(sp,i);
}
printf("按任意键退出!");
getchar();
}
void sousuo(struct goods sp[])
{
char goods_name[20];//存储商品名称
char again;//确认是否继续搜索商品、控制程序结束
int i;//控制结构体数组下标变化
while(1)
{
printf("请输入要搜索的商品的名称:");
scanf("%s", goods_name);
getchar();
for(i = 0; i < n; i++)
{
if(strcmp(sp[i].name,goods_name) == 0)
{
printf("找到该商品信息如下:n");
RRR;
show1(sp,i);
again://对应 381行,起重新输入操作符号的作用
printf("是否继续搜索?(Y/y/N/n)n");
scanf("%c", &again);
getchar();
if(again == 'Y' || again == 'y')
{
break;//break到 356行
}
else if(again == 'N' || again == 'n')
{
printf("即将退出!n按任意键退出!");
getchar();
return;
}
else
{
printf("请输入正确操作数字!n按任意键重新输入!");
getchar();
goto again;//跳至 363行
}
}
}
if(i == n)//避免 369行选择继续搜索时 break到本处输出 “未找到该商品信息”,输出错误提示信息
{
printf("未找到该商品信息!n");
again2://对应 406行,起重新输入操作字符的作用
printf("是否继续搜索?(Y/y/N/n)");
scanf("%c", &again);
getchar();
if(again == 'Y' || again == 'y')
{
//这里不用执行任何语句,如果满足判断条件,就进入该选择语句,从而不执行后面的else if和else ,然后出了 57行的if语句,继续执行 23行的while,从而起到继续搜索的作用
}
else if(again == 'N' || again == 'n')
{
printf("按任意键退出!");
getchar();
return;
}
else
{
printf("请输入正确操作数字!n按任意键重新输入!");
getchar();
goto again2;//跳至 388行,重新输入操作字符
}
}
}
}
void buy(struct goods sp[])
{
char goods_name[20];//存储商品名称
int i,j,num;//查找出要购买的商品信息, num记录要购买的商品数量 ,j避免发生错误
char confirm,again;//confirm确认是否要购买,again确认是否要继续购买
while(1)
{
loop://对应 479行,起 继续购买商品的作用
printf("请输入要购买的商品的名称:");
scanf("%s", goods_name);
getchar();
for(i = 0; i < n; i++)
{
if(strcmp(sp[i].name,goods_name) == 0)
{
printf("找到该商品的信息如下:n");
RRR;
show1(sp,i);
if(sp[i].stock != 0)//库存不为 0时才可以继续执行,否则执行 500行告诉用户库存不足
{
for(j = 0; ; j++)//j记录
{
while(j > 0)//如果为第二次及以上次购买时就执行这个while
{
if(sp[i].stock == 0)//如果上一次购买后库存为 0,就要执行这个if语句索引出正确提示信息 ,否则就会出现执行 117行以后的代码的情况,实际库存为 0,而 117行的代码叫用户输入要购买的数量,违背实际情况
{
goto pp;//跳至 491行,避免库存不够时还输出 445行后的代码
}
else
{
break;
}
}
printf("请输入要购买的数量:");
scanf("%d", &num);
getchar();
if(num <= sp[i].stock)//库存不为 0之后还一个 问题就是用户输入的购买数量,库存是否有这么多
{
printf("该商品单价为:%.3ft您要购买数量为:%dt总计费用:%.3fn",sp[i].price,num,num*sp[i].price);
printf("是否确认要购买?(Y/y/N/n)");
scanf("%c", &confirm);
getchar();
if(confirm == 'Y' || confirm == 'y')
{
printf("购买成功!");
printf("总计费用%fn", num * sp[i].price);
sp[i].stock -= num;
(sp[i].sum) += num;
(sp[i].yingli) += num * sp[i].price;
}
again://对应 486行
printf("是否需要继续购买?(Y/y/N/n)");
scanf("%c", &again);
getchar();
if(again == 'N' || again == 'n')
{
printf("按任意键退出!");
getchar();
return;
}
else if(again == 'Y' || again == 'y')
{
printf("继续购买本商品(X)还是继续购买其它商品(Y)?n");
scanf("%c", &again);//again可以重新使用,不受前面一次赋值的影响
getchar();
if(again == 'Y')
{
goto loop;//回到输入商品名称处 419行
}
}
else
{
printf("请输入正确的操作符号!n按任意键重新输入!");
getchar();
goto again;//跳至 462行重新输入
}
}
else
{
pp:
printf("库存不足,购买失败!n");
printf("目前您最多购买的数量为%d!n", sp[i].stock);
printf("按任意键退出!");
getchar();
return;
}
}
}
else
{
printf("库存不足,请等待商家添加库存!");
printf("按任意键退出!");
getchar();
return;
}
}
}
printf("未找到该商品信息!n");
NNN://对应 528行
printf("是否需要再次输入商品名称查找?(Y/y/N/n)n");
scanf("%c", &again);
getchar();
if(again == 'N' || again == 'n')
{
printf("按任意键退出!");
getchar();
return;
}
else if(again == 'Y' || again == 'y')
{
//此处可空语句
}
else
{
printf("请输入正确的操作字符!n按任意键重新搜索!");
getchar();
goto NNN;//跳至 510行重新搜索
}
}
printf("按任意键退出!");
getchar();
}
void show1(struct goods sp[], int i)
{
printf("%-10d", sp[i].i);
printf("%-10s", sp[i].name);
printf("%-10.3f", sp[i].price);//输出小数点后三位
printf("%-10dn", sp[i].stock);
}
void show2(struct goods sp[], int i)
{
printf("%-10d", sp[i].i);
printf("%-10s", sp[i].name);
printf("%-10.3f", sp[i].price);
printf("%-10d", sp[i].stock);
printf("%-10d", sp[i].sum);
printf("%-10.3fn", sp[i].yingli);//输出小数点后三位
}
void menu_1()
{
system("cls");//清空屏幕
printf("n");
printf("tt*****************************************n");
printf("tt*tt<超市系统>tt*n");
printf("tt*****************************************n");
printf("tt*t 1 管理登录 tt*n");
printf("tt*t 2 用户登录 tt*n");
printf("tt*t 0 退出系统 tt*n");
printf("tt*****************************************n");
printf("tt请输入你要进入的系统的序号:");
}
void menu_2()
{
system("cls");//清空屏幕
printf("n");
printf("tt*****************************************n");
printf("tt*tt<管理登录>tt*n");
printf("tt*****************************************n");
printf("tt*t 1 增加商品 tt*n");
printf("tt*t 2 减少商品 tt*n");
printf("tt*t 3 修改商品 tt*n");
printf("tt*t 4 查看盈利 tt*n");
printf("tt*t 5 查看库存 tt*n");
printf("tt*t 0 退出登录 tt*n");
printf("tt*****************************************n");
printf("tt请输入你要进入的系统的序号:");
}
void menu_3()
{
system("cls");//清空屏幕
printf("n");
printf("tt*****************************************n");
printf("tt*tt<用户登录>tt*n");
printf("tt*****************************************n");
printf("tt*t 1 全部商品 tt*n");
printf("tt*t 2 搜索商品 tt*n");
printf("tt*t 3 购买商品 tt*n");
printf("tt*t 0 退出登录 tt*n");
printf("tt*****************************************n");
printf("tt请输入你要进入的系统的序号:");
}



