超市管理系统的二次开发
(1)来源:同学项目
(2)运行环境+运行结果的截图(附伸缩源代码)
运行环境:Visual Studio
运行结果:
主菜单显示:

添加商品功能:

食品类商品保质期特殊属性:

电器类类商品颜色特殊属性:

卖出商品功能:

查询库存功能:

保存数据到文件功能:

从文件加载数据功能:

添加商品异常处理:

卖出商品异常处理:


源代码:
点击查看main代码
#include "Supermarket.h"
#include <iostream>
#include <limits>
// 显示主菜单
void displayMenu() {
std::cout << "\n===== 超市货物管理系统 =====\n";
std::cout << "1. 添加商品\n";
std::cout << "2. 卖出商品\n";
std::cout << "3. 查询库存\n";
std::cout << "4. 保存数据到文件\n";
std::cout << "5. 从文件加载数据\n";
std::cout << "6. 退出系统\n";
std::cout << "请选择操作(1-6): ";
}
int main() {
Supermarket supermarket;
int choice;
const std::string filename = "supermarket_data.csv";
std::cout << "=== 超市货物管理系统 v1.0 ===" << std::endl;
std::cout << "正在初始化系统...\n";
// 尝试从文件加载现有数据
supermarket.LoadFromFile(filename);
do {
displayMenu();
std::cin >> choice;
switch (choice) {
case 1:
supermarket.Add();
break;
case 2:
supermarket.Sale();
break;
case 3:
supermarket.Search();
break;
case 4:
supermarket.SaveToFile(filename);
break;
case 5:
supermarket.LoadFromFile(filename);
break;
case 6:
// 退出前保存数据
supermarket.SaveToFile(filename);
std::cout << "系统已退出。感谢使用!\n";
break;
default:
std::cout << "无效选择,请重新输入!\n";
}
// 清除输入错误状态
if (std::cin.fail()) {
std::cin.clear();
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
}
} while (choice != 6);
return 0;
}
点击查看Food类代码
#pragma once
#include "Goods.h"
// 食品类 - 继承自Goods基类
class Food : public Goods {
public:
std::string expiry_date; // 保质期(食品特有属性)
// 构造函数(带默认参数)
Food(std::string n = "", int q = 0, std::string exp = "");
// 实现基类纯虚函数
void ShowMe() const override;
};
点击查看DailyGoods代码
#pragma once
#include "Goods.h"
// 日常用品类 - 继承自Goods基类
class DailyGoods : public Goods {
public:
// 构造函数(带默认参数)
DailyGoods(std::string n = "", int q = 0);
// 实现基类纯虚函数
void ShowMe() const override;
};
点击查看ElectricalAppliance代码
#pragma once
#include "Goods.h"
// 家电类 - 继承自Goods基类
class ElectricalAppliance : public Goods {
public:
std::string color; // 颜色(家电特有属性)
// 构造函数(带默认参数)
ElectricalAppliance(std::string n = "", int q = 0, std::string c = "");
// 实现基类纯虚函数
void ShowMe() const override;
};
点击查看Goods代码
#pragma once
#include <string>
#include <iostream>
// 商品基类(抽象类)
class Goods {
public:
std::string name; // 商品名称
int quantity; // 商品数量
// 构造函数
Goods(std::string n, int q);
// 纯虚函数 - 显示商品信息
virtual void ShowMe() const = 0;
// 虚析构函数 - 确保派生类正确释放
virtual ~Goods();
};
点击查看Supermarket代码
#pragma once
#include "DailyGoods.h"
#include "Food.h"
#include "ElectricalAppliance.h"
#include <vector>
#include <memory>
#include <string>
// 超市管理系统类
class Supermarket {
private:
// 使用智能指针管理商品对象
std::vector<std::unique_ptr<DailyGoods>> daily_goods; // 日常用品货架
std::vector<std::unique_ptr<Food>> foods; // 食品货架
std::vector<std::unique_ptr<ElectricalAppliance>> appliances; // 家电货架
// 查找商品辅助函数模板
template <typename T>
T* findProduct(std::vector<std::unique_ptr<T>>& shelf, const std::string& name);
public:
// 添加商品
void Add();
// 卖出商品
void Sale();
// 查询商品
void Search();
// 保存数据到文件
void SaveToFile(const std::string& filename);
// 从文件加载数据
void LoadFromFile(const std::string& filename);
};
(3)主要问题列表,针对问题的改善或者重构思路
1.问题:缺乏商品唯一标识——仅靠商品名称查找,同名商品无法区分;不同品牌/规格的同名商品会被混淆
改善思路:查找逻辑改进——保留名称查找的同时添加ID查找
2.问题:缺少价格系统
改善思路:添加价格属性
3.问题:缺少商品编辑功能——无法修改已存在的商品信息
改善思路:超市类中添加编辑商品信息和根据类型处理不同修改逻辑的功能函数
4.缺少库存预警
改善思路:添加库存预警功能并设置预警阈值
(4)新代码
点击查看**问题1**修改代码
// Goods.h 添加商品ID
class Goods {
protected:
static int next_id; // 静态成员,自动生成ID
int id; // 商品唯一ID
std::string name;
int quantity;
public:
Goods(std::string n, int q) : id(next_id++), name(n), quantity(q) {}
int GetId() const { return id; }
};
// Supermarket.cpp 查找逻辑改进
Goods* FindProduct(int id) { // 支持ID查找
// 在三个货架中查找
}
Goods* FindProduct(const std::string& name) { // 保留名称查找
// 返回第一个匹配项或全部匹配
}
点击查看**问题2**代码
// Goods.h 添加价格属性
class Goods {
protected:
double price; // 商品单价
public:
double GetPrice() const { return price; }
double GetTotalValue() const { return price * quantity; } // 库存总价值
};
点击查看**问题3**修改代码
// Supermarket.h
void EditProduct(); // 编辑商品信息
// Supermarket.cpp
void Supermarket::EditProduct() {
std::string name;
std::cout << "输入要编辑的商品名称: ";
std::getline(std::cin, name);
Goods* product = FindProduct(name);
if (!product) {
std::cout << "商品不存在\n";
return;
}
std::cout << "当前信息: ";
product->ShowMe();
std::cout << "选择要修改的项:\n"
<< "1. 名称\n"
<< "2. 数量\n"
<< "3. 价格\n"
<< "4. 特殊属性\n";
// 根据类型处理不同修改逻辑
}
点击查看**问题4**修改代码
// Supermarket.h
void SetLowStockWarning(int threshold); // 设置预警阈值
void CheckLowStock(); // 检查低库存商品
// Supermarket.cpp
void Supermarket::CheckLowStock() {
const int WARNING_THRESHOLD = 10; // 可从配置读取
for (auto& item : daily_goods) {
if (item->quantity < WARNING_THRESHOLD) {
std::cout << "⚠️ 库存不足: " << item->name
<< " 仅剩 " << item->quantity << "个\n";
}
}
// 同样检查其他货架
}
(5)重构的软件的测试截图
添加商品并自动生成ID:

ID唯一性:

查询商品及库存信息:

按ID查询和编辑商品:

触发库存预警检查:

(6)总结
一、开发难点
智能指针:unique_ptr不能直接赋值,要用std::move转移所有权,一开始不理解导致编译报错
文件兼容:添加价格字段后,旧文件无法加载,需要处理新旧两种格式
二、耗时较久的问题
模板链接错误
三、逆向软件工程思考
本次二次开发不是从零开始设计,而是从现有代码出发,分析它为什么这样写,找出问题再改进
例如:发现同名商品问题
1.看原代码:只能按名称查找
2.逆向思考:如果有两个"牙刷"怎么办?
3.改进方案:添加唯一ID
四、思考
1.渐进开发比一次性写完更重要:先保证基础功能能用,再一个个加改进功能,每加一个就测试一次
2.兼容性要考虑:加新功能不能破坏旧数据;文件格式要能读老版本
3.用户体验很重要:编辑功能:不用删了重加;库存预警:主动提醒补货
4.代码可读性:变量命名要清楚;加注释说明逻辑;方便以后维护

浙公网安备 33010602011771号