【问题标题】:For loops and inputing data?对于循环和输入数据?
【发布时间】:2012-04-11 14:11:40
【问题描述】:

试图弄清楚如何制作一个小库存程序,但我终生无法弄清楚它为什么不起作用。

#include <iostream>
#include <fstream>
#include <string>
using namespace std;

struct record
{
    int item_id;
    string item_type;
    int item_price;
    int num_stock;
    string item_title;
    string item_author;
    int year_published;
};

void read_all_records(record records[]);
const int max_array = 100;
int main()
{
    record records[max_array];
    read_all_records(records);

    cout << records[2].item_author;
    return 0;
}

void read_all_records(record records[])
{
    ifstream invfile;
    invfile.open("inventory.dat"); 
    int slot = 0;
    for (int count = 0; count<max_array; count++);
    {
        invfile >> records[slot].item_id >> records[slot].item_type >> records[slot].item_price >> records[slot].num_stock >> records[slot].item_title >> records[slot].item_author >> records[slot].year_published;
        slot++;
    }
    invfile.close();

}

我正在通过让它打印来自记录作者的第二项来测试它。当我运行它时,它根本不显示作者姓名。 .dat 文件几乎位于项目所在的每个文件夹中(我忘记了它需要在哪个文件夹中),所以它就在那里。 问题不在于该文件不起作用。这是数组没有打印任何东西。 我的 inv 文件基本上是:

123456 书 69.99 16 标题 等等 等等

并在一行上重复不同的书籍/CD等,所有这些都没有空格。应该就在下一个。

【问题讨论】:

    标签: c++ file loops input for-loop


    【解决方案1】:

    您应该检查文件是否已打开。

    invfile.open("inventory.dat"); 
    if (!invfile.is_open())
      throw std::runtime_error("couldn't open inventory file");
    

    您应该检查您的文件读取是否正常工作,并在您到达文件末尾时中断。

    invfile >> records[slot].item_id >> records[slot].item_type ...
    if (invfile.bad())
      throw std::runtime_error("file handling didn't work");
    if (invfile.eof())
      break;
    

    您可能希望同时读取每条记录,因为从这段代码中不清楚 C++ 流应该如何区分每个字段。

    通常您希望使用std::getline,将字段拆分为您分隔它们的位置,然后使用boost::lexical_cast 之类的东西进行类型解析。

    【讨论】:

    • 刚刚编辑并放入 .dat 文件。它基本上是逐行的,没有空格。所以不需要拼接。我签入了,仍然没有任何结果。
    【解决方案2】:

    如果我这样做,我想我的结构会大不相同。

    首先,我将operator&gt;&gt; 重载为record

    std::istream &operator>>(std::istream &is, record &r) { 
        // code about like you had in `read_all_records` to read a single `record`
        // but be sure to return the `stream` when you're done reading from it.
    }
    

    然后我会使用std::vector&lt;record&gt; 而不是数组——它更不容易出错。

    要读取数据,我会使用std::istream_iterators,可能会将它们提供给vector&lt;record&gt; 的构造函数:

    std::ifstream invfile("inventory.dat");
    
    std::vector<record> records((std::istream_iterator<record>(invfile)),
                                 std::istream_iterator<record>());
    

    在它们之间(即,在创建文件之后,但在向量之前)是您插入错误处理的位置,大致按照@Tom Kerr 推荐的顺序——检查is_open()bad()eof() 等,以找出尝试打开文件时出现的问题(如果有的话)。

    【讨论】:

    • 这有点超出我的想象......不太确定在那里做什么。这不适合学校,所以我并不是只需要它来工作,我实际上想了解为什么这不起作用。
    • @Nogg:我应该补充一点:我想我会为我知道存在的文件副本提供完整(绝对)路径。这样可以更好地确保打开文件,而不仅仅是将副本分散到各处并希望它找到其中一个。
    • @Nogg:只需提供文件的完整路径即可。例如。在 Linux 上,它类似于“/usr/me/projects/inventory/inventory.dat”。在 Windows 上,可能更像:“C:\\projects\\inventory\\inventory.dat”。如果在 Windows 上使用反斜杠,则需要将每个反斜杠加倍。虽然它们不经常使用,但如果您愿意,可以在 Windows 上使用普通斜杠。在这种情况下,您不需要像反斜杠那样将它们加倍。
    【解决方案3】:

    添加一点检查:

     if (!invfile.is_open()) {
      cout<<"file open failed";
      exit(1);
     }
    

    这样一来,您就不需要像现在一样将输入文件复制到任何地方;-) 您正在按特定顺序阅读,因此您的输入文件应该具有相同的顺序和所需的输入数量。

    您正在打印结构记录的第三个元素。所以你应该至少有 3 条记录。我看不出你的代码有什么问题。如果你能发布你的示例输入文件会容易得多。

    【讨论】:

    • 不会是 !invfile 吗?据我所知,它会在打开时触发 cout。
    • 没有。如果文件已成功打开,is_open() 返回 true。
    • 对。 is_open 在实际打开时返回 true。因此,if 语句将在打开时打印“文件打开失败”。对吗?
    • 所以在这种情况下文件正在工作但没有输出我需要的文件。
    猜你喜欢
    • 1970-01-01
    • 2014-01-03
    • 1970-01-01
    • 1970-01-01
    • 2023-02-10
    • 2013-07-25
    • 2013-06-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多