资源描述
设计内容 公司库存管理系统
一、设计规定
1.目的和规定
(1)规定学生纯熟掌握C++语言的基本知识和技能;
(2)规定运用面向对象的方法以及C++的编程思想来完毕系统的设计,在设计的过程中,建立清楚的类层次;;
(3)基本掌握面向对象程序设计的基本思绪和方法;
(4)在系统中定义类,每个类中要有各自的属性和方法;
(5)在系统的设计中,至少要用到面向对象的一种机制。
(6)可以运用所学的基本知识和技能,解决简朴的面向对象程序设计问题。
(7)写出设计说明书
2.设计内容
1、问题描述(功能规定):
某公司现有以下设备:普通电视机、DVD、带DVD的电视机,带DVD的电视机的售价为普通电视机和DVD单价之和的80%,规定对所有的库存设备都能按照品名进行显示、查找、入库和出库、保存的功能。
普通电视机有下列属性:尺寸、类型(液晶或等离子) 、售价、重量、品牌、入库数量、入库编号
DVD有下列属性:规格(高清、蓝光高清、普通)、售价、重量、品牌、入库数量、入库编号
带DVD的电视机是上两者的派生类,但请注意有些属性的反复问题。
规定生成的相关库存数据结果以文献方式存放在硬盘中,或用链表、数组来进行管理。
2、问题的解决方案:
根据系统功能规定,可以将问题解决分为以下环节:
(1)写出需求分析(做什么),建立该系统的功能模块框图;
(2)分析系统中的各个实体之间的关系及其属性和行为;
(3)根据问题描述,设计系统的类层次;
(4)完毕类层次中各个类的描述(涉及属性和方法);
(5)完毕类中各个成员函数的定义;
(6)完毕系统的应用模块;
(7)功能调试;
(8)完毕系统总结报告以及系统使用说明书。
3.设计环境
Windows操作系统、VC++6.0、C++语言
4.个人承担任务
重要负责系统的显示、查找、入库、出库重要功能实现和系统封装。
二、系统需求分析
公司库存管理系统程序中,系统规定我们设计四个类:一个基础类Device,由Device类派生出来的普通电视机类和DVD类;再由普通电视机类和DVD类共同派生出来的带DVD的普通电视机类。在这个系统中我们需要实现重要的五个功能:1、显示物品功能;2、查找物品功能;3、入库物品功能;4、出库物品功能;5、保存物品功能。
公司库存管理系统重要是为了让用户根据自己的需要自己想输入的一些物品,然后将其保存,当用户想查看所有物品时可以查看,想添加物品时可以添加自己想添加的相关物品信息;当用户根据实际物品的库存调整时,可以进行出入库操作,并且记录每一次的出入库的时间和数量,以便日后查看;当用户想查找某一物品时,用户可以输入这一物品的名称或入库编码,然后搜索并查看这一物品的所有信息。
在这个系统中,用户可以根据系统的提醒分别执行用户自己想实现的功能,比如:在显示物品功能中用户可以查看用户所保存的所有物品信息;在查找物品功能中用户可以根据自己的需要输入自己想查找的物品名称或入库编码,然后查找用户想查找的物品的所有相关信息;在出、入库物品功能中用户可以根据自己的需要输入自己想要出、入库的物品名称或入库编码,然后进行出、入库操作;在物品保存功能中,凡是用户每对库存系统内部的信息进行一次操作,系统就会自动保存并记录相关信息。
三、程序设计思绪
1、系统功能模块图:
从系统的需求中我们可以看到:该系统要对产品进行显示、查找、入库、出库和保存功能。这就意味着这个系统需要一个show函数(通过cout将数据显示在屏幕上)来实现显示功能,而其他各个功能需要不同的模块来实现,也就意味着这个系统需要五个不同的功能模块。
菜
单
1、显示物品信息
2、查找物品信息
3、入库物品信息
4、出库物品信息
5、退出系统
派生
派生
2、公司库存管理系统中各功能模块的实现:
a. 显示物品模块:
在输入好库存信息后,库存信息就会被保存到“库存清单。txt”文本中,然后根据菜单显示选择“1、显示物品信息”,就会直接调用文本文献中的所有信息并加以显示。
b.查找物品信息:
查找物品信息
查找类型
查找名称
显示物品信息
显示物品出、入库记录
c.入库物品信息:
选择“3、入库物品信息”后,一方面刷屏显示现有库存信息的所有内容,方便用户观测需要入库的产品信息和具体库存数量。之后,可以根据选择入库编码或者设备名称来查找需要入库的具体设备。假如该设备存在于库存当中,则输入入库数量,提醒入库成功;假如仓库中没有该种设备,则提醒“对不起,没有找到该库存物品。”入库成功后,该物品库存数量增长,库存记录增长。
如图:
d.出库物品信息:
出库物品信息和入库物品信息操作原理同样,显示相同;只但是一个增长一个减少,在此就不再赘述。
e.保存效果:
3、具体程序代码书写思绪:
由于用的c++编程语言和环境,所以针对于面向对象的程序书写理念。我将程序模块化,把类的实现进行了封装,运用创建一个工程的方式把程序做的更为具体和清楚。在关键地方,在程序后面做有注释,便于其别人阅读和分析。
四、总结
本公司库存管理系统很好的实现了“显示、查找、入库、出库、保存”的重要功能,较为完美的实现了本次程序设计的重要规定。除此之外,我还在程序中增长了一定的纠错能力,比如当出库数量大于现有库存是会提醒“库存局限性,请重新输入”的提醒,直到用户输入对的的数值为止。并且,在用户对于菜单的属于操作出现失误时,系统也会根据具体情况进行相应的提醒,避免了死循环的出现,方便了用户的操作、增长了系统的健壮性。
对于程序的书写,可以说这个程序的封装以及模块化结构做的很好,主程序很简朴,需要运用函数的时候直接调用相应部分即可。这对于程序书写时的修改、校正也极为方便,避免了“牵一发而动全身”的麻烦。我觉得这种模块化的思想应当继续保持,运用到此后的程序设计当中,既避免了主程序过于繁杂的麻烦,也为其别人的阅读、分析和此后的程序改良提供了方便。
在程序应用中,菜单选项仅是对于现有库存的各种操作和解决,但并没有提供外部接口让用户积极添加其它的物品信息。对于此,我们特意增长了文本修改功能,可以从后台的地方增长或删减现有库存信息。填补了库存不可变动的缺陷。也体现了,重要信息需要掌握在公司内部人员手中,而不能随意进行修改的理念。
五、调试及其测试
(调试出现的重要问题,编译语法错误及修改,重点是运营逻辑问题修改和调整)
1、 由于本次设计用到了类,而类中有受保护的对像和私有对象,他们都不可以在类外使用。于是使得下边一些数据不能使用。最后我只能将数据全改成公有数据。这样也让继承的时候不会出现问题。
2、 本次程序几经修改才做到了现在这个样子,起初是一个长达700多行的程序,没有运用封装和工程,显得程序比较冗长。但是有个严重的问题就是每次程序重新启动的时候上次录入的信息和记录就所有清零,必须重新录入才可以进行出、入库解决,这样就使程序丧失了实用性,所以针对这个问题我特意书写的录入代码,让程序可以在一开始运营的时候就把库存清单里的信息先读入系统,然后再在这个基础上进行添加删除等操作,这样才干真正做到一个实用的系统。
3、 由于系统规定必须把库存的信息保存到文本文献,这个操作我们课上只做了简朴的介绍,并且凭借现有的知识尚有所欠缺,我在查阅了大量资料和请教别人之后才逐步搞懂了这个环节。由此通过修改写出了第二个程序,可以调用文本文献并且可以进行复杂操作的程序。
4、 除此之外,一开始我保存和显示库存信息的文献方式也有所欠缺,没有做到空间的合理运用,通过老师的点拨和修改后,我设立了“string”字符串,让所有信息以字符串的形式显示和保存,并控制了每一个字段的长度,这样在现实的时候就显得十分美观,也便于读取和观测。
5、 之后,我又在这个程序的基础上,进行了进一步的延伸。由于程序规定必须把每一个库存信息都要储存,为了避免反复与不好记录的方面,我只好把添加信息的菜单隐藏,放于后台解决。对于用户界面只对现有库存信息进行显示、查找、入库、出库的操作。假如想要添加信息,那就得在“库存菜单.txt”的这个文献里直接进行输入。这样修改的好处在于,我可以把信息做的系统化,并且可以记录每一次的出、入库记录,并加以显示。
6、 最后,我将四个类封装解决,设立工程,程序模块化设计,真正的体现了一个c++程序设计的思想。
六、用户手册
1、显示菜单
在这里输入“1、2、3、4、5”进行菜单操作,每一步都会有系统字样提醒,根据提醒进行信息录入即可。假如录入错误,系统会有自动提醒,重新录入对的信息即可。
2、显示信息。
在主菜单中直接输入数字1,进行菜单显示,由于显示信息较多,所以最佳调整一下显示框大小,避免出现显示错位的现象。
显示后,根据菜单提醒输入“1”返回主菜单,输入“2”退出程序。(以下相同,不再提醒)
3、查找物品信息
在主菜单中直接输入数字2,进行物品查找,在查找选项中可以通过入库编码和设备名称两样分别进行查找。
查找后,显示该物品的具体信息并且显示近期来针对于本物品的出、入库信息。
4、出、入库物品信息
在主菜单中直接输入数字3或4,进行物品出、入库。选择物品出、入库后,系统会自动把所有库存信息进行显示,让用户可以看到可以入库的设备名称和入库编码,然后进行选择。一方面要选择进行出、入库的设备,之后按提醒输入出、入库的数量。(注:在出库时,假如出库数量大于现有库存就会提醒“库存局限性”)。等到屏幕显示“入(出)库成功!”时,物品入(出)库成功。
5、退出程序
在主菜单中直接输入数字5,退出程序。
七、附录:
(程序源代码)
1、Device类
#include<iostream>
#include<fstream>
#include<cstring>
#include<windows.h>
#include<string>
using namespace std;
class Device
{
public:
bool mask[11]; //定义字段是否应当被屏蔽(true:字段无效,false:字段有效)
void *fs; //指向全局fileSystem对象的指针
string strCategory; //设备分类:1-普通电视机, 2-DVD, 3-DVD电视机
string strName; //货品名称
string strDate; //日期
//string strSize; //仅对TV有效,TV尺寸
//string strType; //仅对TV有效,TV类型
//string strCharactor; //仅对DVD有效,DVD规格
string strWeight; //重量
string strPrice; //价格
string strBrand; //品牌
int nTotal; //数量
string strCode; //入库编码
Device();
virtual ~Device();
virtual void Update(int n) = 0; // 出入库n台设备的操作,n>0:入库;n<0:出库
virtual void Show() = 0; // 展示当前库存和出入库记录
};
#include "stdafx.h"
#include "Device.h"
Device::Device(){}
Device::~Device(){}
2、DVD类
#include "Device.h"
class DVD : virtual public Device
{
public:
string strCharactor; //仅对DVD有效,规格
DVD();
virtual ~DVD();
void Update(int n); // 入库n台设备的操作
void Show(); // 展示当前库存和出入库记录
};
#include "stdafx.h"
#include "DVD.h"
#include "fileSystem.h"
DVD::DVD()
{
strCategory = "DVD";
for (int i = 0; i < FIELDNUM; i ++){
mask[i] = false;
}
mask[3] = true;
mask[4] = true;
}
DVD::~DVD(){}
void DVD::Update(int n) // 出入库n台设备的操作
{
nTotal += n;
char buf[BUFSIZE];
if (n > 0) {
sprintf(buf, "%s (%s) 入库 %d 台。 ", strName.c_str(), strCategory.c_str(), n);
} else {
sprintf(buf, "%s (%s) 出库 %d 台。 ", strName.c_str(), strCategory.c_str(), -n);
}
((fileSystem *)fs)->Save(buf);//进行物品记录保存
}
void DVD::Show() // 展示当前库存和出入库记录
{
//显示当前库存
//显示标题行
for(int i = 0; i < FIELDNUM; i ++){
if (mask[i]) {
continue;
}
cout << ((fileSystem *)fs)->strTitles[i];
}
cout << endl;
//显示所有数据
string values[FIELDNUM];
char total[BUFSIZE];
values[0] = strCategory;
values[1] = strName;
values[2] = strDate;
values[6] = strPrice;
values[7] = strWeight;
values[8] = strBrand;
sprintf(total, "%d", nTotal);
values[9] = total;
values[10] = strCode;
values[3] = "NA";
values[4] = "NA";
values[5] = strCharactor;
for(int ii = 0; ii < FIELDNUM; ii ++){
if (mask[ii]) {
continue;
}
for(int j = values[ii].size(); j < COL_WIDTH; j ++) {
values[ii].append(" ");
}
cout << values[ii];
}
cout << endl;
//显示出入库记录
cout << endl << "出入库记录如下:" << endl;
((fileSystem *)fs)->ShowLog(strName);
}
3、TV类
#include "Device.h"
#include<cstring>
#include<windows.h>
#include<string>
class TV : virtual public Device
{
public:
string strSize; //仅对TV有效, 尺寸
string strType; //仅对TV有效,类型
TV();
virtual ~TV();
void Update(int n); // 出入库n台设备的操作,n>0:入库;n<0:出库
void Show(); // 展示当前库存和出入库记录
};
#include "stdafx.h"
#include "TV.h"
#include "fileSystem.h"
TV::TV()
{
strCategory = "普通电视机";
for (int i = 0; i < FIELDNUM; i ++){
mask[i] = false;
}
mask[5] = true;
}
TV::~TV(){}
void TV::Update(int n) // 出入库n台设备的操作
{
nTotal += n;
char buf[BUFSIZE];
if (n > 0) {
sprintf(buf, "%s (%s) 入库 %d 台。 ", strName.c_str(), strCategory.c_str(), n);
}
else {
sprintf(buf, "%s (%s) 出库 %d 台。 ", strName.c_str(), strCategory.c_str(), -n);
}
((fileSystem *)fs)->Save(buf);
}
void TV::Show() // 展示当前库存和出入库记录
{
//显示当前库存
//显示标题行
for(int i = 0; i < FIELDNUM; i ++){
if (mask[i]) {
continue;
}
cout << ((fileSystem *)fs)->strTitles[i];
}
cout << endl;
//显示所有数据
string values[FIELDNUM];
char total[BUFSIZE];
values[0] = strCategory;
values[1] = strName;
values[2] = strDate;
values[6] = strPrice;
values[7] = strWeight;
values[8] = strBrand;
sprintf(total, "%d", nTotal);
values[9] = total;
values[10] = strCode;
values[3] = strSize;
values[4] = strType;
values[5] = "NA";
for(int ii = 0; ii < FIELDNUM; ii ++){
if (mask[ii]) {
continue;
}
for(int j = values[ii].size(); j < COL_WIDTH; j ++) {
values[ii].append(" ");
}
cout << values[ii];
}
cout << endl;
//显示出入库记录
cout << endl << "出入库记录如下:" << endl;
((fileSystem *)fs)->ShowLog(strName);
}
4、TV_DVD类
#include "DVD.h"
#include "TV.h"
class TV_DVD : virtual public TV
{
public:
DVD innerDvd;
TV_DVD();
virtual ~TV_DVD();
void Show(); // 展示当前库存和出入库记录
};
#include "stdafx.h"
#include "TV_DVD.h"
#include "fileSystem.h"
TV_DVD::TV_DVD()
{
strCategory = "DVD电视机";
for (int i = 0; i < FIELDNUM; i ++){
mask[i] = false;
}
}
TV_DVD::~TV_DVD(){}
void TV_DVD::Show() // 展示当前库存和出入库记录
{
//显示当前库存
//显示标题行
for(int i = 0; i < FIELDNUM; i ++){
if (mask[i]) {
continue;
}
cout << ((fileSystem *)fs)->strTitles[i];
}
cout << endl;
//显示所有数据
string values[FIELDNUM];
char total[BUFSIZE];
values[0] = strCategory;
values[1] = strName;
values[2] = strDate;
values[6] = strPrice;
values[7] = strWeight;
values[8] = strBrand;
sprintf(total, "%d", nTotal);
values[9] = total;
values[10] = strCode;
values[3] = strSize;
values[4] = strType;
values[5] = innerDvd.strCharactor;
for(int ii = 0; ii < FIELDNUM; ii ++){
if (mask[ii]) {
continue;
}
for(int j = values[ii].size(); j < COL_WIDTH; j ++) {
values[ii].append(" ");
}
cout << values[ii];
}
cout << endl;
//显示出入库记录
cout << endl << "出入库记录如下:" << endl;
((fileSystem *)fs)->ShowLog(strName);
}
5、fileSystem函数
#include<iostream>
#include<fstream>
#include<cstring>
#include<windows.h>
#include<string>
using namespace std;
#define FIELDNUM 11 //库存数据文献的字段数量
#define BUFSIZE 100 //库存数据文献的每行最大字数
#define COL_WIDTH 12 //用于显示的列宽
#define MAXDEVICE 20 //系统最大允许设备数量
#include "Device.h"
#include "TV.h"
#include "DVD.h"
#include "TV_DVD.h"
#include "time.h"
#include "stdio.h"
class fileSystem
{
public:
void ShowLog(string strName);
void Save(string strMsg);
void Show();
string strTitles[FIELDNUM];
void InitAllDevices();
void * devs[MAXDEVICE];
int devsCategory[MAXDEVICE]; //设备分类:1-普通电视机, 2-DVD, 3-DVD电视机
int nDevs; //库存设备个数
string strKCFileName; //库存数据文献名
string strLogFileName; //出入库日记文献名
fileSystem();
virtual ~fileSystem();
private:
void release();
string strValues[FIELDNUM];
};
#include "stdafx.h"
#include "fileSystem.h"
using namespace std;
fileSystem::fileSystem()
{
strKCFileName = "库存清单.txt";
strLogFileName = "出入库日记.txt";
nDevs = 0;
InitAllDevices();
//Show();
//Save("save");
//ShowLog("A型电视机");
//((DVD *)devs[5])->Update(-5);
//((TV *)devs[5])->Show();
}
fileSystem::~fileSystem()
{
release();
}
void fileSystem::InitAllDevices()
{
release();
ifstream in(strKCFileName.c_str());
// 第一行是字段标题
for (int i = 0; i < FIELDNUM; i ++) {
in >> strTitles[i];
for(int j = strTitles[i].size(); j < COL_WIDTH; j ++) {
strTitles[i].append(" ");
}
//cout << strTitles[i];
}
//cout << endl;
// 读取所有库存记录
nDevs = 0;
bool bRead = true;
while (bRead) {
for (int i = 0; i < FIELDNUM; i ++) {
in >> strValues[i];
if (strValues[i].size() == 0) {
bRead = false;
break;
}
//cout << strValues[i];
}
if (!bRead) {
break;
}
if (strValues[5] == "NA") {
// create TV class
TV *tvTemp = new TV();
devs[nDevs] = tvTemp;
tvTemp->strName = strValues[1];
tvTemp->strDate = strValues[2];
tvTemp->strSize = strValues[3];
tvTemp->strType = strValues[4];
tvTemp->strPrice = strValues[6];
tvTemp->strWeight = strValues[7];
tvTemp->strBrand = strValues[8];
tvTemp->nTotal = atoi(strValues[9].c_str());
tvTemp->strCode = strValues[10];
devsCategory[nDevs] = 1;
tvTemp->fs = this;
} else if (strValues[3] == "NA") {
// create DVD class
DVD *dvdTemp = new DVD();
devs[nDevs] = dvdTemp;
dvdTemp->strName = strValues[1];
dvdTemp->strDate = strValues[2];
dvdTemp->strCharactor = strValues[5];
dvdTemp->strPrice = strValues[6];
dvdTemp->strWeight = strValues[7];
dvdTemp->strBrand = strValues[8];
dvdTemp->nTotal = atoi(strValues[9].c_str());
dvdTemp->strCode = strValues[10];
devsCategory[nDevs] = 2;
dvdTemp->fs = this;
} else {
// create TV_DVD class
TV_DVD *tdTemp = new TV_DVD();
devs[nDevs] = tdTemp;
tdTemp->strName = strValues[1];
tdTemp->strDate = strValues[2];
tdTemp->strSize = strValues[3];
tdTemp->strType = strValues[4];
tdTemp->strPrice = strValues[6];
tdTemp->strWeight = strValues[7];
tdTemp->strBrand = strValues[8];
tdTemp->nTotal = atoi(strValues[9].c_str());
tdTemp->strCode = strValues[10];
tdTemp->innerDvd.strCharactor = strValues[5];
devsCategory[nDevs] = 3;
tdTemp->fs = this;
}
//cout << endl;
nDevs ++;
}
in.close();
//Show();
}
void fileSystem::release()
{
for (int i = 0; i < nDevs; i ++) {
delete(devs[i]);
devs[i] = 0;
devsCategory[i] = 0;
}
nDevs = 0;
}
void fileSystem::Show()
{
//显示标题行
for(int i = 0; i < FIELDNUM; i ++){
cout << strTitles[i];
}
cout << endl;
//显示所有数据
for (int n = 0; n < nDevs; n ++) {
string values[FIELDNUM];
char total[BUFSIZE];
switch (devsCategory[n]) {
case 1:
values[0] = ((TV *)devs[n])->strCategory;
values[1] = ((TV *)devs[n])->strName;
values[2] = ((TV *)devs[n])->strDate;
values[6] = ((TV *)devs[n])->strPrice;
values[7] = ((TV *)devs[n])->strWeight;
values[8] = ((TV *)devs[n])->strBrand;
sprintf(total, "%d", ((TV *)devs[n])->nTotal);
values[9] = total;
values[10] = ((TV *)devs[n])->strCode;
values[3] = ((TV *)devs[n])->strSize;
values[4] = ((TV *)devs[n])->strType;
values[5] = "NA";
break;
case 2:
values[0] = ((DVD *)devs[n])->strCategory;
values[1] = ((DVD *)devs[n])->strName;
values[2] = ((DVD *)devs[n])->strDate;
values[6] = ((DVD *)devs[n])->strPrice;
values[7] = ((DVD *)devs[n])->strWeight;
values[8] = ((DVD *)devs[n])->strBrand;
sprintf(total, "%d", ((DVD *)devs[n])->nTotal);
values[9] = total;
values[10] = ((DVD *)devs[n])->strCode;
values[3] = "NA";
values[4] = "NA";
values[5] = ((DVD *)devs[n])->strCharactor;
break;
case 3:
values[0] = ((TV_DVD *)devs[n])->strCategory;
values[1] = ((TV_DVD *)devs[n])->strName;
values[2] = ((TV_DVD *)devs[n])->strDate;
values[6] = ((TV_DVD *)devs[n])->strPrice;
values[7] = ((TV_DVD *)devs[n])->strWeight;
values[8] = ((TV_DVD *)devs[n])->strBrand;
sprintf(total, "%d", ((TV_DVD *)devs[n])->nTotal);
values[9] = total;
values[10] = ((TV_DVD *)devs[n])->strCode;
values[3] = ((TV
展开阅读全文