如何在C ++中将空格和换行符分隔的整数读入二维数组?

时间:2012-03-05 17:19:41

标签: c++

我有一个.txt文件的数字(在这种情况下都小于100)用空格分隔,用新行分隔的行。像这样:

 41 53 07 91 44
 52 17 13 03 21

我想将这些数字读成2d数组,与它们看起来完全一样,以便空格分隔数组的列,新行分隔行。

我可以让它以字符串形式读取行,但后来我无法分离出单个数字,并将其作为整数处理。

5 个答案:

答案 0 :(得分:17)

试试这个:

#include <vector>
#include <string>
#include <fstream>
#include <sstream>
#include <iostream>

int main()
{
    // The result of the read is placed in here
    // In C++, we use a vector like an array but vectors can dynamically grow
    // as required when we get more data.
    std::vector<std::vector<int> >     data;

    // Replace 'Plop' with your file name.
    std::ifstream          file("Plop");

    std::string   line;
    // Read one line at a time into the variable line:
    while(std::getline(file, line))
    {
        std::vector<int>   lineData;
        std::stringstream  lineStream(line);

        int value;
        // Read an integer at a time from the line
        while(lineStream >> value)
        {
            // Add the integers from a line to a 1D array (vector)
            lineData.push_back(value);
        }
        // When all the integers have been read, add the 1D array
        // into a 2D array (as one line in the 2D array)
        data.push_back(lineData);
    }
}

答案 1 :(得分:1)

好的,“完全按照它们出现”的要求意味着你需要一个参差不齐的数组,以防不同数量的列出现在不同的行中。我会用std::vector< std::vector<long> >。每个包含的向量对应一行。

因此,每次阅读一行文本时,都要创建一个新的空矢量。

在您阅读的行上反复调用strtol,使用push_back将其收集到矢量中。当输出指针与输入指针相同时(这表示失败,可能是因为你到达了行的末尾),push_back整个向量并开始下一行。

这样的事情:

std::vector< std::vector<long> > all_data;

std::string text_row;

while(getline(fin, text_row)) {
    all_data.push_back();
    std::vector<long>& this_row = *all_data.rend();

    const char* p1 = text_row.c_str();
    const char* p2;
    while (1) {
         long num = strtol(p2 = p1, &p1, 0);
         if (p1 == p2) break;
         this_row.push_back(num);
    }

    /* to ignore blank lines, add this code
    if (this_row.empty()) all_data.pop_back();
     */
}

答案 2 :(得分:1)

以下代码显示了如何解决您的问题。它还显示了打开文件时如何使用RAII。这是获取资源时的良好做法。通过获取构造函数中的资源并在析构函数中释放它,如果抛出异常,则可以防止资源泄漏。这被认为是C ++世界的好习惯。

#include <fstream>
#include <vector>

struct FileHandle
{
  std::ifstream file_;
  FileHandle(std::string file_name)
  {
    file_.open(file_name);
  }
  ~FileHandle()
  {
    file_.close();
  }
};

bool next_char_is_end_of_line(std::ifstream &file)
{
  bool found = false;
  char c;
  file.get(c);
  if(c == '\n')
    found = true;
  file.unget();
  return found;
}

int main()
{
  FileHandle fh("c:\\your_file.txt");
  std::vector<std::vector<int> > v;
  std::vector<int> current_line;
  int x;
  while(fh.file_ >> x)
  {
    current_line.push_back(x);
    if(next_char_is_end_of_line(fh.file_))
    {
      v.push_back(current_line);
      current_line.clear();
    }
  }
  //Then just access each std::vector<std::vector<int>> 
  //v[0].size(); ...
  return 0;
}

此代码通过将每行上的所有数字放入单独的向量中来为您提供“锯齿状”向量。然后将该载体添加到主载体中。因此“向量”中的每一行可以具有不同的长度。我想你明白了......

祝你好运!

答案 3 :(得分:0)

尝试stringstream

答案 4 :(得分:0)

实际上有两个问题,在这里:

  1. 如何识别输入和......
  2. 如何在内存中表示它。
  3. 你谈到“二维数组”:这是一个要求还是一个假设?是2x5尺寸要求还是只是样品?

    您谈到了文件布局。这是强制性的,还是不是?您是否应该承认(和检查)最终会误导更多数字或错位?如果第一行有6个数字,第二行有4个数字,你需要做什么?

    一个非常简单的解决方案是使用2x5阵列并用保护循环填充它:

    #include <iostream>
    #include <fstream>
    #include <iomanip>
    #include <stdexcept>
    
    const int ROWS=2;
    const int COLS=5;
    
    int main(int argc, char** argv)
    {
        int m[ROWS][COLS];
        try
        {
            std::ifstream s(argv[1]);
            if(!s) throw std::runtime_error("cannot open file");
            for(int r=0; r<ROWS; ++r)
                for(int c=0; c<COLS; ++c)
                   if(!(s >>m[r][c])
                       throw std::runtime_error("insufficient or bad input");
        }
        catch(const std::exception& e)
        {
            std::cout << "Reading error: " << e.what() << std::endl;
            return -1;
        }
    
        std::cout << "read matrix is \n";
        for(int r=0; r<ROWS; ++r)
        {
            for(int c=0; c<COLS; ++c)
                std::cout << std::setw(8) << m[r][c];
            std::cout << '\n';
        }
        std::cout << std::endl;
        return 0;
    }
    

    这将读取由“空白”分隔的10个数字,无论分布和对齐如何。 (这是2x5是一个结论。)

    另一方面,您可能需要检测自己矩阵的宽度:文件可以包含任意数量的行,每个行的长度都是多少。

    在这种情况下,您需要一个“灵活的结构”,您需要识别线条中的线条和元素。

    #include <iostream>
    #include <fstream>
    #include <string>
    #include <vector>
    #include <sstream>
    #include <iomanip>
    #include <stdexcept>
    #include <utility>
    
    int main(int argc, char** argv)
    {
        std::vector<std::vector<int> > m;
        try
        {
            std::ifstream fs(argv[1]);
            if(!fs) throw std::runtime_error("cannot open input file");
            while(fs)
            {
                std::string line;
                std::getline(fs,line);
                std::vector<int> row;
                std::stringstream ss(line);
                int x;
                while(ss >> x)
                   row.push_back(x); 
                if(!row.empty())
                    m.emplace_back(std::move(row));
            }
        }
        catch(const std::exception& e)
        {
            std::cout << "Reading error: " << e.what() << std::endl;
            return -1;
        }
    
        std::cout << "read lines: \n";
        for(auto i=m.begin(); i!=m.end(); ++i)
        {
            for(auto j=i->begin(); j!=i->end(); ++j)
                std::cout << std::setw(8) << *j;
            std::cout << '\n';
        }
        std::cout << std::endl;
    
        return 0;
    }