【问题标题】:C++ text file into multi-dimensional array problemsC++文本文件转换成多维数组问题
【发布时间】:2014-05-10 09:41:58
【问题描述】:

作为学校项目的一部分,我想将库存 *.txt 文件放入 C++ 中的数组中,并最终在程序的稍后部分返回 *.txt 文件。

文本文件以 10 行开始,代表杂货店商品,并包括代表商品名称、价格和数量的三列。我已经能够从文件中读取,甚至在显示的每一行前面添加数字。现在,我想将文本文件放入一个字符串数组中,以便“员工”用户可以一次更改一个项目,然后我可以将该数组转储回 *.txt 文件中。

下面的代码是我迄今为止一直在尝试的。我可以获得文件中的行数,但似乎无法计算列数或显示的行中的数据。当我运行程序时,在显示行 (10) 和 Cols(0) 之后,我得到了 10 个空行。

*.txt 文件中的列通常用空格分隔。我尝试了一个选项卡,然后尝试:while(getline(invFile, lines, '\t'); 这只是导致控制台显示我猜测的内存地址然后崩溃。

不幸的是,我们在调试程序方面还没有走得太远,而且从教学大纲的角度来看,我认为不会很彻底地涵盖这一点,所以我不知道如何进一步排除故障。在过去的几个小时里,我一直在谷歌上搜索,并且已经到了我真正需要寻求帮助的地步。

该项目涉及的不仅仅是这个组件,但我真的被这部分困住了。我不是要求有人为我做这件事,但如果有人知道我做错了什么并且可以指出我将文本文件放入多维数组的最佳方向,我将不胜感激。

谢谢。

    #include <iostream>
    #include <fstream>
    #include <iomanip>
    #include <string>
    #include <sstream>
    #include <array>


    int row = 0;
    int col = 0;

    using namespace std;

    int main()
    {
        string lines;
        int x;
        string textArray[2][2];
        ifstream invFile;
        invFile.open("inventory.txt");

        if(invFile.fail()){
            cerr << "The file cannot be opened!";
            exit(1);
        }

        cout << "\n" << endl;
        while(invFile.good()) {

            while(getline(invFile, lines)) {
                istringstream streamA(lines);
                col = 0;
                while(streamA >> x) {
                    cout << x;
                    textArray[row][col] = x;
                    col++;
                }
                row++;
            }
        }

        invFile.close();

        cout << "Rows: " << row << endl;
        cout << "Cols: " << col << endl;
        cout << "\n" << endl;

        for(int i=0; i<row; i++){
            for(int j=0; j<col; j++){
                cout << "Line: " << i << textArray[i][j] << ".";
            }
            cout << "\n";
        }

        return(0);
    }
=============================
    inventory.txt:

    Apples 1.25 20
    Oranges 1.75 20
    Kiwi 2.50 15
    Pineapples 5.50 20
    Tomatoes 1.50 20
    Onions 2.00 20
    Corn 1.80 20
    Carrots 2.30 20
    Milk 4.50 20
    Cheese 2.25 20

【问题讨论】:

  • 我可以看到两个问题。第一个是变量x 的类型。它应该是 string,例如,“Oranges”不能解析为数字,并且会导致 while(streamA &gt;&gt; x) 在第一次尝试时失败。第二个问题是textArray的声明。这两个数组边界都不足以存储您拥有的数据。使用textArray[20][3] 应该可以,但您也应该尝试了解原因。
  • 当我看到你的第二句话时,我觉得我的额头要疼好几个小时了!我盯着这个看了好几个小时,左右改变了一切,除了 x 的数据类型。我忘了我是从一个整数列表开始的,然后改为字符串。在之前的测试中,我的数组大小更大。一旦我将它们都移回 10 并将 x 更改为字符串,一切正常。非常感谢!

标签: c++ arrays multidimensional-array text-files getline


【解决方案1】:

有几种方法可以做到这一点。最简单的方法是将类似 3,10 的内容放在文件顶部,然后您就知道三列和 10 行。由于您是在修改后编写的,因此您只需要确保这些数字正确写入即可。

如果你想学习一些更高级的方法,那么在你学习更多之后你的生活会更轻松。

如果你使用向量,使用类似vector&lt; vector&lt;string&gt; &gt; 的东西,你可以读到stringstream,然后拆分读取的行并将其放入向量中

fstream file(...);
string tempString;
vector< vector<string> > list;

// Get a full line
while(getline(file, tempString, '\n'){

    // Create a StringStream and store tempString in it for further manipulation
    stringstream ss;
    ss << tempString;
    vector<string> tempVec;

    // Get each column from this row
    while(getline(ss, tempString, '\t'){
        // Put each column into a vector
        tempVec.push_back(tempString);
    }

    // Put the entire vector into our list vector
    list.push_back(tempVec);
}

第二种方法的好处是双重的。首先,这很容易。我猜你不知道它是如何工作的,但是在你不知道的关键字上进行一些简单的谷歌搜索,你会很快找到。第二个是它允许(理论上)无限的行和不受约束的列。我的意思是一排可以有 20 列,一排可以有 2 列,不会浪费空间。

请注意,在研究之前,您不应该使用我展示的框架代码。如果您至少对这里发生的事情没有大致的了解,那么您以后只会给自己带来麻烦。我不会在这里解释一切,因为其他人已经这样做了。此外,由于您是在学校学习的,因此您最终会得到这些东西,因此您只会取得进步。一个主要的限制是如果您的项目需要数组,在这种情况下,我的第一个解决方案将是最佳选择。

【讨论】:

  • 我们最近介绍了向量,我只是对它们不太满意。我想我会尝试一下,因为这将是一个很好的做法。谢谢。
【解决方案2】:

我建议您创建一个structclass 来保存数据。从每一行文本中,适当地提取字段并将它们提取到您的struct。然后,使用std::vector 保留这些structs 的列表。

#include <iostream>
#include <fstream>
#include <iomanip>
#include <string>
#include <sstream>
#include <array>
#include <vector>
#include <cstdlib>

using namespace std;

struct Row
{
   vector<string> columns;
};

int main()
{
   string line;
   vector<Row> rows;
   ifstream invFile;
   invFile.open("inventory.txt");

   if(invFile.fail()){
       cerr << "The file cannot be opened!";
       exit(1);
   }

   cout << "\n" << endl;
   while(invFile.good()) {

       while(getline(invFile, line)) 
       {
          Row row;
          istringstream streamA(line);
          string col;
          while ( streamA >> col )
          {
             row.columns.push_back(col);
          }
          rows.push_back(row);
       }
   }

   invFile.close();

   cout << "Rows: " << rows.size() << endl;
   cout << "Cols: " << rows[0].columns.size() << endl;
   cout << "\n" << endl;

   for(int i=0; i<rows.size(); i++){
       for(int j=0; j<rows[i].columns.size(); j++){
           cout << "Line: " << i << " " << rows[i].columns[j] << "\n";
       }
       cout << "\n";
   }

   return(0);
}

【讨论】:

  • 我们很快就会了解这些,从我所看到的情况来看,它们应该会更好地工作。不幸的是,我必须坚持我们到目前为止所涵盖的内容。谢谢。
【解决方案3】:

我想建议您在重要步骤中添加一些打印行——我认为这也是一种快速且良好的“调试”方法。这样您就可以轻松找到错误的地方。 例如在您的代码中,似乎没有分配textArray,所以在附近添加一些打印:

while(getline(invFile, lines)) {
                cout <<"lines: " << lines << endl; //test enter here
                istringstream streamA(lines);
                col = 0;
                while(streamA >> x) {
                    cout << "x is" << x; //test if enter here
                    textArray[row][col] = x;
                    col++;
                }
                row++;
            }

通过输出,行没问题,但cout &lt;&lt; "x is" &lt;&lt; x;没有打印出来,这意味着while(streamA &gt;&gt;x)条件为假,为什么?

找到调用的库函数,std::istringstreamx 是 int 类型,但是 col 1 的值是 Applesoperator &lt;&lt; 将返回 NULL,将 Apples 分配给 int 是不合理的,直到现在,找到第1点。如果必须使用intfloat来存储数字,请使用一些转换API,如atoiatof

xint更改为string后,出现分段错误,显然textArray[2][2]不足以存储所有信息。 “超出范围”是分段错误的原因,所以做一个大数组继续测试直到通过。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-07-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多