Alex ander bro 2024-10-24 13:46 采纳率: 0%
浏览 3

商品库存管理系统单链表

我用c++写的商品库存管理系统,当在运行窗口第一步读文件,第二步输出的时候,发现无法输出文件的内容,且文件里面是有内容的。请解决这个问题

#include <iostream>  
#include <iomanip>  
#include <string>  
#include <fstream>  
#include <vector>
#include <sstream>  
using namespace std;

struct product {
    string Id;//商品编号
    string name;//商品名称
    double price;//商品价格
    int amount;//商品数量
    product* next;

    product(string I = "", string n = "", double p = 0.0, int a = 0)
        : Id(I), name(n), price(p), amount(a), next(nullptr) {}
};

class List {
private:
    product* head;
public:
    List() {
        head = new product(); // 创建一个虚拟头结点  
    }
    void insert(int position, string I, string n, double p, int a) {//增加了一个重复性检测的功能
        product* current = head;
        int i;
        if (position < 1) {
            cout << "插入位置必须大于0" << endl;
            return;
        }

        // 重复性检测 product* current = head->next; // 假设 head 是链表的头节点 while (current != nullptr) {  
        if (current->Id == I) {
            cout << "商品ID '" << I << "' 已存在,无法插入重复的商品!" << endl;
            return; // 找到重复,直接返回 }  
            current = current->next; // 移动到下一个节点 }  

            product* p1 = head; // 从头节点开始 int i =0;  
            while (p1 != nullptr && i < position - 1) {
                p1 = p1->next; // 找到插入位置的前一个节点 i++;  
            }

            if (p1 == nullptr) {
                cout << "插入位置异常,超出链表范围" << endl;
            }
            else {
                product* p2 = new product(I, n, p, a); // 创建新节点 p2->next = p1->next; // 新节点的下一个指向当前节点的下一个 p1->next = p2; // 当前节点的下一个指向新节点 cout << "插入成功!" << endl;  
            }
        }
    }
    void delete_node(int position) {//根据某个商品的位置进行删除
        if (head == nullptr || head->next == nullptr) {
            cout << "链表未初始化或没有可删除的节点。" << endl;
            return;
        }
        if (position < 1) {
            cout << "删除位置必须大于 0" << endl;
            return;
        }
        product* p1 = head; // 作为遍历指针  
        product* p2; // p2 用于指向被删除节点  
        int i = 0;

        while (p1 != nullptr && i < position - 1) {
            p1 = p1->next;
            i++;
        }

        if (p1 == nullptr || p1->next == nullptr) {
            cout << "删除位置异常" << endl;
        }
        else {
            p2 = p1->next; // p2 指向要被删除的节点  
            p1->next = p2->next; // 更新 p1 的指针  
            delete p2; // 删除节点  
            cout << "删除成功!" << endl;
        }
    }
    //根据商品编号进行批量删除
    void delete_nodes_by_ids(const vector<string>& ids) {
        product* prev = head;
        if (head == nullptr) {
            cout << "链表未初始化或没有可删除的节点。" << endl;
            return;
        }
        for (const string& id : ids) {
            product* p1 = head; //作为遍历指针 product* p2; // p2 用于指向被删除节点 product* prev = nullptr; // 用于跟踪前一个节点 // 查找包含指定商品编号的节点 while (p1 != nullptr && p1->id != id) {
            prev = p1; // 更新前一个节点 p1 = p1->next; //继续遍历 }

            // 如果找到节点,进行删除 if (p1 != nullptr) {
            if (prev == nullptr) {
                // 要删除的是头节点 head = p1->next; // 更新头节点为下一个节点 } else {
                prev->next = p1->next; // 前一个节点跳过 p1 }
                delete p1; // 删除指向的节点 cout << "删除编号为 "" << id << "" 的商品成功!" << endl;
            }
            else {
                cout << "未找到编号为 "" << id << "" 的商品,删除失败." << endl;
            }
        }
    }
    int search(const string& name) {
        product* p = head->next;
        int i = 0;
        while (p) {
            if (name == p->name) return i;
            i++;
            p = p->next;
        }
        return -1;
    }
    void findProductsInRange(double minPrice, double maxPrice) {
        product* current = head;
        bool found = false;

        while (current) {
            if (current->price >= minPrice && current->price <= maxPrice) {
                std::cout << "Product Name: " << current->name << ", Price: " << current->price << std::endl;
                found = true;
            }
            current = current->next;
        }

        if (!found) {
            std::cout << "No products found in the given price range." << std::endl;
        }
    }
    void Print() {
        product* p = head->next;
        cout << left << setw(10) << "商品编号"
            << "\t" << left << setw(30) << "商品名称"
            << "\t" << left << setw(10) << "商品价格"
            << "\t" << left << setw(20) << "商品数量" << endl;
        while (p) {
            cout << left << setw(10) << p->Id
                << "\t" << left << setw(30) << p->name
                << "\t" << left << setw(10) << p->price
                << "\t" << left << setw(20) << p->amount << endl;
            p = p->next;
        }
    }

    void modify(int position, string I, string n, double p, int a) {
        product* p1 = head->next;
        int i = 0;
        while (i < position - 1 && p1) {
            p1 = p1->next;
            i++;
        }
        if (p1) {
            p1->Id = I;
            p1->name = n;
            p1->price = p;
            p1->amount = a;
            cout << "修改成功!" << endl;
        }
        else {
            cout << "修改位置异常" << endl;
        }
    }

    void clear() {
        product* current = head->next;
        product* next;
        while (current) {
            next = current->next;
            delete current;
            current = next;
        }
        head->next = nullptr; // 清空后的链表  
    }
        void loadFromFile(const string & filename) {
            ifstream infile(filename);
            if (!infile) {
                cout << "无法打开文件 " << filename << endl;
                return;
            }

            string I, n;
            double p;
            int a;
            while (infile >> I >> n >> p >> a) {
                insert(1, I, n, p, a); // 直接插入到链表头部  
            }

            infile.close();
            cout << "从文件加载成功!" << endl;
        }

    void saveToFile(const string& filename) {
        ofstream outfile(filename);
        if (!outfile) {
            cout << "无法打开文件 " << filename << endl;
            return;
        }

        product* p = head->next;
        while (p) {
            outfile << p->Id << " " << p->name << " " << p->price << " " << p->amount << endl;
            p = p->next;
        }

        outfile.close();
        cout << "商品信息已成功保存到文件!" << endl;
    }

    ~List() {
        clear();
        delete head;
    }
};

void showMenu() {
    cout << "\n====== 商品管理系统 ======" << endl;
    cout << "1. 插入" << endl;
    cout << "2. 删除" << endl;
    cout << "3. 查询" << endl;
    cout << "4. 输出" << endl;
    cout << "5. 修改" << endl;
    cout << "6. 读文件" << endl;
    cout << "7. 写文件" << endl;
    cout << "8. 清空书库" << endl;
    cout << "0. 退出" << endl;
    cout << "==========================" << endl;
    cout << "请输入你的选择: ";
}
int main() {
    List productList;
    int choice;
    string name, Id;
    double price, minPrice, maxPrice;
    int amount, position;
    string filename;
    while (true) {
        showMenu();
        cin >> choice;

        switch (choice) {
        case 1: // 插入商品 
            cout << "请输入编号: ";
            cin >> Id;
            cout << "请输入商品名称: ";
            cin >> name;
            cout << "请输入价格: ";
            cin >> price;
            cout << "请输入数量: ";
            cin >> amount;
            cout << "请输入插入位置: ";
            cin >> position;
            productList.insert(position, Id, name, price, amount);
            break;

        case 2: // 删除书籍(增加了一个实现批量删除的功能选择)  
            cout << "1.根据用户位置进行删除" << endl;
            cout << "2.根据商品编号进行批量删除" << endl;
            int choose;
            cout << "请输入选择" << endl;
            cin >> choose;
            switch (choose)
            {
            case 1:
                cout << "请输入删除位置: ";
                cin >> position;
                productList.delete_node(position);
                break;
            case 2:
                int num_ids;
                cout << "请输入需要删除的商品编号的数量: ";
                cin >> num_ids;
                vector<string> ids(num_ids); // 创建一个字符串向量以存储商品编号 // 获取用户输入的商品编号 cout << "请输入商品编号,空格分隔: ";
                for (int i = 0; i < num_ids; ++i) {
                    cin >> ids[i];
                }
                productList.delete_nodes_by_ids(ids);
                break;
            }
        case 3: // 查询商品位置  
            int c;
            cout << "1.根据商品名称进行唯一查询" << endl;
            cout << "2.根据输入的商品的价格范围进行查找" << endl;
            cout << "3.请选择:" << endl;
            cin >> c;
            switch (c)
            {
            case 1:
                cout << "请输入要查询的商品名称: ";
                cin >> name;
                position = productList.search(name);
                if (position != -1) {
                    cout << "商品 '" << name << "' 的位置: " << position << endl;
                }
                else {
                    cout << "未找到该商品: " << name << endl;
                }
                break;
            case2: // 根据输入的商品价格范围进行查找 double minPrice, maxPrice;  
                cout << "请输入最小价格: ";
                cin >> minPrice;
                cout << "请输入最大价格: ";
                cin >> maxPrice;
                productList.findProductsInRange(minPrice, maxPrice);
                break;
            }
        case 4: // 输出商品信息  
            productList.Print();
            break;
        case 5: // 修改书籍信息  
            cout << "请输入要修改商品的位置: ";
            cin >> position;
            cout << "请输入新的商品编号: ";
            cin >> Id;
            cout << "请输入新的商品价格: ";
            cin >> price;
            cout << "请输入新的商品数量: ";
            cin >> amount;
            productList.modify(position, Id, name, price, amount);
            break;

        case 6: // 从文件加载书籍信息  
            cout << "请输入文件名: ";
            cin >> filename;
            productList.loadFromFile(filename);
            break;

        case 7: // 将书籍信息保存到文件  
            cout << "请输入文件名: ";
            cin >> filename;
            productList.saveToFile(filename);
            break;
        case 8://清空商品库中的信息
            productList.clear();
            cout << "清空商品库成功!" << endl;
            break;
        case 0: // 退出  
            cout << "退出程序..." << endl;
            return 0;
        default:
            cout << "无效的选择,请重新输入." << endl;
        }
    }
    return 0;
}

  • 写回答

1条回答 默认 最新

  • 越重天 新星创作者: Java技术领域 2024-10-24 16:12
    关注

    本答案参考 多次询问 ChatGPT-3.5 后选择的最佳回答,若是满意,还请采纳,谢谢

    1. 问题分析
      • 在程序中,读文件函数loadFromFile看起来是将文件中的数据逐行读取并插入到链表中。然而,输出函数Print无法正确显示文件内容。可能的原因如下:
        • 数据插入问题:在loadFromFile函数中,数据插入到链表的方式可能存在问题。虽然代码中是将数据插入到链表头部(insert(1, I, n, p, a);),但这可能导致链表顺序与预期不符或者某些数据被覆盖。
        • 文件读取格式问题:如果文件中的数据格式与程序中while (infile >> I >> n >> p >> a)期望的格式不完全一致,可能导致数据读取错误。例如,文件中存在多余的空格或者格式不规范的行。
        • 链表结构损坏:在插入数据到链表的过程中,可能存在指针操作错误,导致链表结构被破坏,从而影响输出。
    2. 解决方案
      • 修改数据插入方式
        • loadFromFile函数中,可以考虑将数据按照顺序插入到链表末尾,而不是总是插入到头部。修改insert函数以支持在链表末尾插入数据。
        • 示例修改后的insert函数(用于在末尾插入):
          void insert(string I, string n, double p, int a) {
          product* new_product = new product(I, n, p, a);
          product* current = head;
          while (current->next!= nullptr) {
           current = current->next;
          }
          current->next = new_product;
          cout << "插入成功!" << endl;
          }
          
        • 然后修改loadFromFile函数:
          void loadFromFile(const string& filename) {
          ifstream infile(filename);
          if (!infile) {
           cout << "无法打开文件 " << filename << endl;
           return;
          }
          string I, n;
          double p;
          int a;
          while (infile >> I >> n >> p >> a) {
           insert(I, n, p, a);
          }
          infile.close();
          cout << "从文件加载成功!" << endl;
          }
          
      • 检查文件读取格式
        • 确保文件中的数据格式与程序中while (infile >> I >> n >> p >> a)期望的格式严格一致。例如,文件中的每一行应该是商品编号 商品名称 商品价格 商品数量这样的格式,中间用单个空格分隔,并且没有多余的字符。
      • 检查链表结构完整性
        • loadFromFile函数中添加一些调试输出,例如在每次插入数据后输出链表的部分信息,以检查链表结构是否正确构建。
        • 例如,可以在insert函数(无论是原来的插入函数还是修改后的)中添加如下调试代码:
          void insert(string I, string n, double p, int a) {
          product* new_product = new product(I, n, p, a);
          product* current = head;
          while (current->next!= nullptr) {
           current = current->next;
          }
          current->next = new_product;
          cout << "插入成功! 当前链表中的商品编号: ";
          current = head->next;
          while (current!= nullptr) {
           cout << current->Id << " ";
           current = current->next;
          }
          cout << endl;
          }
          
        • 这将有助于在加载文件数据时检查链表结构是否按照预期构建。
    评论

报告相同问题?

问题事件

  • 创建了问题 10月24日