目录
主要功能
1.管理员、店长两类账户;管理员管理账户数据,店长管理商品数据。
2.针对商品的编号、名称、库存量属性进行输入和分类,并可依据库存量进行排序。
代码
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include<conio.h>
typedef struct User
{
char UserID[20]; //用户ID
char password[12]; //密码
int UserFlag; //使用者标签 判别使用者 管理员:-1、店长:0
}User;
typedef struct sp
{
char no[12]; //编号
char name[40]; //名称
int workload; //库存
struct sp *next; //指针
} SP;
//预设一个 管理员 账户
User UserAdministrator = {"admin","root",-1};
//预设一个 店长 账户
User UserOwner = {"O","1",0};
void ListCreate(SP *L, int n); //创建商品链表节点
void LIstSearch(SP *L); //查找商品信息
void ListModify(SP *L); //修改商品信息
void ListInsert(SP *L); //插入商品信息
void ListDelete(SP *L); //删除商品信息
void Input(SP *p, int i); //输入商品信息
void SumSp(SP *L); //统计商品的库存总量
void Sort(SP *L); //对每类商品的库存量进行排名
void OwnerMenu(); //店长界面
int LoginStatus = 0;
//格式化 登录 登出 还原
void init_sys();
int Login();
void Logout();
void Restore();
//首页 管理者菜单
int Menu();
void AdministratorMenu();
//修改店主信息
void Modify_Owner();
//商品库存管理系统的主函数入口
int main()
{
int i=2;
int item, n; //item用于接收输入的命令,n用于接收输入的商品人数
SP *L = NULL; //初始化一个头节点
L = (SP *)malloc(sizeof(SP)); //为头节点开辟内存空间
L->next = NULL; //将头节点的指针域置空
while (i != 1&&i != 0)
{
init_sys();
i = Menu();
}
if (i != 0)
{
do
{
OwnerMenu();
printf("请输入相应的数字,进行相应的操作:\n");
scanf("%d", &item);
system("cls");
switch (item)
{
case 1:
printf("请输入您要录入的商品数目:");
scanf("%d", &n);
ListCreate(L, n);
getchar();
printf("\n请按任意键返回主菜单\n");
getchar();
system("cls");
break;
case 2:
LIstSearch(L); //查找商品信息
getchar();
printf("\n请按任意键返回主菜单\n");
getchar();
system("cls");
break;
case 3:
ListModify(L); //修改商品库存信息
getchar();
printf("\n请按任意键返回主菜单\n");
getchar();
system("cls");
break;
case 4:
ListDelete(L); //删除商品信息
getchar();
printf("\n请按任意键返回主菜单\n");
getchar();
system("cls");
break;
case 5:
ListInsert(L); //插入商品信息
getchar();
printf("\n请按任意键返回主菜单\n");
getchar();
system("cls");
break;
case 6:
SumSp(L);
getchar();
printf("\n请按任意键返回主菜单\n");
getchar();
system("cls");
break;
case 7:
Sort(L);
getchar();
printf("\n请按任意键返回主菜单\n");
getchar();
system("cls");
break;
case 0: //退出商品库存管理系统
printf("即将退出商品库存管理系统.....");
exit(0);
default:
printf("您输入的指令不正确,请重新输入");
}
printf("\n\n");
} while (item && i);
}
return 0;
}
//创建链表,将新生成的节点插入到链表的表头
void ListCreate(SP *L, int n)
{
int i;
for (i = 0; i < n; i++)
{
SP *p;
//将新生成的节点插入到链表中
p = NULL;
p = (SP *)malloc(sizeof(SP));
Input(p, i);
p->next = L->next;
L->next = p;
}
printf("录入成功!");
}
//查找商品库存量
void LIstSearch(SP *L)
{
char n[40];
SP *p = L->next;
if (p == NULL)
printf("数据为空,无法查找!");
else
{
printf("请输入您要查找的商品名称:");
scanf("%s", n);
while (strcmp(p->name, n) != 0)
{
p = p->next;
if (p == NULL)
{
printf("没有找到相关信息\n");
return;
}
}
printf("%s的库存量为%d\n",p->name,p->workload);
}
}
//修改商品的库存量
void ListModify(SP *L)
{
int a;
char nam[40];
SP *p = L->next;
if (p == NULL)
printf("数据为空,无法修改!");
else
{
printf("请输入您修改的商品名称:");
scanf("%s",nam);
while(strcmp(p->name, nam) != 0)
{
p = p->next;
if (p == NULL)
{
printf("没有找到相关信息\n");
return;
}
}
printf("请输入您修改后的库存量:");
scanf("%d",&p->workload);
printf("修改成功");
}
}
//删除商品信息
void ListDelete(SP *L)
{
char n[40];
SP *p = L->next, *pre = L; //定义p指针指向头节点的指向,定义pre指向头节点,pre始终指向p的前驱节点
if (p == NULL)
printf("数据为空,无法删除!");
else
{
printf("请输入您要删除的商品名称:");
scanf("%s", n);
while (strcmp(p->name, n) != 0)
{
pre = p;
p = pre->next;
if (p == NULL)
{
printf("没有找到相关信息,无法删除\n");
return;
}
}
pre->next = p->next;
free(p);
printf("删除成功");
}
}
//插入商品库存的相关信息
void ListInsert(SP *L)
{
SP *s = NULL; //生成一个新节点s
s = (SP *)malloc(sizeof(SP));
printf("请输入商品的商品编号:");
scanf("%s", s->no);
printf("请输入商品的名称:");
scanf("%s", s->name);
printf("请输入商品的库存量:");
scanf("%d", &s->workload);
s->next = L->next;
L->next = s;
printf("插入成功!");
}
//统计商品的库存总量
void SumSp(SP *L)
{
int sum=0;
SP *p=L->next;
while(p!=NULL)
{
sum+=p->workload;
p=p->next;
}
printf("商品的库存总量为%d\n",sum);
}
//对每类商品的库存量进行排名
void Sort(SP *L)
{
SP *p,*q,*tail,*l;
tail=NULL;
while((L->next->next) != tail)
{
p = L;
q = L->next;
while(q->next != tail)
{
if((q->workload) > (q->next->workload))
{
p->next = q->next;
q->next = q->next->next;
p->next->next = q;
q = p->next;
}
q = q->next;
p = p->next;
}
tail = q;
}
printf("商品库存量从小到大结果如下:\n");
l=L->next;
while(l!=NULL)
{
if(l->next!=NULL)
{
printf("%s(%d)->",l->name,l->workload);
l=l->next;
}
else
{
printf("%s(%d)",l->name,l->workload);
l=l->next;
}
}
}
//输入商品库存的相关信息
void Input(SP *p, int i)
{
printf("请输入第%d个商品的商品编号:", i + 1);
scanf("%s", p->no);
printf("请输入第%d个商品的名称:", i + 1);
scanf("%s", p->name);
printf("请输入第%d个商品的库存量:", i + 1);
scanf("%d", &p->workload);
}
int Menu()
{
while (1) {
system("cls");
printf("\t********************************\n");
printf("\t* *\n");
printf("\t* 1. 用户登录 *\n");
printf("\t* *\n");
printf("\t* ESC. 退出系统 *\n");
printf("\t* *\n");
printf("\t********************************\n");
switch (getch()) {
case 49: LoginStatus = Login(); break;
case 27: printf(" 系统退出成功.\n"); return 0;
}
if (LoginStatus == 1) {
AdministratorMenu();
}
else if (LoginStatus == 2) {
return 1;
}
else if (LoginStatus == -1) {
printf(" 系统退出成功.\n");
return 0;
}
}
}
void AdministratorMenu()
{
while(1)
{
system("cls");
printf("\t********************************\n");
printf("\t* *\n");
printf("\t* 1. 修改店主信息 *\n");
printf("\t* *\n");
printf("\t* 2. 还原账户信息 *\n");
printf("\t* *\n");
printf("\t* ESC. 退出登录 *\n");
printf("\t* *\n");
printf("\t********************************\n");
switch(getch())
{
case 49: Modify_Owner();break;
case 50: Restore();return;
case 27: Logout();return;
}
}
}
//商品库存管理系统的菜单
void OwnerMenu()
{
system("cls");
printf("\n\n");
printf("\t\t\t===================商品库存管理系统======================\n");
printf("\t\t\t* 作者:XXX 班级:XXXXXXXXXXX 学号:XXXXXXXXXX *\n");
printf("\t\t\t* *\n");
printf("\t\t\t* 1>. 录入商品库存信息 *\n");
printf("\t\t\t* 2>. 查找某个商品的库存量 *\n");
printf("\t\t\t* 3>. 修改某个商品的库存量 *\n");
printf("\t\t\t* 4>. 删除某个商品库存相关信息 *\n");
printf("\t\t\t* 5>. 插入某个商品的相关信息 *\n");
printf("\t\t\t* 6>. 统计商品的库存总量 *\n");
printf("\t\t\t* 7>. 对每类商品的库存量排名 *\n");
printf("\t\t\t* 0>. 退出管理系统 *\n");
printf("\t\t\t* 欢迎使用本系统!*\n");
printf("\t\t\t========================================================\n");
printf("\t\t\t输入选项,按回车进入选项: \n");
}
//登录
int Login(){
char _UserID[20];
char _password[12];
int count = 6; //限制5次登录尝试
system("cls");
printf("\t********************************\n");
printf("\t* 用户登录 *\n");
printf("\t********************************\n");
while(1){
//首次登录
if(count == 6){
printf(" 用户ID :");
scanf("%s",_UserID);
printf(" 密码 :");
scanf("%s",_password);
count--;
}else if(count == 0){
printf(" 错误次数已达上限,系统关闭");
return -1;
}else{
printf(" 用户ID或密码错误,您还有 %d 次机会\n",count);
printf(" 用户ID :");
scanf("%s",_UserID);
printf(" 密码 :");
scanf("%s",_password);
count--;
}
//strcmp(str1,str2) 返回值:
//如果返回值 < 0,则表示 str1 小于 str2。
//如果返回值 > 0,则表示 str2 小于 str1。
//如果返回值 = 0,则表示 str1 等于 str2。
if((strcmp(_UserID,UserAdministrator.UserID) == 0) && (strcmp(_password,UserAdministrator.password) == 0)){
//登录的是管理员账户
return 1;
}else if((strcmp(_UserID,UserOwner.UserID) == 0) && (strcmp(_password,UserOwner.password) == 0)){
//登录的是店主账户
return 2;
}
}
}
//登出
void Logout(){
LoginStatus = 0;
}
//修改店主信息
void Modify_Owner(){
FILE *fp;
char NewID[20];
char Newpassword[12];
system("cls");
printf("\t********************************\n");
printf("\t* 修改店主信息 *\n");
printf("\t********************************\n");
printf(" 请输入新的用户ID :");
scanf("%s",NewID);
printf(" 请输入新的密码 :");
scanf("%s",Newpassword);
memset(&UserOwner, 0, sizeof(UserOwner));
strncpy(UserOwner.UserID, NewID,strlen(NewID));
strncpy(UserOwner.password, Newpassword,strlen(Newpassword));
if((fp=fopen("Owner.txt","w+"))==NULL){
printf(" 修改失败!\n 按任意键以继续。");
}else{
if(fprintf(fp,"%s %s", UserOwner.UserID, UserOwner.password)<0){
fclose(fp);
remove("Owner.txt");
printf(" 修改失败!\n 按任意键以继续。");
}
else{
fclose(fp);
printf(" 修改成功!\n 按任意键以继续。");
}
}
getch();
}
//初始化账户系统
void init_sys(){
FILE *fp;
//打开店主信息文件,若存在则读取内容修改 UserOwner变量
if((fp=fopen("Owner.txt","r+"))==NULL) // w: 文件不存在则创建文件 r:文件不存在则返回NULL不创建文件
{
//不存在
printf("店主信息为默认信息...\n");
}else{
//修改店主信息
fscanf(fp,"%s %s", UserOwner.UserID, UserOwner.password);
fclose(fp);
}
}
//还原账号系统
void Restore()
{
FILE *fp;
if((fp=fopen("Owner.txt","r+"))==NULL)
{
printf("店主信息还原成功...\n");
}else
{
fclose(fp);
if(remove("Owner.txt") == 0)
{
printf("店主信息还原成功...\n");
}else
{
printf("店主信息还原失败\n");
}
}
if((fp=fopen("AssistantNumber.txt","r+"))==NULL)
{
printf("店员数量信息已归零...\n");
printf("店员信息还原成功...\n");
}
else
{
fclose(fp);
if(remove("AssistantNumber.txt") == 0)
{
if((fp=fopen("Assistant.txt","r+"))==NULL)
{
printf("店员数量信息已归零...\n");
printf("店员信息还原成功...\n");
}else
{
fclose(fp);
if(remove("Assistant.txt") == 0)
{
printf("店员数量信息已归零...\n");
printf("店员信息还原成功...\n");
}
else
{
printf("店员信息还原失败\n");
}
}
}
else
{
printf("店员信息还原失败\n");
}
}
LoginStatus = 0;
init_sys();
printf("系统信息还原完成,请重新打开程序。\n");
getch();
exit(0);
}
经验总结
1.system()清空命令行界面;getch()读取不回显字符并输出。
2.文件打开的完整报错流程。
3.使用初始化函数在每次打开程序时实现所有文件的读取。
4.注意野指针和指针越界问题。
优化方向
1.目前修改账户信息必须同时修改账号和密码。
2.使用插件实现图形化用户界面,而不是命令行用户界面。