arrays - User input to matrix in C++ -


i have trouble read in input user , convert them matrix calculation. example, input = {1 2 3 / 4 5 6}, program should read in matrix in form of

1 2 3  4 5 6 

which have 3 cols , 2 rows. got far not seem work:

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

so i'm trying break input token , store them matrix using setelement function take number of row, column , variable user want store. wrong code variable of tok doesnt seem change , keep stuck in 0. assuming row , col knows.

thanks help.

although many simple ways exist solve specific problem (and other answer have various suggestions) let me try give more general view of problem of "formatted input".

there 3 kind of problems, here:

  1. at low level youi have string number conversion
  2. at higer level have parse composite format (understanding rows , line separation)
  3. finally have understand size of compound (how many rows , cols?)

this 3 things not independent , last needed know how store elements (how size matrix?)

finally there 4th problem (that spread other other 3): if input "wrong".

these kind of problem typically afforded in 2 opposite ways:

  1. read data come, recognize if format matched, , dynamically grow data structure have contain them or...
  2. read data once (textual form) analyze text figure out how many elements has, isolate "chunks" , conversions.

point 2. requires string manipulations, requires ability know how input long (what happens if 1 of separating spaces new-line? idea got getline fails in cases)

point 1 requires matrix class capable grow read or temporary dynamic structure (like , std container) in yo ucan place read before sending appropriate place.

since don't know how matrix works, let me keep temporary vector , counters store lines.

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

now can read matrix as

input >> readmatrix(matrix); 

you notice @ point there recurring patterns in code: typical in one-pass parses, , patterns can grouped form sub-parsers. if generically -in fact- rewrite boost::spirit.

of course adaption can done depending on how matrix works (has fixed sizes??), or if rows sizes don't match (partial column filling ??)

you can add formatted input operator like

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

so can do

input >> matrix; 

Comments

Popular posts from this blog

ruby on rails - RuntimeError: Circular dependency detected while autoloading constant - ActiveAdmin.register Role -

c++ - OpenMP unpredictable overhead -

javascript - Wordpress slider, not displayed 100% width -