Parsing only numbers from istream in C ++

I have a set of input files that look like this:

(8,7,15) (0,0,1) (0,3,2) (0,6,3) (1,0,4) (1,1,5) 

I need to write a function that analyzes these inputs one number at a time, so I need to be able to split the input by numbers, for example: 8, then 7, then 15, then 0, another 0 and so on.

The only way I've been thinking so far is to use istream.get (), which returns the following ASCII character code, which I can convert back to its character format by translating it to char. Then I would check if the character was a number or not (so the brackets are ignored), but this way any double (or triple) digits of digits are read only one digit at a time.

What would be the best way to achieve this?

By the way, I have to use istream. This is part of the specification that I am not allowed to change

thanks

+6
source share
5 answers

Here is some code, you can adapt to meet your specific needs.

 for (;;) { int ch = in.get(); if (ch == EOF) break; if (isdigit(ch)) { int val = ch - '0'; for (;;) { ch = in.get(); if (!isdigit(ch)) break; val *= 10; val += ch - '0'; } // do something with val } } 

This is unverified code.

+4
source

This is one of the solutions:

 struct integer_only: std::ctype<char> { integer_only(): std::ctype<char>(get_table()) {} static std::ctype_base::mask const* get_table() { static std::vector<std::ctype_base::mask> rc(std::ctype<char>::table_size,std::ctype_base::space); std::fill(&rc['0'], &rc['9'+1], std::ctype_base::digit); return &rc[0]; } }; int main() { std::cin.imbue(std::locale(std::locale(), new integer_only())); std::istream_iterator<int> begin(std::cin); std::istream_iterator<int> end; std::vector<int> vints(begin, end); std::copy(vints.begin(), vints.end(), std::ostream_iterator<int>(std::cout, "\n")); return 0; } 

Input:

 (8,7,15) (0,0,1) (0,3,2) (0,6,3) (1,0,4) (1,1,5) 

Conclusion:

 8 7 15 0 0 1 0 3 2 0 6 3 1 0 4 1 1 5 

Online demo: http://ideone.com/Lwx9y

In the above example, you should replace std::cin file stream after successfully opening the file, since:

  std::ifstream file("file.txt"); file.imbue(std::locale(std::locale(), new integer_only())); std::istream_iterator<int> begin(file); std::istream_iterator<int> end; std::vector<int> vints(begin, end); //container of integers! 

Here vints is a vector that contains all integers. You want to work with vints to do something useful. Alternatively, you can use it where int* is expected as:

 void f(int *integers, size_t count) {} f(&vints[0], vints.size()); //call a function which expects `int*`. 

A similar trick can be applied when reading only words from a file. Here is an example:

+7
source

try to read the number. if this fails, clear the error state and try to read char (and ignore it). repeat these two steps until the char is read, in which case you are in EOF or true failure.

it can be optimized by recognizing ")", and then until it is ('.

but I don’t think it is worth it.

greetings and hth.,

+2
source

Another solution:

 #include <string> #include <ostream> #include <fstream> #include <iostream> struct triple { long a; long b; long c; }; std::ostream& operator << (std::ostream& os, const triple& value) { return os << value.a << "/" << value.b << "/" << value.c; } int main() { std::ifstream stream("Test.txt"); if (!stream) { std::cout << "could not open the file" << std::endl; } std::string dummy; triple value; while (std::getline(stream, dummy, '(') >> value.a && std::getline(stream, dummy, ',') >> value.b && std::getline(stream, dummy, ',') >> value.c) { std::cout << value << std::endl; } } 
+2
source
 int getFirstPos(const string& str) { int pos=0,PosHit=0; bool bfind=false; if((PosHit=str.find(','))!=string::npos){ if(!bfind) pos=PosHit; pos=pos>PosHit?PosHit:pos; bfind=true; } if((PosHit=str.find('('))!=string::npos){ if(!bfind) pos=PosHit; pos=pos>PosHit?PosHit:pos; bfind=true; } if((PosHit=str.find(')'))!=string::npos){ if(!bfind) pos=PosHit; pos=pos>PosHit?PosHit:pos; bfind=true; } return bfind?pos:string::npos; 

}

 void main() { ifstream ifile("C:\\iStream.txt"); string strLine; vector<double> vecValue; //store the datas while(getline(ifile,strLine)){ if(strLine.size()==0) continue; int iPos=0; while((iPos=getFirstPos(strLine))!=string::npos) strLine[iPos]=' '; istringstream iStream(strLine); double dValue=0; while(iStream>>dValue) vecValue.push_back(dValue); } //output the result! vector<double>::iterator it; for (it=vecValue.begin(); it!=vecValue.end() ; ++it){ cout<<setprecision(3)<<*it<<endl; } } 
+1
source

Source: https://habr.com/ru/post/895391/


All Articles