C语言实现的销售管理系统
最后修改于2021/05/18
要求
某公司有N(N<=20)位销售员(编号:E001-E00N,至少包含销售员的若干基本信息如姓名、性别、受教育程度等),负责销售M(M<=30)个产品(编号:P001-P00M,至少包含产品的基本信息,如产品名称、单价、库存量等信息)。每个销售员在销售商品时,执行订单操作(销售记录,至少包含销售日期、销售编号、销售员编号、销售产品编号、销售数量等信息)。 设计一个简易库存-销售系统,使之能提供以下功能: 1、系统以菜单方式工作; 2、销售表信息录入功能(销售记录信息用文件保存)--输入; 3、统计销售情况 1)统计每个销售员的总销售额、每种产品的总销售额; 2)按销售额对销售员进行升序排序,输出排序结果; 3)按销售额对产品进行降序排序,输出排序结果。 (提示:至少应该有三个文件来保存基本数据,一个文件保存商品的基本信息,一个文件保存销售员的基本信息,还有一个文件保存销售记录。自行设计完整的数据结构并实现以上功能,程序应具有简单的错误处理,如不存在的销售员、超过库存的销售、不存在的产品等。如同学觉得能有更好的想法,也可以增加额外的功能,会酌情加分)。
项目的实验报告包括以下部分内容:
一、报告封面(请自行设计,内容清晰明了);
二、第一章:项目介绍;
三、第二章:完善的程序设计算法与流程;
四、第三章:清晰的测试结果;
五、第四章:分析与评论:完整且清晰的注释;
整个报告必须是:完整的包含以上内容且文档的总体风格非常专业(包括:参考文献、版权声明等)。
变量命名遵循的是谷歌的C/C++编程规范,结合注释应该不难理解本人的代码思路;
当初在设计的时候,安全是按照较大规模的数据进行设计的,对于题目要求的一百以内的数据,的确有点太冗杂了。
项目简介 本程序使用C语言进行编写,主要实现了对销售人员信息、商品信息、销售记录的录入与排序操作、文件的读写,为了加快查询速度和处理较大规模的数据量,使用Hash原理,可以在O(1)时间复杂度内通过关键值找到目标信息,但是不足之处在于作者还不能构建出一个把销售人员名字或商品名字作为关键值的Hash算法,只能把编号作为唯一的索引值。
C语言标准:C17
编译环境:gcc version 8.1.0 (x86_64-posix-seh-rev0, Built by MinGW-W64 project)
操作系统:Windows 10 20H2
开发工具:CLion 2021.1.1(JetBrains)、
Visual Studio Code 1.56.2(MircorSoft)
文件操作 程序中的文件路径均使用相对路径,所用到的文件与源代码在相同的目录之下
代码规范 函数、变量命名遵循Google的C/C++编程规范
代码如下:
头文件
#ifndef SalesSystem
#define SalesSystem
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#include <string.h>
#define KHashSize 50
const int KMaxSalesman = 20;
const int KMaxProduct = 30;
typedef struct _Salesman_ Salesman;
typedef struct _ProductInformation_ ProductInformation;
typedef struct _Data_ Data;
typedef struct _SaleRecord_ SaleRecord;
struct _Salesman_ //用来记录销售人员信息的结构体
{
int number; //编号
char name[20]; //姓名
char gender[4]; //性别;0为男,否则为女
char education_experience[20]; //教育经历;高中、本科、研究生、小学
double sumsale;
};
struct _ProductInformation_ //记录商品信息的结构体
{
int number; //编号
char name[20]; //商品名称
double price; //单价
int remain_quantity; //剩余的商品数量
double sumsale;
};
struct _Data_ //记录日期的结构体
{
int year; //年
int month; //月
int day; //日
};
struct _SaleRecord_ //记录销售记录,里面嵌套了两个结构体
{
Data data; //销售日期
int number; //销售编号
int count; //销售的数量
ProductInformation productinformation; //产品信息
Salesman salesman; //销售人员的信息
};
/*******************************************************/
//创建索引,可以在O(1)的时间复杂度由编号内找到对应的信息
Salesman *salesman_number_hash[KHashSize] = {NULL};
Salesman *salesman_name_hash[KHashSize] = {NULL};
ProductInformation *product_number_hash[KHashSize] = {NULL};
ProductInformation *product_name_hash[KHashSize] = {NULL};
SaleRecord *sale_record_number_hash[KHashSize] = {NULL};
/*******************************************************/
int compare_saleman(const void *a, const void *b) //对销售人员的销售额按照升序排列(从小到大)
{
Salesman *pa = (Salesman *)a;
Salesman *pb = (Salesman *)b;
return pa->sumsale - pb->sumsale;
}
int compare_product(const void *a, const void *b) //对单个商品的消费额按照降序排列(从大到小)
{
ProductInformation *pa = (ProductInformation *)a;
ProductInformation *pb = (ProductInformation *)b;
return pb->sumsale - pa->sumsale;
}
void PrintTips() //打印菜单
{
system("cls"); //清楚终端内的所有内容
printf("+--------------------------------------------------------+\n");
printf("| |*Menu*| |\n");
printf("| | 1.InPutSalesman | |\n");
printf("| | 2.InPutProductInformation | |\n");
printf("| | 3.InPutSaleRecord | |\n");
printf("| | 4.CalculateSaleSumOfProduct | |\n");
printf("| | 5.CalculateSaleSumOfSalesman | |\n");
printf("| | 6.SortSaleOfSalesman | |\n");
printf("| | 7.SortSaleOfProduct | |\n");
printf("| | 8.Exit | |\n");
printf("+--------------------- |*End*| -----------------------+\n");
printf("Please input your option:\n");
}
FILE *OpenFileSelf(const char *file_name, const char *mode) //打开文件并对是否打开做出处理
{
FILE *file_open = fopen(file_name, mode);
if (file_open == NULL)
{
puts("Open file error,Please try again!");
return 0;
}
else
{
puts("Open file succeed,Please continue!");
return file_open;
}
}
bool InPutJudge(int struct_size, int value) //验证输入的销售人员编号和商品编号是否在范围内,由结构体所占内存大小来判断是销售人员还是商品
{
//TODO Add more than repr
switch (struct_size)
{
case sizeof(Salesman):
if (value <= 0 || value > KMaxSalesman)
return false;
else if (value > 0 && value <= KMaxSalesman)
return true;
break;
case sizeof(ProductInformation):
if (value <= 0 || value > KMaxProduct)
return false;
else if (value > 0 && value <= KMaxProduct)
return true;
break;
default:
break;
}
}
bool JudgeRecord(SaleRecord *prameter) //对销售记录进行判断,包含对商品和销售人员的判断
{
if (!InPutJudge(sizeof(prameter->salesman), prameter->salesman.number)) //对销售人员编号进行验证
{
printf("Salesman number error!");
return false;
}
else if (!InPutJudge(sizeof(prameter->productinformation), prameter->productinformation.number)) //对商品编号进行验证
{
printf("Product number error!");
return false;
}
else if (prameter->count > product_number_hash[prameter->productinformation.number]->remain_quantity) //对库存进行验证
{
printf("exceed remanin quantity!");
return false;
}
else if (strcmp(prameter->salesman.name, salesman_number_hash[prameter->salesman.number]->name) != 0) //对销售人员名字进行验证
{
printf("Salesman name error!");
return false;
}
else if (strcmp(prameter->productinformation.name, product_number_hash[prameter->productinformation.number]->name) != 0) //对商品名称进行验证
{
printf("Product name error!");
return false;
}
else
return true;
}
void InPutSalesman() //输入销售人员的信息
{
system("cls");
int count = 0;
puts("Please input the number of saleaman:");
scanf("%d", &count);
FILE *file_open = OpenFileSelf("Salesman.txt", "w");
puts("Please input |number|*|name|*|gender|*|education_experience|");
fprintf(file_open, "|number| |name| |gender| |education_experience|\n");
for (int i = 1; i <= count; i++)
{
Salesman *temp = (Salesman *)malloc(sizeof(struct _Salesman_));
temp->sumsale = 0;
scanf("%d %s %s %s", &temp->number, temp->name, temp->gender, temp->education_experience);
if (InPutJudge(sizeof(Salesman), temp->number) && file_open)
{
fprintf(file_open, "%-10d %-20s %-3s %-12s %.2lf\n", temp->number, temp->name, temp->gender, temp->education_experience, temp->sumsale);
salesman_number_hash[temp->number] = temp;
}
else
puts("Your input illegal!");
}
fclose(file_open);
}
void InPutProductInformation() //输入商品的信息
{
system("cls");
int count = 0;
puts("Please input the number of ProductInformation:");
scanf("%d", &count);
FILE *file_open = OpenFileSelf("ProductInformation.txt", "w");
puts("Please input |number|*|name|*|price|*|remain_quantity|");
fprintf(file_open, "|number| |name| |price| |remain_quantity|");
for (int i = 1; i <= count; i++)
{
ProductInformation *temp = (ProductInformation *)calloc(1, sizeof(ProductInformation));
temp->sumsale = 0;
scanf("%d %s %lf %d", &temp->number, temp->name, &temp->price, &temp->remain_quantity);
if (InPutJudge(sizeof(ProductInformation), temp->number) && file_open)
{
fprintf(file_open, "%-5d %-20s %-4.2lf %-5d\n", temp->number, temp->name, temp->price, temp->remain_quantity);
product_number_hash[temp->number] = temp;
}
else
puts("Your input is illegal!");
}
fclose(file_open); //关闭文件,否则信息都会留在缓存区而没有保存到文件里面
}
void InPutSaleRecord() //输入销售记录
{
system("cls");
puts("Please input the number of SaleRecord");
int count;
scanf("%d", &count);
FILE *file_open = OpenFileSelf("SaleRecord.txt", "w");
if (file_open == NULL)
return;
fprintf(file_open, " Data Sale_number Sale_count Saleman_number Saleman_name Product_number Product_name\n");
printf("Please input Data(Year\\Month\\Day) ");
printf("sale_number sale_count ");
printf("product_number product_name");
printf(" Salesman_number->Salesman_name:\n");
for (int i = 1; i <= count; i++)
{
SaleRecord *temp = (SaleRecord *)malloc(sizeof(SaleRecord));
//printf("This %d Product:", i);
scanf("%d %d %d", &temp->data.year, &temp->data.month, &temp->data.day);
scanf("%d %d", &temp->number, &temp->count);
scanf("%d %s", &temp->productinformation.number, temp->productinformation.name);
scanf("%d %s", &temp->salesman.number, temp->salesman.name);
//if ((temp->count > 0 && temp->count < temp->productinformation.remain_quantity))
if (JudgeRecord(temp))
{
/******************************************************/
//由哈希表对输入的商品的信息进行修改
int product_key_number = temp->productinformation.number;
product_number_hash[product_key_number]->remain_quantity -= temp->count;
product_number_hash[product_key_number]->sumsale += product_number_hash[product_key_number]->price * temp->count;
/******************************************************/
int salesman_key_number = temp->salesman.number; //销售人员编号,也就是索引值
//对销售人员的信息进行修改
salesman_number_hash[salesman_key_number]->sumsale += product_number_hash[product_key_number]->price * temp->count;
fprintf(file_open, "%d/02%d/02%d %-10d %-10d %-10d %-10s %-10d %-10s\n",temp->data.year,temp->data.month,temp->data.day, temp->number, temp->count, temp->salesman.number, temp->salesman.name, temp->productinformation.number, temp->productinformation.name);
//printf("the %dth finished \n", i);
}
else
puts("Your input is illegal!");
}
fclose(file_open);
}
double CalculateSaleSumOfProduct() //计算所有产品的总销售额
{
double sum_sale_product = 0;
for (int i = 0; i <= KHashSize - 1; i++)
{
if (product_number_hash[i] == NULL)
continue;
else
sum_sale_product += product_number_hash[i]->sumsale;
}
return sum_sale_product;
}
double CalculateSaleSumOfSalesman() //计算所有销售人员的销售额
{
double sum_sale_salesman = 0;
for (int i = 0; i <= KHashSize - 1; i++)
{
if (salesman_number_hash[i] == NULL)
continue;
else
sum_sale_salesman += salesman_number_hash[i]->sumsale;
}
return sum_sale_salesman;
}
void SortSaleOfSalesman() //对销售人员按照销售额升序(从小到大)排序
{
//Salesman saleman=(Salesman*)malloc(sizeof(Salesman)*KHashSize);
Salesman saleman[KHashSize];
int count = 0;
for (int i = 0; i <= KHashSize - 1; i++)
{
if (salesman_number_hash[i] != NULL)
saleman[count++] = *(salesman_number_hash[i]);
else
continue;
}
qsort(saleman, count, sizeof(Salesman), compare_saleman);
FILE *file_open = OpenFileSelf("sort_sales_man.txt", "w");
puts("Salesman_name number gender education_experience sum_sales");
fprintf(file_open, "Salesman_name number gender education_experience sum_sales\n");
for (int i = 0; i <= count - 1; i++)
{
printf("%-14s %-7d %-10s %-20s %-5.2lf\n", saleman[i].name, saleman[i].number, saleman[i].gender, saleman[i].education_experience, saleman[i].sumsale);
fprintf(file_open, "%-14s %-7d %-10s %-20s %-5.2lf\n", saleman[i].name, saleman[i].number, saleman[i].gender, saleman[i].education_experience, saleman[i].sumsale);
}
}
void SortSaleOfProduct() //对商品信息的销售额按照降序(从大到小进行排序)
{
ProductInformation product[KHashSize];
int count = 0;
for (int i = 0; i <= KHashSize - 1; i++)
{
if (product_number_hash[i] != NULL)
product[count++] = *(product_number_hash[i]);
else
continue;
}
qsort(product, count, sizeof(ProductInformation), compare_product);
FILE *file_open = OpenFileSelf("sort_product_informantion.txt", "w");
puts("Product_name number sumsalse remain_quantity");
fprintf(file_open, "Product_name number sumsalse remain_quantity\n");
for (int i = 0; i <= count - 1; i++)
{
printf("%-14s %-7d %-10.2lf %-10d\n", product[i].name, product[i].number, product[i].sumsale, product[i].remain_quantity);
fprintf(file_open, "%-14s %-7d %-10.2lf %-10d\n", product[i].name, product[i].number, product[i].sumsale, product[i].remain_quantity);
}
}
void RecycleMemory() //对内存进行回收
{
for (int i = 0; i <= KHashSize - 1; i++)
{
if (salesman_number_hash[i] != NULL)
free(salesman_number_hash[i]);
if (product_name_hash[i] != NULL)
free(product_name_hash[i]);
if (sale_record_number_hash[i] != NULL)
free(sale_record_number_hash[i]);
else
continue;
}
}
#undef KHashSize //取消宏定义
#endif
main 函数如下;
#include "Sale.h"
int main()
{
//freopen("input_test_1.txt", "r", stdin);
while (1)
{
PrintTips();
int option = 0;
scanf("%d", &option);
double sale_sum_of_product = 0;
double sum_of_salesman = 0;
switch (option)
{
case 1:
InPutSalesman();
break;
case 2:
InPutProductInformation();
break;
case 3:
InPutSaleRecord();
break;
case 4:
sale_sum_of_product = CalculateSaleSumOfProduct();
printf("SalesSumOfProduct : %.2lf\n", sale_sum_of_product);
system("pause");
break;
case 5:
sum_of_salesman = CalculateSaleSumOfSalesman();
printf("sum_of_salesman :%.2lf\n", sum_of_salesman);
system("pause");
break;
case 6:
SortSaleOfSalesman();
system("pause");
break;
case 7:
SortSaleOfProduct();
system("pause");
break;
case 8:
RecycleMemory();
printf("End\n");
return 0;
default:
printf("Option is invalid.\nPlease check!\n");
break;
}
}
return 0;
}
makefile如下
result: main.c
g++ -o result main.c
clean:
rm main.exe