【问题标题】:how to access information in a file? C++如何访问文件中的信息? C++
【发布时间】:2016-02-07 22:22:08
【问题描述】:

我在两件事上遇到了麻烦,首先在我选择 C ​​的 if 语句中,它应该从文件中获取选定的记录并更改其内容,但由于某种原因文件内容不会更改,它不起作用。同样在选项 D 中,我需要它能够读取并添加文件中的所有数量和销售成本,并将它们加在一起然后显示它们。我什至不知道从哪里开始。我知道我需要访问文件中的信息,但只有具有如此所述数据的行,然后将它们加在一起并将它们保存在要显示的变量中,但是我怎样才能只访问文件中具有该数据的行?

 #include <iostream>
    #include <fstream>
    #include <string>
    #include "stdafx.h"
    using namespace std;

    struct Info
    {
        // create inventory items info
        string ItemDescription;
        int Quantity;
        double WholesaleCost;
        double RetailCost;
        string Date;
    };

    int main()
    {
        //make instance of info and a variable for user selection
        Info Item;
        char choice;
        // set up functions
        long byteNum(int);
        void showRec(Info);
        void changeRec(Info);
        //open file
        fstream inventory("inventory.dat", ios::out | ios::in | ios::binary);
        // loop for user selection
        do
        {
            cout << "press 'A' to add files\n";
            cout << "press 'D' to display files\n";
            cout << "press 'C' to Change files\n";
            cout << "press 'G' to Generate a record\n";
            cout << "or press 'Q' to quit\n";
            cin >> choice;
            //if add files get record info put it into struct and save it tofile
            if (choice == 'A' || choice == 'a')
            {

                cout << "enter Item description\n";
                cin >> Item.ItemDescription;
                cout << "enter quantity on hand\n";
                cin >> Item.Quantity;
                cout << "enter whole sale cost\n";
                cin >> Item.WholesaleCost;
                cout << "enter Item retail cost\n";
                cin >> Item.RetailCost;
                cout << "enter date added to inventory\n";
                cin >> Item.Date;
                cout << "data added\n";
                inventory.write(reinterpret_cast<char *>(&Item), sizeof(Item));

            }
            //display record
            else if (choice == 'D' || choice == 'd')
            {
                int recordChoice;
                // get which record user wants
                cout << "enter which record number you want?";
                cin >> recordChoice;
                // display record info
                cout << " here is record " << recordChoice << endl;
                inventory.seekg(byteNum(recordChoice), ios::beg);
                inventory.read(reinterpret_cast<char *>(&Item), sizeof(Item));
                showRec(Item);

            }
            // change record info
            else if (choice == 'C' || choice == 'c')
            {
                int recordChoice;
                //get which record user wants to change
                cout << "enter which record number you want to change?";
                cin >> recordChoice;
                // change struct info and save it over old record in the file
                changeRec(Item);
                inventory.seekp(byteNum(recordChoice), ios::beg);
                inventory.write(reinterpret_cast<char *>(&Item), sizeof(Item));

            }
            else if (choice == 'G' || choice == 'g')
            {


                cout << "D";
            }



        } while (choice != 'Q' || choice != 'q');


        inventory.close();
        return 0;
    }

    long byteNum(int recNum)
    {
        // get record selection number
        return sizeof(Info) * recNum;
    }

    void showRec(Info record)
    {
        // display record info
        cout << record.ItemDescription << endl;
        cout << record.Quantity << endl;
        cout << record.WholesaleCost << endl;
        cout << record.RetailCost << endl;
        cout << record.Date << endl;
    }

    void changeRec(Info record)
    {
        // change record info in struct
        cout << "enter new Item description\n";
        cin >> record.ItemDescription;
        cout << "enter new quantity on hand\n";
        cin >> record.Quantity;
        cout << "enter new whole sale cost\n";
        cin >> record.WholesaleCost;
        cout << "enter new Item retail cost\n";
        cin >> record.RetailCost;
        cout << "enter new date added to inventory\n";
        cin >> record.Date;
        cout << "data added\n";
    }

【问题讨论】:

  • 您不能让std::string 成员被简单地从/序列化到二进制文件中。
  • 请仔细阅读std::tolowerstd::toupper,这样您就可以减少比较次数(或者更好的是,cases 在switch 语句中的数量)。
  • 在互联网上搜索“C++ 序列化技术字符串”。类到文件的输入和输出称为序列化。有很多文章描述了如何处理包含std::stringstd::vector等指针的数据类型。

标签: c++ struct iostream binaryfiles records


【解决方案1】:

你的班级由一堆 std::strings 组成(还有一些其他的东西,但这并不重要)。

std::string 是一个实现类似文本字符串的接口的类。它本身不是字符串。通常,std::string 由指向堆分配缓冲区的指针、字符串的大小以及可能的其他一些元数据组成。

您不必担心这些。您所要做的就是访问std::string 方法,例如substr() 和其他方法,然后您就会得到结果。类本身管理其内部元数据,并对其负责。您调用substr(),该类使用其内部指针查找字符串的请求部分并返回,等等。

inventory.write(reinterpret_cast<char *>(&Item), sizeof(Item));

因此,您最终将Item 结构的二进制内容写入文件。其中包括一堆std::strings。那太棒了。您的文件现在包含一些二进制数据,其中包括一堆包含文本字符串的堆分配缓冲区的原始内存地址。它本身不包含文本字符串。

当您稍后读回它们时,您将得到的只是相同的原始内存地址。这很好,除了现在,它是一个完全不同的进程,并且某个前一段时间终止的进程使用的原始内存地址......不是很有用。当你尝试访问它们时,你的代码就会崩溃,因为所有这些指针现在都是毫无意义的废话。

问自己以下简单的问题:你明白你在上面的write() 调用中写了sizeof(Item) 字节,对吗?而且您知道sizeof(Item) 是一个常量表达式(或者,至少,您的C++ 课程的讲师应该告诉您的第一件事是sizeof 始终是一个常量表达式)。那么,您需要问自己一个问题,无论Item 结构中的一个字符串是包含十个字符还是一万个字符,如何始终写入一些恒定数量的字节是可能的?

不幸的是,这并不像 write() 和 read() 调用那么简单。您需要提出一种文件格式来表示您的 Item 类的内容,并实现不同的方法来将所有字段的内容一一写入文件并读回。

您的问题的 cmets 已经为您提供了一些 Google 食物。使用它。

【讨论】:

  • 好的,我会查找序列化,看看我是否能找到重新格式化我的文件的方法。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-07-07
  • 1970-01-01
相关资源
最近更新 更多