“你帮我助”物品交换系统开发
“你帮我助”物品交换系统
本项目为上海交通大学CS3331软件工程课程作业。
需求分析
疫情期间,各个小区居民发挥互助精神,进行物品交换,互通有无。
编写一个物品交换软件,该程序允许添加物品的信息,删除物品的信息,显示物品列表,也允许查找物品的信息。
实现方案
使用VS Code,通过C++实现物品交换软件的功能。
PSP数据记录
| 用时 | |
|---|---|
| 分析需求 | 10min |
| 生成设计文档 | 15min |
| 设计复审 | 无 |
| 代码规范 | 10min |
| 具体设计 | 20min |
| 具体编码 | 4h |
| 代码复审及测试 | 1h |
| 撰写报告 | 20min |
| 计算工作量 | 10min |
| 事后总结 | 20min |
项目代码
item_list.h
定义了物品列表类
#ifndef ITEM_H_
#define ITEM_H_
#include <string>
using namespace std;
// Item结构体用于保存物品的相关信息
struct Item {
int m_num; // 物品数量
string m_name; // 物品名字
string m_owner; // 物品主人
string m_tel; // 联系电话
Item() {}
Item(int num, string name, string owner, string tel) :
m_num(num), m_name(name), m_owner(owner), m_tel(tel){}
~Item() {}
};
// 重载输入输出运算符以获得或输出物品信息
istream &operator>>(istream &is, Item &i);
ostream &operator<<(ostream &os, Item &i);
// ItemList为物品列表,采用双链表实现
class ItemList {
public:
ItemList();
~ItemList();
void add(); // 添加物品
void remove(int index); // 根据物品的序号移除物品
void showList(); // 显示所有物品
void search(string name); // 搜索物品
void reset();
private:
// 双链表结点
struct Node
{
Item m_item;
Node *prev, *next;
Node() : next(nullptr) {}
Node(Item &i, Node *p = nullptr, Node *n = nullptr) :
m_item(i), prev(p), next(n) {}
~Node() {}
};
int num_item; // 列表内物品数量
Node *head, *tail; // 起始结点和尾结点
void getList(); // 从外部文件获取列表
void saveList(); // 保存列表到外部文件
};
#endif
list_functions.cpp
物品列表类的方法实现
#include "itemlist.h"
#include <iostream>
#include <iomanip>
#include <fstream>
#include <string>
using namespace std;
// 显示表头
void showHeader()
{
cout << setw(5) << "\n编号";
cout << setw(20) << "物品名称";
cout << setw(10) << "物品数量";
cout << setw(15) << "物品持有人";
cout << setw(15) << "联系电话";
cout << endl;
}
// Item的输入输出重载
istream &operator>>(istream &is, Item &i)
{
cout << "请输入物品名称:";
getline(is, i.m_name);
cout << "请输入物品数量:";
int n = 0;
is >> n;
while (n <= 0)
{
cout << "输入有误,请重新输入:";
is >> n;
}
i.m_num = n;
is.get(); // 吸收换行符
cout << "请输入物品持有人姓名:";
getline(is, i.m_owner);
cout << "请输入物品持有人电话:";
getline(is, i.m_tel);
return is;
}
ostream &operator<<(ostream &os, Item &i)
{
cout << setw(20) << i.m_name;
cout << setw(10) << i.m_num;
cout << setw(15) << i.m_owner;
cout << setw(15) << i.m_tel;
return os;
}
void ItemList::getList()
{
Item get_item;
ifstream fin("listdata.csv");
if (fin)
{
while (!fin.eof())
{
getline(fin, get_item.m_name, ',');
string s_num; // 临时以字符串形式保存数字
if (get_item.m_name == "") break; // 检测是否为空行
getline(fin, s_num, ',');
get_item.m_num = stoi(s_num);
getline(fin, get_item.m_owner, ',');
getline(fin, get_item.m_tel, ',');
getline(fin, s_num); // 文件读取位置换行
Node *temp = new Node(get_item);
temp->prev = tail->prev;
temp->next = tail;
tail->prev->next = temp;
tail->prev = temp;
++num_item;
}
fin.close();
}
}
void ItemList::saveList()
{
Node *temp = head->next;
ofstream fout("listdata.csv");
if (!fout)
{
cout << "保存物品列表失败!" << endl;
return;
}
while (temp != tail)
{
//将链表中的Item类以二进制形式存入外部文件
fout << temp->m_item.m_name << ",";
fout << temp->m_item.m_num << ",";
fout << temp->m_item.m_owner << ",";
fout << temp->m_item.m_tel << ",";
fout << endl;
temp = temp->next;
}
fout.close();
}
// ItemList构造函数
ItemList::ItemList()
{
head = new Node();
tail = new Node();
head->next = tail;
tail->prev = head;
num_item = 0;
getList();
}
// ItemList的析构函数
ItemList::~ItemList()
{
Node *temp;
while (head) {
temp = head;
head = head->next;
delete temp;
}
}
// 向物品列表中添加物品
void ItemList::add()
{
Item add_item;
cin >> add_item;
// 创建新的结点插入双链表尾部
Node *temp = new Node(add_item);
temp->prev = tail->prev;
temp->next = tail;
tail->prev->next = temp;
tail->prev = temp;
cout << "物品" << add_item.m_name << "添加成功!" << endl;
++num_item;
saveList(); // 保存当前的列表到csv文件
}
// 显示物品列表
void ItemList::showList()
{
int index = 1; // 物品的编号
showHeader();
Node *temp = head->next;
while (temp != tail) {
cout << setw(5) << index;
cout << temp->m_item << endl;
temp = temp->next;
++index;
}
cout << "\n共找到" << num_item << "条数据\n\n";
}
// 根据物品的序号移除物品
void ItemList::remove(int index)
{
// 判断是否存在该编号的物品
if (index <= 0 || index > num_item)
{
cout << "编号为" << index << "的物品不存在!" << endl;
return;
}
Node *temp = head;
for (int i = 0; i < index; ++i)
{
temp = temp->next;
}
string temp_name = temp->m_item.m_name; // 被删除物品的名字
temp->next->prev = temp->prev;
temp->prev->next = temp->next;
delete temp;
cout << "成功删除编号为" << index << "的物品" << temp_name << "!" << endl;
--num_item;
saveList();
}
// 搜索物品
void ItemList::search(string name)
{
Node *temp = head->next;
int cnt = 0, index = 1;
bool header = false; // 是否显示标头
while (temp) {
if (temp->m_item.m_name == name)
{
if (!header)
{
header = true;
showHeader();
}
cout << setw(5) << index;
cout << temp->m_item << endl;
++cnt;
}
temp = temp->next;
++index;
}
if (cnt == 0)
{
cout << "未搜索到相关物品" << endl;
}
else
{
cout << "\n\n共搜索到" << cnt << "条结果" << endl;
}
}
// 重置列表
void ItemList::reset()
{
Node *temp = head;
for (int i = 0; i < num_item; ++i) {
temp = temp->next;
temp->next->prev = temp->prev;
temp->prev->next = temp->next;
delete temp;
}
num_item = 0;
saveList();
}
main.cpp
主程序
#include "itemlist.h"
#include <iostream>
#include <string>
#include <cctype>
#include <iomanip>
using namespace std;
void showWelcome();
void showTips();
int main()
{
ItemList list;
string query_name;
char op; // 操作
showWelcome();
while (true)
{
showTips();
op = cin.get();
cin.get(); // 吸收换行符
switch (op)
{
case '1':
list.add();
break;
case '2':
int index;
cout << "输入删除的物品的编号:";
cin >> index;
cin.get(); // 吸收换行符
list.remove(index);
break;
case '3':
list.showList();
break;
case '4':
cout << "请输入你要查询的物品的名字:";
getline(cin, query_name);
list.search(query_name);
break;
case 'r':
while (true)
{
cout << "你确定要重置列表吗(y/n):";
cin >> op;
cin.get();
if (tolower(op) == 'y')
{
list.reset();
break;
}
else if (tolower(op) == 'n')
{
break;
}
}
break;
case 'q':
exit(0);
default:
cout << "没有此指令,请重新输入!";
}
cout << "\n************请输入下一个操作指令************\n";
}
return 0;
}
void showWelcome()
{
cout << setw(20) << "##########################################" << endl;
cout << setw(20) << "#### 欢迎使用”你帮我助“物品交换系统 ####" << endl;
cout << setw(20) << "##########################################" << endl;
}
void showTips()
{
cout << "\n请选择你要使用的功能并输入相应的数字或字母" << endl;
cout << "1.添加物品" << endl;
cout << "2.删除物品" << endl;
cout << "3.查看列表" << endl;
cout << "4.搜索列表" << endl;
cout << "r.重置列表" << endl;
cout << "q.退出程序" << endl;
}
总结
- 使用面向对象的设计方法,把物品列表封装成抽象的类,对不同的功能进行模块化设计,容易维护。
- 对于列表中物品信息的输入输出,对输入运算符
>>和输出运算符<<进行了重载,可以减少代码的重复,增加代码的可读性。 - 使用双链表存储列表中的物品,插入和删除物品的效率高。
项目地址
项目已发布至GitHub

浙公网安备 33010602011771号