将C ++文本文件转换为多维数组问题

时间:2014-03-31 06:39:08

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

作为学校项目的一部分,我希望将库存* .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

3 个答案:

答案 0 :(得分:3)

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

#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);
}

答案 1 :(得分:1)

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

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

如果你使用了一个向量,使用类似vector< vector<string> >的东西,你可以只读到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 :(得分:1)

我建议您在重要步骤中添加一些打印行 - 我认为这也是一种快速且良好的“调试”方法。这样你就可以轻松找到错误的地方。 例如,在您的代码中,似乎未分配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 << "x is" << x;,这意味着while(streamA >>x)条件为假,为什么?

去查找名为std::istringstream x的库函数是int类型但是col 1值是Applesoperator <<将返回NULL,这是不合理的{{1}到Apples,到现在为止,找到了第1点。如果必须使用intint来存储数字,请使用某些转化API,例如float,{{} 1}}。

atoi更改atofx后,得到了细分,显然textArray [2] [2]不足以存储所有信息。 “超出范围”是分段错误的原因,因此要使大数组继续测试直到通过。