1

I wanted to know how I can grab numbers out of a string in C++. I'm getting the string from an input and will be getting multiple lines, but I already have the line reading working. Note: the lines always have an even number of ints

Here's what I'd like the code to look something like:

std::getline(std::cin, line);// line looks something like "10 3 40 45 8 12" int a, b; while(!line.empty() /*line still has ints to extract*/) { a = someMethod(line);//gets first int. So, 10 first loop, 40 second, 8 third b = someMethod(line);//gets second int. So, 3 first loop, 45 second, 12 third myMethod(a,b);//a method from elsewhere in my code. It's here so you know that I need both a and b } 

Anything similar would help. Thank you very much!

5
  • How about std::stringstream? Commented Jun 2, 2014 at 4:07
  • How could I use stringstream for this? I'm only a little familiar with it. Commented Jun 2, 2014 at 4:11
  • @user2670028: You'd construct it from line and then use it in just the same way as you'd extract integers from std::cin. The library is nicely orthogonal this way. However, there are things to watch out for - see How to parse a string to an int in C++. Commented Jun 2, 2014 at 4:14
  • @Simon I think I've come up with a way that will work using this idea, thanks! Commented Jun 2, 2014 at 4:25
  • Did you do any research before asking here. This has so many answers, just search: parse space delimited numbers c++ and google has many many solutions. Commented Jun 2, 2014 at 4:41

4 Answers 4

3

Here is a complete example.

#include <sstream> #include <string> #include <iostream> int main(){ std::string line = "2 4 56 6"; std::stringstream stream(line); int i; while (stream >> i) { std::cout << i << std::endl; } } 

The following works fine also, so reading multiple lines should not be a problem.

#include <sstream> #include <string> #include <iostream> int main(){ std::string line = "2 4 56 6"; std::stringstream stream(line); int i; while (stream >> i) { std::cout << i << std::endl; } line = "32 62 44 6 22 58 34 60 71 86"; stream.clear(); stream.str(line); int a,b; while(stream >> a && stream >> b){ std::cout << a << " " << b << "\n"; } } 
Sign up to request clarification or add additional context in comments.

14 Comments

while(!stream.eof()) is broken - eof isn't set until after a read operation fails - it doesn't promise that the next read will not fail (how could it - it doesn't know what you'll try to read yet). You should use while (stream >> i) directly.
@TonyD, Fair point, fixed.
@merlin2011 thanks, this is a lot like what I've created based on another comment. The only thing missing (which I guess wasn't entirely specified inthe question, sorry) is that I need the stringstream to work for the next line as well. Do I have to create a new stringstream or do you know how to grab the next version of "line"?
@user2670028, You should be able to reuse it by doing stream.clear() followed by stream.str(line).
@merlin2011 I'm core dumping at the end. My Code: while(stream >> a && stream >> b){ cout << a << " " << b << "\n"; myMethod(a,b); } output with line "32 62 44 6 22 58 34 60 71 86": 32 62 44 66 22 58 34 60 Segmentation fault BTW thanks for all your help. I can probably figure this out on my own now but I still got this error.
|
0

Get tokens from string line and use them as you want.

#include <iostream> #include <string> #include <boost/tokenizer.hpp> using namespace std; typedef boost::tokenizer<boost::char_separator<char> > tokenizer; void myMethod(int a, int b) { cout<<a<<" "<<b<<endl; } void getNumber(string line) { boost::char_separator<char> sep(" "); tokenizer tokens(line, sep); string evenStr, oddStr; for(tokenizer::iterator iterToken=tokens.begin(); iterToken != tokens.end(); ++iterToken) { evenStr = *iterToken; ++iterToken; if(iterToken != tokens.end()) { oddStr = *iterToken; myMethod(atoi(evenStr.c_str()), atoi(oddStr.c_str())); } } } int main() { string line("10 3 40 45 8 12"); getNumber(line); return 0; } 

Comments

0

You can do like this:

string line; getline(std::cin, line);// line looks something like "10 3 40 45 8 12" int a, b; vector<string> tokens; istringstream iss(line); copy(istream_iterator<string>(iss), istream_iterator<string>(), back_inserter<vector<string> >(tokens)); stringstream s; for (int i=0;i<tokens.size()/2;i++) { s<< tokens[i]; s>>a; s.clear(); s<<tokens[i+2]; s>>b; s.clear(); myMethod(a,b); } 

2 Comments

strstream has been deprecated since C++98, see en.cppreference.com/w/cpp/io/strstream
@TonyD, thanks for pointing out. used stringstream.
0

There are multiple ways to achieve this. I prefer to use boost.

Example:

#include <iostream> #include <fstream> #include <string> #include <vector> #include <boost/algorithm/string.hpp> #include <boost/lexical_cast.hpp> int main() { std::string line = "10 3 40 45 8 12 9"; //std::getline(std::cin, line);// line looks something like "10 3 40 45 8 12" std::vector<std::string> intNumbers; std::string s; boost::split(intNumbers, line, boost::is_any_of(" "), boost::token_compress_on); unsigned int i=0; while(i < intNumbers.size()) { try{ int a = boost::lexical_cast<int>(intNumbers[i++]); if(i >= intNumbers.size()) { std::cout << "invlaid values" << std::endl; break; } int b = boost::lexical_cast<int>(intNumbers[i++]); std::cout << "value a: " << a << std::endl; std::cout << "value b: " << b << std::endl; std::cout << "my method (multiply) a*b: " << (a*b) << std::endl; } catch(boost::bad_lexical_cast &e) { std::cout << "invlaid values" << std::endl; } } } 

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.