文章目录
前言
关于超市货架管理系统,具体使用语言C++,其中用到STL Stack 和Vector
以个人的想法编写而成代码,感觉使用stack和vector比较方便,就天马行空的写下代码✍,供自己学习,仅供参考。
一、超市货架管理系统
1.题目说明
在商店中,每种商品用一个货架专门摆放。生产日期越近的越靠近货架底部,出货时从货架顶层取货。一天营业结束后,如果货架不满,则需要上货。如果直接将商品摆放到货架上,会使生产日期越近的商品越靠近货架顶层,这样就需要倒货架,使生产日期越近的越靠近货架底部。
2.功能要求及说明
设计一个算法实现商品货架的摆放管理,要求实现以下操作:
(1)初始化商品货架。商品种类不少于10种,每种商品的货架容量为100。
(2)每种商品至少包含商品名称,数量和生产日期3种属性,生产日期以年月日的形式存放。营业时间客户可以从货架取走商品,但取走商品的数量不能超过已有库存量;
(3)当天营业结束后,对货架不满的商品进行上货操作时,保证每一次上货后生产日期越近的商品越靠近货架底部;
(4)上货结束后,对每个商品按照从货架顶部到货架底部的顺序,打印出所有商品的数量和生产日期。
(5)采用模块化设计,分别以函数形式描述上述各功能,程序界面清晰简洁。
3.测试数据
当天营业结束时,商品“牛奶”的货架上有生产日期分别为“2017-01-14”和“2017-04-22”的各20份,进行上货操作。
新上牛奶的生产日期为“2017-05-13”。上货结束后打印该货架上的商品信息应为:
牛奶:
生产日期为“2017-01-14”的数量20;
生产日期为“2017-04-22”的数量20,
生产日期为“2017-05-13”的数量60。
4.提示
以栈结构实现商店货架。生产日期越近的越靠近栈底,出货时从栈顶取货。如果直接将商品摆放到货架上,会使生产日期越近的商品越靠近栈顶,这样就需要倒货架,使生产日期越近的越靠近栈底。
5.个人分析
- 每一种商品包含信息,书写商品类,类中写信息
- 商品种类不少于10种,每种商品货架容量为100,不确定商品种类有多少,书写货架类 使用动态数组保存商品种类
- 上货、出货和打印信息,有关数量和生产日期,在关于生产日期的地方使用到栈和排序算法
- (根据4.提示) 生产日期近的为最近生产的,远的为生产有一段时间的,生产日期远的物品会先生产先进栈,导致生产日期近的物品在栈顶,由于需要先售卖生产日期远的,所以需要倒栈,使得生产日期远的在栈顶。 (好像有那么一丝丝的绕🤔)
- 以栈结构实现商品货架,为方便和速率,使用STL stack,装载不同数量和生产日期的商品
- 货架装载商品,商品包含信息,货架使用动态数组保存商品种类,商品用栈装载每一次进货该商品的信息,即动态数组 数组元素为栈 栈中元素为商品类信息
二、具体实现
1.商品类
商品类中信息包括名称、数量和日期:
//商品类,商品信息
class Commodit
{
public:
string name; //商品名称
int num; //数量
int year; //年份
int month; //月份
int day; //日期
};
2.货架类
货架类私有属性为商品类,即货架上放商品:
class Shelves
{
private:
Commodit* data; //商品信息
public:
void ComInit(stack<Commodit>&s, vector<stack<Commodit>>&v);//初始化
void PutCom(stack<Commodit>&s, vector<stack<Commodit>>&v);//上货
void OutCom(stack<Commodit>&s, vector<stack<Commodit>>&v);//出货
void PrintCom(stack<Commodit>&s, vector<stack<Commodit>>&v);//显示货物的信息
};
这里使用了STL stack和vector 记得添加头文件
#include<vector>
#include<stack>
3.main方法
Shelves S; //货架
Commodit *com; //商品信息
com = new Commodit;
stack<Commodit> s; //STL stack
vector<stack<Commodit>> v; //动态数组vector
菜单的话 就看自己设计啦
switch (select)
{
case 1: //1.初始化
S.ComInit(s,v);
break;
case 2: //2.营业时间售卖
S.OutCom(s,v);
break;
case 3: //3.营业结束上货
S.PutCom(s,v);
break;
case 4: //4.商品信息打印
S.PrintCom(s,v);
break;
case 5: //5.退出
exit(0);
default:
break;
}
4.初始化
初始化数据,这肯定是必不可少的😀
cout << "请输入商品种类数量:" << endl;
cin >> ComNUM;
for (int i = 0; i <= ComNUM - 1; i++)
{
Commodit C; //商品类信息作为结点
stack<Commodit> s;
cout << "商品名称:" << endl; //商品名称
cin >> C.name;
cout << "商品数量:" << endl; //商品数量
cin >> C.num;
if (C.num > 100)
{
C.num = 100;
}
cout << "商品的日期:(年--月--日):" << endl; //商品日期
cin >> C.year >> C.month >> C.day;
cout << endl;
s.push(C); //商品信息作为结点进栈
v.push_back(s); //栈作为数组元素进数组
}
依次输入商品的名称和数量,因为容量最大为100,所以数量最多为100
然后输入的商品信息入栈,栈又作为数组元素
5.出货售卖
到点出货售卖了😘
首先肯定是要输入商品的名称和需要买的数量的
string BuyName; //输入需要购买的商品名称
int BuyNum,count=0;
cout << "输入需要购买的商品的名称:" << endl;
cin >> BuyName; //要购买的数量
cout << "输入需要购买的数量:" << endl;
cin >> BuyNum;
但是好像没写如果不存在商品的时候的情况。
然后开始进行判断
for (int i = 0; i <= v.size() - 1; i++)
{
if (!v[i].empty())
{
v[i].top();
if (v[i].top().name == BuyName && BuyNum > 0) //找到名称对应的商品,并且要购买的数量要保证大于0
{
stack<Commodit> temp; //临时的栈来储存
while (!v[i].empty()) //先统计栈里面此类商品的总数Num
{
Commodit C;
count = v[i].top().num + count; //计算栈里面商品总共的数量:count
C = v[i].top();
v[i].pop();
temp.push(C); //另一个栈保存至原本的栈为空
}
while (!temp.empty()) //倒栈还回来至临时的栈为空
{
Commodit Temp;
Temp = temp.top();
temp.pop();
v[i].push(Temp);
}
if (count < BuyNum) //需要购买的数量大于库存,提示需要上货
{
cout << "商品数量不足,需要上货。" << endl;
}
if (count >= BuyNum) //库存大于购买量,够数量售卖
{
if (v[i].top().num == BuyNum) //比较栈顶元素结点的num和需要购买的数量大小
{
v[i].pop(); //栈顶元素与购买量相等,则直接出栈。
if (v[i].empty())
{
cout << "此商品售至数量为0,货架上不存在这个商品,需要重新初始化。" << endl; //数量为0时,货架上不存在这个东西,要重新初始化
break; //为什么不加break时,当唯一结点num正好买完时候,栈空会报错?
}
break;
}
if (v[i].top().num > BuyNum) //栈顶元素的num比需要购买的大,则数量直接相减
{
v[i].top().num = v[i].top().num - BuyNum;
break;
}
if (v[i].top().num < BuyNum) //若栈顶元素的num比需要购买的小,则先出栈后再取新的栈顶元素进行判断
{
BuyNum = BuyNum - v[i].top().num;
v[i].pop();
while (!v[i].empty()) //往下新的栈顶元素进行判断比较
{
if (v[i].top().num == BuyNum) //栈顶元素num等于购买量时,出栈
{
v[i].pop();
break;
}
if (v[i].top().num > BuyNum) //num比购买量大,数量相减
{
v[i].top().num = v[i].top().num - BuyNum;
break;
}
if (v[i].top().num < BuyNum) //仍然不足时,出栈再取新的栈顶元素再判断
{
BuyNum = BuyNum - v[i].top().num;
v[i].pop();
}
}
}
}
}
}
}
数量的判断就很麻烦,要考虑购买数量和已有数量的关系,还容易出现空指针的情况。
太多判断条件了,其实感觉可以优化一下,而且还用倒栈,就感觉效率很低
6.上货补货
别看售卖这么复杂,其实补货更加复杂,不仅要保证售卖的时候先售卖生产日期远的,然后还有根据生产日期进行一个排序,如果生产日期相同,又因为数量的问题,需要相加等等操作
string InName; //上货商品名称
for (int i = 0; i <= v.size() - 1; i++)
{
if (!v[i].empty())
{
v[i].top();
if (v[i].top().name == InName)
{
stack<Commodit> temp; //临时的栈储存
stack<Commodit> sort; //排序栈
while (!v[i].empty())
{
Commodit C;
count = v[i].top().num + count; //统计原本的栈里面商品的总数
C = v[i].top();
v[i].pop();
temp.push(C); //倒栈,至原本的栈为空
}
if (count == 100)
{
cout << "货架上容量已满,不需要上货。" << endl;
break;
}
Commodit Add; //上货,作为新结点
Add.name = InName;
cout << "输入需要新上货的商品数量:" << endl; //输入新上货商品的数量
cin >> Add.num;
if (count + Add.num > 100) //保证货架容量为100,修正数值
{
Add.num = 100 - count;
}
cout << "输入需要新上货的商品的日期:" << endl; //输入新上货商品的日期
cin >> Add.year >> Add.month >> Add.day;
//进行排序,保证打印信息日期最近的在下面,年份的比较
if (Add.year < temp.top().year)
{
while (Add.year < temp.top().year)
{
Commodit comsort;
comsort = temp.top();
temp.pop(); //栈顶元素出栈
sort.push(comsort); //进行判断是否与新的栈顶元素日期相同
if (!temp.empty() && Add.year == temp.top().year && Add.month == temp.top().month && Add.day == temp.top().day)
{
Add.num = Add.num + temp.top().num; //与新的栈顶元素日期相等,上货的数量修正加上原本在栈里的商品数量
temp.pop(); //新的栈顶元素出栈
break; //break 出while 让上货的结点进栈
}
if (temp.empty())
{
break;
}
}
temp.push(Add); //排序完成进栈
while (!sort.empty())
{
Commodit backsort;
backsort = sort.top();
sort.pop();
temp.push(backsort);
}
}
//进行排序,保证打印信息日期最近的打印出来在下面,年份相等的情况下月份的比较
if (Add.year == temp.top().year && Add.month < temp.top().month)
{
while (Add.year == temp.top().year && Add.month < temp.top().month)
{
Commodit comsort;
comsort = temp.top();
temp.pop(); //栈顶元素出栈
sort.push(comsort); //进行判断是否与新的栈顶元素日期相同
if (!temp.empty() && Add.year == temp.top().year && Add.month == temp.top().month && Add.day == temp.top().day)
{
Add.num = Add.num + temp.top().num; //与新的栈顶元素日期相等,上货的数量修正加上原本在栈里的商品数量
temp.pop(); //新的栈顶元素出栈
break; //break 出while 让上货的结点进栈
}
if (temp.empty())
{
break;
}
}
temp.push(Add); //排序完成进栈
while (!sort.empty())
{
Commodit backsort;
backsort = sort.top();
sort.pop();
temp.push(backsort);
}
}
//进行排序,保证打印信息日期最近的打印出来在下面,年份月份相等的情况下月份的比较
if (Add.year == temp.top().year && Add.month == temp.top().month && Add.day < temp.top().day)
{
while (Add.year == temp.top().year && Add.month == temp.top().month && Add.day < temp.top().day)
{
Commodit comsort;
comsort = temp.top();
temp.pop(); //栈顶元素出栈
sort.push(comsort); //进行判断是否与新的栈顶元素日期相同
if (!temp.empty()&& Add.year == temp.top().year && Add.month == temp.top().month && Add.day == temp.top().day)
{
Add.num = Add.num + temp.top().num; //与新的栈顶元素日期相等,上货的数量修正加上原本在栈里的商品数量
temp.pop(); //新的栈顶元素出栈
break; //break 出while 让上货的结点进栈
}
if (temp.empty())
{
break;
}
}
temp.push(Add); //排序完成进栈
while (!sort.empty())
{
Commodit backsort;
backsort = sort.top();
sort.pop();
temp.push(backsort);
}
}
//日期相等的情况中,与栈顶元素日期相等的情况
if (Add.year == temp.top().year && Add.month == temp.top().month && Add.day == temp.top().day)
{
temp.top().num = Add.num + temp.top().num;
}
//新上货的日期为最近最新的,不需要排序,直接上货
if (Add.year > temp.top().year || (Add.year == temp.top().year && Add.month > temp.top().month)
|| (Add.year == temp.top().year && Add.month == temp.top().month && Add.day > temp.top().day))
{
temp.push(Add); //因为倒栈,商品在临时储存的栈里面
}
while (!temp.empty() && count<100) //倒栈回来,至临时的栈为空
{
Commodit Temp;
Temp = temp.top();
temp.pop();
v[i].push(Temp);
}
}
}
}
7.遍历打印信息
一开始认为这个打印信息,这难道不是最好写的嘛,直接输出就好了
等写到上货和出货,突然想起来,是不是打印信息也需要倒栈操作呢?
//打印商品所有信息
void Shelves::PrintCom(stack<Commodit>&s, vector<stack<Commodit>>&v)
{
string Secondname;
cout << "输入需要打印的商品的名称:" << endl;
cin >> Secondname;
for (int i=0;i<=v.size()-1;i++) //遍历动态数组vector
{
if(!v[i].empty())
{
v[i].top();
if (v[i].top().name == Secondname)
{
stack<Commodit> temp; //临时的一个栈储存
while (!v[i].empty())
{
Commodit C;
C = v[i].top();
cout << "商品名称为:" << v[i].top().name << endl; //打印信息
cout << "商品数量为:" << v[i].top().num << endl;
cout << "商品的生产日期为:" << v[i].top().year << "-" << v[i].top().month << "-" << v[i].top().day << endl;
v[i].pop();
temp.push(C);
}
while (!temp.empty()) //倒栈回来,至原本栈为空
{
Commodit Temp;
Temp = temp.top();
temp.pop();
v[i].push(Temp);
}
}
}
}
}
感觉倒栈操作,还是蛮复杂的,不知道是不是使用stack的问题呢,或许还有方法可以优化呢
总结
这就是自己所设想的超市货架管理系统了,其实还是有很多可以优化的地方的,而且好像还会有空指针的情况出现,代码中还有很多书写不规范的地方,当时写的时候没有在意命名规则 emmmm 以后改进 一开始拿到题目的时候,感觉都想用类来写,但是发现关于数量的问题就很难表示最后用到stack 和 vector 感觉还是很方便的,这也是c++强大的地方吧
不得不说STL stack和 vector真的真的真的很方便
个人学艺不精代码,如果写的不当之出,可以指出,共同学习🙃