“你帮我助”物品交换系统开发

“你帮我助”物品交换系统

本项目为上海交通大学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;
}

总结

  1. 使用面向对象的设计方法,把物品列表封装成抽象的类,对不同的功能进行模块化设计,容易维护。
  2. 对于列表中物品信息的输入输出,对输入运算符>>和输出运算符<<进行了重载,可以减少代码的重复,增加代码的可读性。
  3. 使用双链表存储列表中的物品,插入和删除物品的效率高。

项目地址

项目已发布至GitHub

posted @ 2022-10-01 21:35  pseudoChemist  阅读(82)  评论(0)    收藏  举报