C语言课程设计:销售管理系统
项目概述
本项目旨在使用C语言开发一个基于文本界面的销售管理系统,该系统将模拟一个简单的商品销售流程,包括商品信息管理、销售记录管理、数据统计与查询等功能,系统将采用文件存储方式来持久化数据,确保程序关闭后数据不丢失。

(图片来源网络,侵删)
开发目标:
- 巩固和运用C语言的核心知识,如结构体、数组、文件操作、指针、函数等。
- 学习模块化程序设计思想,将复杂功能分解为独立的函数模块。
- 掌握基本的用户界面设计,提供清晰、友好的交互体验。
- 理解数据持久化的概念,并实现文件读写操作。
功能需求分析
系统应具备以下核心功能模块:
1. 主菜单 系统启动后,首先显示一个主菜单,列出所有可用的功能选项,并等待用户输入选择。
2. 商品信息管理

(图片来源网络,侵删)
- 添加商品: 输入商品ID、名称、单价、库存数量等信息,并将新商品信息保存到商品文件中。
- 修改商品: 根据商品ID,修改商品的名称、单价或库存数量。
- 删除商品: 根据商品ID,从商品文件中删除指定商品。
- 查询商品:
- 按ID查询: 输入商品ID,显示该商品的详细信息。
- 按名称查询: 输入商品名称(或部分名称),模糊匹配并显示所有符合条件的商品。
- 显示所有商品: 以表格形式列出系统中所有商品的详细信息。
3. 销售管理
- 创建销售单:
- 输入顾客姓名。
- 逐项添加购买的商品(输入商品ID和购买数量)。
- 系统自动计算单项金额、总金额。
- 在生成销售单时,自动扣减对应商品的库存数量。
- 将销售单信息(包括销售单号、日期、顾客、商品明细、总金额)保存到销售记录文件中。
- 查询销售记录:
- 按日期查询: 输入日期范围,查询该时间段内的所有销售记录。
- 按顾客查询: 输入顾客姓名,查询该顾客的所有购买记录。
- 按销售单号查询: 输入销售单号,查询特定销售单的详细信息。
4. 统计与报表
- 日销售统计: 输入一个日期,显示当天的总销售额、销售订单数、销售商品种类数。
- 商品销售排行: 统计指定时间段内所有商品的销售总数量或总销售额,并按从高到低的顺序进行排行。
- 利润分析(可选高级功能): 如果添加了“成本价”字段,可以计算单次销售或指定时间段的利润。
5. 数据文件
- 商品文件 (
products.dat): 存储所有商品信息。 - 销售记录文件 (
sales.dat): 存储所有销售订单信息。
系统设计
1. 数据结构设计

(图片来源网络,侵删)
为了管理商品和销售记录,我们需要定义相应的结构体。
// 商品结构体
typedef struct {
int id; // 商品ID
char name[50]; // 商品名称
float price; // 单价
int stock; // 库存数量
} Product;
// 销售单明细结构体(单张销售单中的某一项商品)
typedef struct {
int product_id; // 商品ID
char product_name[50]; // 商品名称(为了查询方便,冗余存储)
int quantity; // 购买数量
float subtotal; // 小计金额
} SaleItem;
// 销售单主结构体
typedef struct {
char sale_id[20]; // 销售单号 (如: 20251027001)
char date[11]; // 日期 (格式: YYYY-MM-DD)
char customer[50]; // 顾客姓名
SaleItem items[50]; // 销售明细,最多50种商品
int item_count; // 实际商品种类数
float total_amount; // 总金额
} SaleRecord;
2. 模块化设计
将程序划分为多个源文件(.c)和头文件(.h),便于管理和维护。
main.c: 程序入口,包含主菜单循环和调用其他模块的函数。product.c/product.h: 商品管理模块,包含所有商品相关的函数(增、删、改、查、显示)。sale.c/sale.h: 销售管理模块,包含创建销售单、查询销售记录的函数。report.c/report.h: 统计报表模块,包含各种统计和分析功能的函数。utils.c/utils.h: 工具模块,包含通用的辅助函数,如清屏、获取输入、日期生成等。
3. 文件存储设计
products.dat: 使用二进制文件格式存储Product结构体数组,二进制文件读写速度快,格式紧凑。sales.dat: 使用二进制文件格式存储SaleRecord结构体数组。
核心代码实现示例
下面给出一些关键模块的代码片段,以帮助你理解实现思路。
1. 主菜单 (main.c)
#include <stdio.h>
#include <stdlib.h>
#include "product.h"
#include "sale.h"
#include "report.h"
void showMenu() {
printf("\n=============== 销售管理系统 ===============\n");
printf(" 1. 商品管理\n");
printf(" 2. 销售管理\n");
printf(" 3. 统计报表\n");
printf(" 0. 退出系统\n");
printf("==========================================\n");
printf("请输入您的选择: ");
}
int main() {
int choice;
while (1) {
showMenu();
scanf("%d", &choice);
switch (choice) {
case 1:
productMenu(); // 调用商品管理子菜单
break;
case 2:
saleMenu(); // 调用销售管理子菜单
break;
case 3:
reportMenu(); // 调用统计报表子菜单
break;
case 0:
printf("感谢使用,再见!\n");
exit(0);
default:
printf("无效的输入,请重新选择!\n");
break;
}
}
return 0;
}
2. 商品管理模块 (product.c)
#include <stdio.h>
#include <string.h>
#include "product.h"
// 函数声明
void addProduct();
void modifyProduct();
void deleteProduct();
void queryProduct();
void displayAllProducts();
void productMenu() {
int choice;
while (1) {
printf("\n--- 商品管理 ---\n");
printf("1. 添加商品\n");
printf("2. 修改商品\n");
printf("3. 删除商品\n");
printf("4. 查询商品\n");
printf("5. 显示所有商品\n");
printf("0. 返回主菜单\n");
printf("请选择: ");
scanf("%d", &choice);
switch (choice) {
case 1: addProduct(); break;
case 2: modifyProduct(); break;
case 3: deleteProduct(); break;
case 4: queryProduct(); break;
case 5: displayAllProducts(); break;
case 0: return;
default: printf("无效选择!\n");
}
}
}
// 示例:添加商品函数
void addProduct() {
Product p;
printf("请输入商品ID: ");
scanf("%d", &p.id);
printf("请输入商品名称: ");
scanf("%s", p.name);
printf("请输入商品单价: ");
scanf("%f", &p.price);
printf("请输入库存数量: ");
scanf("%d", &p.stock);
// 将商品信息写入文件 (此处简化,实际应先读取已有数据,追加新数据)
FILE *fp = fopen("products.dat", "ab"); // "ab" 表示二进制追加模式
if (fp == NULL) {
printf("无法打开商品文件!\n");
return;
}
fwrite(&p, sizeof(Product), 1, fp);
fclose(fp);
printf("商品添加成功!\n");
}
3. 销售管理模块 (sale.c)
#include <stdio.h>
#include <time.h>
#include "sale.h"
#include "product.h"
// 示例:创建销售单函数
void createSale() {
SaleRecord sale;
// ... 初始化销售单信息 (如生成单号、日期) ...
printf("请输入顾客姓名: ");
scanf("%s", sale.customer);
sale.item_count = 0;
sale.total_amount = 0.0;
char choice;
do {
if (sale.item_count >= 50) {
printf("已达到单次购买商品种类上限!\n");
break;
}
SaleItem item;
printf("请输入要购买的商品ID: ");
scanf("%d", &item.product_id);
// 从商品文件中查找商品,并检查库存
Product p;
int found = 0;
FILE *fp = fopen("products.dat", "rb");
if (fp) {
while (fread(&p, sizeof(Product), 1, fp)) {
if (p.id == item.product_id) {
found = 1;
break;
}
}
fclose(fp);
}
if (!found) {
printf("未找到该商品!\n");
continue;
}
printf("请输入购买数量: ");
scanf("%d", &item.quantity);
if (item.quantity > p.stock) {
printf("库存不足!当前库存: %d\n", p.stock);
continue;
}
// 计算小计并更新库存
item.subtotal = p.price * item.quantity;
strcpy(item.product_name, p.name);
sale.items[sale.item_count++] = item;
sale.total_amount += item.subtotal;
// 更新商品文件中的库存
// ... (这部分逻辑需要实现,先读取所有商品,修改对应库存,再写回文件) ...
printf("已添加: %s x %d, 小计: %.2f\n", p.name, item.quantity, item.subtotal);
printf("是否继续添加商品? (y/n): ");
scanf(" %c", &choice); // 注意空格,用于吸收回车
} while (choice == 'y' || choice == 'Y');
// 将销售单保存到销售记录文件
FILE *sfp = fopen("sales.dat", "ab");
if (sfp == NULL) {
printf("无法打开销售记录文件!\n");
return;
}
fwrite(&sale, sizeof(SaleRecord), 1, sfp);
fclose(sfp);
printf("销售单创建成功!总金额: %.2f\n", sale.total_amount);
}
扩展与优化建议
如果觉得基本功能已经完成,可以尝试以下扩展来提升项目难度和完整性:
- 使用链表代替数组:在内存中使用链表来管理商品和销售记录,这样可以动态处理数据,无需预先设定大小限制(如
SaleItem items[50])。 - 账户与权限管理:增加管理员和普通用户两种角色,管理员拥有所有权限,普通用户只能进行销售操作。
- 密码保护:为管理员账户设置密码。
- 数据备份与恢复:增加将数据文件备份到另一个位置,以及从备份文件恢复数据的功能。
- 更友好的UI:使用颜色、制表符等方式美化界面,使其更美观。
- 错误处理增强:对所有文件操作(
fopen,fread,fwrite)的返回值进行检查,并提供更健壮的错误提示。 - 排序功能:在显示商品或销售记录时,支持按不同字段(如ID、价格、日期)进行排序。
开发步骤建议
- 搭建框架:创建所有
.c和.h文件,并在main.c中编写主菜单循环。 - 实现数据结构:定义好
Product和SaleRecord等结构体。 - 文件操作先行:先编写
products.dat和sales.dat的读取和写入函数,这是整个系统的基础。 - 模块化开发:从商品管理模块开始,逐个实现函数,每完成一个函数,就进行测试。
- 集成与测试:将所有模块集成到
main.c中,进行整体功能测试,注意模块间的数据传递。 - 文档编写:在代码中添加必要的注释,并撰写课程设计报告,说明设计思路、实现过程和功能演示。
这个设计方案为你提供了一个清晰的路线图,祝你课程设计顺利!
