本实验中所涉及的仓库管系统的设计要求如下:
通过实地调研,了解仓库管中的主要数据流程(入库、统计(查询)、出库);
-
- 设计仓库管理程序的模块结构;
- 要求采用命令行参数来控制程序中不同模块的执行(或字符界面下的菜单驱动);
下面是老师给的大体模板:
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#include <malloc.h>
/*
1)需求分析,确定要存储什么数据,要实现什么功能;
2)定义数据类型;
*/
//如果在实验过程中,修改了结构体类型,则应删除已有文件!!!!
struct GOODS {
//主要属性
char strNo[11]; //商品编号(10个字符-数字或字母)
char strName[21]; //商品名称(10个中文或20个字母)
float fPrice; //商品价格
int nInventory; //库存数量,当库为0时,根据statusOK的值,确定是【缺货】还是【下架】
//辅助属性,由程序处理
//为了提高数据处理效率,数据库(含关系数据库或基于文件的数据库);
//删除数据往往是仅仅在记录上打一个“标记”;
//待系统空闲时再统一处理;
//本实验中可以是:在保存数据到文件时,过滤掉带有删除标记的数据
char isDeleted; //如何使用,同学们可自行考虑
char statusOK; //'0' 表示下架,‘1'表示正常
};
//3)声明函数(一个函数可以对应一个模块)
//入库,对里的命令行参数:inbound
//可以是更新库存或增加新的记录
int inbound(struct GOODS goods[], int nUsedNum);
//出库,对里的命令行参数:outbound
//可以是更新库存或删除记录
int outbound(struct GOODS goods[], int nUsedNum);
//查询:通过命令参数:querybyno
void query_by_no(struct GOODS goods[], int nUsedNum);
//显示帮助信息
void Print_Help();
//以下为辅助函数,不对外开放
//为了实现基于文件的数据库,定义read_from_file, write_to_file
//本实验中数据库是存储在自定义格式的文件中的(基本文件的数据库);
//当数据类型(结构体)变更后,文件也可进行转换;
//在本实验中,如果改变形了结构体的内容,则通过删除已存在的文件的办法来重新生成文件数据库
//可思考这做做的缺点是什么 ? 如何可以保留原有数据?
int _read_from_file(struct GOODS goods[]); //从文件中读数据到内存
void _write_to_file(struct GOODS goods[], int nUsedNum); //将内存中的数据保存到文件中
int _query_by_No(struct GOODS goods[], int nUsedNum, char strNo[]); //从数据中按商品号查找
int main(int argc, char* argv[])
{
//4)在主函数中完成预定模块的调用
//最大库存为400条记录
struct GOODS* goods; //为解决数组大于受限的问题,本实验采用动态申请空间的方法来存储数据
int nUsedNum = 0;
if (argc != 2)
{
Print_Help();
return -1;
}
else {
//为拟加载到内存中的数据申请空间
goods = (struct GOODS*)malloc(sizeof(struct GOODS) * 400); //给出初始值,以方便调试
if (goods == NULL) {
printf("申请空间不成功,程序将退出\n");
return -1;
}
//在此入调用加载数据到内存的函数
//读文件的函数执行行,将返回当前库存数
nUsedNum = _read_from_file(goods);
//argv是一个指向字符指针的指针;
//也可以用*argv读取安指向的字符串,*(argv+1)读下一个字符串
//程序支持的命令行参数 inbound,outboud,querybyname,help
if (!strcmp(argv[1], "inbound")) //也可写成 if(strcmp(argv[1],"Hello")==0)
nUsedNum = inbound(goods, nUsedNum);
else if (!strcmp(argv[1], "outbound"))
nUsedNum = outbound(goods, nUsedNum);
else if (!strcmp(argv[1], "querybyno")) //命令参数为 querybyno no
query_by_no(goods, nUsedNum);
else if (!strcmp(argv[1], "help"))
Print_Help();
else
Print_Help();
//在程序退出前,保存数据到文件中
_write_to_file(goods, nUsedNum);
//程序退出前释放已申请的空间
free(goods);
}
return 0;
}
//5)分模块调试程序
//入库,对里的命令行参数:inbound
int inbound(struct GOODS goods[], int nUsedNum) {
printf("I am in inbound function\n");
//1) 先读入商品编号,在现实社会中,该步骤可能是扫描条码!!;
char strNo[21];
printf("请输入商品编号\n");
scanf("%s", strNo); //strNo已是地址
//2) 调用函函查找该商品是否已在库中;
int nIndex;
//为在此调用查询函数
//目前该函数还未给出具体实现,调用时返回-1
//同学们调试程序时,应首先实现_query_by_no( 要注意这是内部函数,对外的是 query_by_no
nIndex = _query_by_No(goods, nUsedNum, strNo);
if (nIndex >= 0) {
//3) 如果在库中,输入商品数量,同时更新库存
;//这是空语句
}
else {
//4) 如果不在库中,则输入全部数据(记录增加一条)
//应进行基础练习,熟练掌握scanf printf的用法
//先输提示信息
printf("strName(%%s) fPrice(%%f) nInventory(%%d)\n");
//1)可通过Visual Studio 的Debug功能调试输入数据
//2)在初学阶段,可采用一个scanf只输入一个变量,且输入后立即输出的方式调试
strcpy(goods[nUsedNum].strNo, strNo); //将已输入的商品号复制到新增加的记录中
scanf("%s", goods[nUsedNum].strName); //strName已是地址
scanf("%f", &goods[nUsedNum].fPrice); //取变量的地址
scanf("%d", &goods[nUsedNum].nInventory); //取变量的地址
printf("Debue Info Begin\n");
//应充份利用C语书写自由的特点,以易读的方式书写代码
printf("%s %s %f %d\n", goods[nUsedNum].strNo,
goods[nUsedNum].strName,
goods[nUsedNum].fPrice,
goods[nUsedNum].nInventory
);
printf("Debug Info End\n");
nUsedNum++; //新增加一条记录
}
return nUsedNum;
}
//出库,对里的命令行参数:outbound
int outbound(struct GOODS goods[], int nUsedNum) {
printf("I am in outbound function\n");
return nUsedNum;
}
//查询:用户通过命令参数输入拟查询的商品
void query_by_no(struct GOODS goods[], int nUsedNum) {
printf("I am in query by No. function\n");
return;
}
//显示Help信息
void Print_Help() {
printf("本程序的正确用法:\n");
printf("Week_151 help | inbound | outbound | querybyname\n");
return;
}
//辅助函数,仅仅供内部使用,不对外部用户开放
//根据商品编号查询,返回-1表示未查到,否则返回的是商品在数组中的序列号
//此函数不处理任何其它的输入、输出操作
int _query_by_No(struct GOODS goods[], int nUsedNum, char strNo[]) {
int nIndex = -1;
printf("I am in query_by_name function\n");
return nIndex;
}
//为了实现基于文件的数据库,定义read_from_file, write_to_file
int _read_from_file(struct GOODS goods[]) {
int n = 0;
FILE* fp;
fp = fopen("MyDatabase.dat", "rb");
if (fp == NULL) {
printf("打开文件读出错:MyDatabase.dat\n");
return 0; //读文件出错时,返回0个记录
}
while (fread(&goods[n], sizeof(struct GOODS), 1, fp) == 1) {
n++;
}
fclose(fp);
return n;
}
void _write_to_file(struct GOODS goods[], int nUsedNum) {
FILE* fp;
fp = fopen("MyDatabase.dat", "wb");
if (fp == NULL) {
printf("打开文件写出错:MyDatabase.dat\n");
return; //读文件出错时,返回0个记录
}
for (int i = 0; i < nUsedNum; i++) {
fwrite(&goods[i], sizeof(struct GOODS), 1, fp);
}
/*
//也可按如下方式来写数据
fwrite(goods,sizeof(GOOSS),nUsedNum,fp);
*/
fclose(fp);
return;
}
想要完整的数据库代码,主要是如何实现入库、统计(查询)、出库等功能,并且希望说明一下这个小程序应该如何使用,谢谢了。