用户在C ++中输入矩阵

时间:2014-12-02 06:46:26

标签: c++ arrays string matrix token

我无法读取用户的输入并将其转换为矩阵进行计算。例如,对于input = {1 2 3 / 4 5 6},程序应该以

的形式在矩阵中读取
1 2 3 
4 5 6

有3列和2行。到目前为止我得到的似乎不起作用:

input.replace(input.begin(), input.end(), '/', ' ');
    stringstream ss(input);
    string token;   
    while (getline(ss, token, ' '))
    {
        for (int i = 0; i < row; i++)
        {
            for (int j = 0; j < col; j++)
            {
                int tok = atoi(token.c_str());
                (*matrix).setElement(i, j, tok);                
            }
        }
    }

所以我要做的是将输入分解为令牌并使用setElement函数将它们存储到矩阵中,该函数接受用户想要存储的行数,列数和变量数。这段代码有什么问题,tok的变量似乎没有改变并一直停留在0。假设知道行和col。

非常感谢您的帮助。

3 个答案:

答案 0 :(得分:1)

虽然有很多简单的方法可以解决具体问题(其他答案有各种好的建议),但我试着对“格式化输入”问题给出一个更一般的看法。

这里存在三种问题:

  1. 在低级别你必须做一个字符串到数字转换
  2. 在更高级别,您必须解析复合格式(理解行和行分隔)
  3. 最后你还必须了解化合物的大小(有多少行和列?)
  4. 这三件事并不是完全独立的,最后需要知道如何存储元素(你如何调整矩阵的大小?)

    最后还有第4个问题(其他3个问题就是其他问题):如果输入“错误”该怎么办。

    这类问题通常以两种相反的方式提供:

    1. 读取数据,识别格式是否匹配,并动态增长必须包含它们的数据结构或...
    2. 按原样读取所有数据(文本形式),然后分析文本以确定它有多少元素,然后隔离“块”并进行转换。
    3. 第2点需要良好的字符串操作,但还需要能够知道输入的长度(如果其中一个分隔空间是一个新行会发生什么?这个想法是通过{{1}得到的所有内容在这些情况下失败)

      第1点需要一个getline类,它能够在您阅读时增长,或者需要一个临时动态结构(如和Matrix容器),您可以将其放入适当的位置,然后再将其发送到相应的的地方。

      由于我不知道你的矩阵是如何工作的,让我保留一个临时向量和计数器来存储行。

      std

      现在您可以将矩阵读作

      #include <vector>
      #include <iostream>
      #include <cassert>
      
      class readmatrix
      {
          std::vector<int> data; //storage
          size_t rows, cols; //the counted rows and columns
          size_t col; //the counting cols in a current row
      
          Matrix& mtx; //refer to the matrix that has to be read
      public:
      
          // just keep the reference to the destination
          readmatrix(Matrix& m) :data(), rows(), cols(), cols(), mtx(m)
          {}
      
          // make this class a istream-->istream functor and let it be usable as a stream 
          // manipulator: input >> readmatrix(yourmatrix) 
          std::istream& operator()(std::istream& s)
          {
              if(s) //if we can read
              {
                  char c=0:
                  s >> c; //trim spaces and get a char.
                  if(c!='{') //not an open brace
                  { s.setstate(s.failbit); return s; } //report the format failure
                  while(s) //loop on rows (will break when the '}' will be found)
                  {
                      col=0;
                      while(s) //loop on cols (will break when the '/' or '}' will be found)
                      {
                          c=0; s >> c;
                          if(c=='/' || c=='}') //row finished?
                          { 
                              if(!cols) cols=col; //got first row length
                              else if(cols != col) //it appears rows have different length
                              { s.setstate(s.failbit); return s; } //report the format failure
                              if(c!='/') s.unget(); //push the char back for later
                              break; //row finished
                          }
                          s.unget(); //pushthe "not /" char back
                          int x; s >> x; //get an integer
                          if(!s) return s; //failed to read an integer!
                          ++col; data.push_back(x); //save the read data
                      }
                      ++rows; //got an entire row
                      c=0; s >> c;
                      if(c == '}') break; //finished the rows
                      else s.unget(); //push back the char: next row begin
                  }
              }
              //now, if read was successful,
              // we can dispatch the data into the final destination
              if(s)
              {        
                  mtx.setsize(rows,cols); // I assume you can set the matrix size this way
                  auto it = data.begin(); //will scan the inner vector
                  for(size_t r=0; r<rows; ++r) for(size_t c=0; c<cols; ++c, ++it)
                      mtx(r,c) = *it; //place the data
                  assert(it == data.end()); //this must be true if counting have gone right
              }
              return s;
          }
      };
      

      此时您会注意到代码中存在某些重复出现的模式:这在单遍解析中很常见,并且这些模式可以分组以形成子解析器。如果你这样做,你实际上会重写input >> readmatrix(matrix);

      当然可以根据矩阵的工作方式(固定大小?)或者行大小不匹配(部分列填充??)来进行一些调整

      您甚至可以添加格式化的输入操作符,如

      boost::spirit

      这样你就可以做到

      std::istream& operator>>(std::istream& s, Matrix& m)
      { return s >> readmatrix(m); }
      

答案 1 :(得分:0)

您正在尝试对输入中读取的每个字符的矩阵的每个单元格进行操作! 你必须为每个单元格取一个char,而不是多个。

可以使用以下函数在标记中拆分字符串。 请不要担心以下代码无法运行,这是由于缺少矩阵类。

尝试以下方法:

#include <iostream>
#include <string>
#include <sstream>
#include <algorithm>
#include <iterator>

using namespace std;

void split(const string& str, char delimiter, vector<string>& result) {
   string::size_type i = 0;
   string::size_type delimOcc = str.find(delimiter);

   while (delimOcc != string::npos) {
       result.push_back(str.substr(i, delimOcc-i));
       i = ++delimOcc;
       delimOcc = str.find(delimiter, delimOcc);

      if (delimOcc == string::npos) {
         result.push_back(str.substr(i, str.length()));
      }
   }
}

int main()
{
    std::string input = "1 2 3 / 4 5 6";

    vector<string> rows;
    split(input, '/', rows);

    for(int i = 0; i < rows.size(); i++) {
        vector<string> cols;
        split(rows[i], ' ', cols);

        for(int j = 0; j < cols.size(); j++) {
            if(cols[j][0] != '\0'){
                int tok = stoi(cols[j]);
                (*matrix).setElement(i, j, tok);   
                cout << tok << " - " << i << " - " << j << endl;
            }
            else {
                if(j == 0) j--;
            }
        }
    }

    return 0;
}

答案 2 :(得分:0)

如果你知道正手矩阵的大小,你实际上不需要getline,你应该用int读取int。 (未经测试的代码)

input.replace(input.begin(), input.end(), '/', '\n');
stringstream ss(input);
for (int i = 0; i < row; i++)
{
    for (int j = 0; j < col; j++)
    {
        int tok;
        ss >> tok;
        (*matrix).setElement(i, j, tok);                
    }
}