I have a string as follows
640x480x32
I want to grab each of the three values separately, so I can put them into a int variable.
I am not sure what std lib can do this for me?
Thanks!
I have a string as follows
640x480x32
I want to grab each of the three values separately, so I can put them into a int variable.
I am not sure what std lib can do this for me?
Thanks!
You can use sscanf from stdio. It's like scanf, except it's used on a char* instead of stdin.
sscanf("640x480x32", "%dx%dx%d", &num1, &num2, &num3);
You can also write your own function to parse it.
But I have a feeling that it is possible to parse it with just string stream and a few << operators.
Yeah, if you already have the "640x480x32" in a string, you will have to perform tokenization in order to split it up into "Tokens". After that you can extract them as integers. Here is some code to do that:
#include <sstream>
#include <string>
#include <iostream>
#include <vector>
using namespace std;
int main()
{
string u_numbers = "640x480x32"; //unformatted numbers
string f_numbers; //formatted numbers
vector <int> numbers; //final numbers in integer form
stringstream ss;
for(int i = 0; i < u_numbers.size(); i++)
{
if(u_numbers.at(i) == 'x') //check if next character is the delimiter
{
ss.put(' ');
}
else
{
ss.put(u_numbers.at(i)); //Output the unformatted string to stringstream
}
}
std::getline(ss, f_numbers); //Get all the data we just put into the stream and put it into another string
std::istringstream iss(f_numbers); //create an integer string stream, fill the stream with the string of formatted numbers
int n;
while (iss >> n)
{
numbers.push_back(n); //pull all the data from the iss and store it as integers in our vector
}
for (int i = 0; i < 3; i++) //a little test to see if it works
{
cout << numbers[i] << ' ';
}
return 0;
}
If you can rely on your input being formatted like that, just dump it in a stringstream and read it back.
const string res = "640x480x32";
int height, width, depth;
char delimiter;
stringstream stream(res);
stream >> height >> delimiter >> width >> delimiter >> depth;
You could use getline and define 'x' as a delimiter, but then you get each number as a string and still need to convert to int.
You could use .ignore(1) instead of the dummy character, but it will look horrible to read.
#include <regex>
#include <boost/lexical_cast.hpp>
std::cmatch matches;
std::regex regExp("\\s{0,}([0-9]+)\\s{0,}x([0-9]+)\\s{0,}x\\s{0,}([0-9]+)\\s{0,}", std::regex_constants::icase);
if (std::regex_match("100X200 x 300", matches, regExp)) {
unsigned int width = boost::lexical_cast<unsigned int>(matches[1].str());
unsigned int height = boost::lexical_cast<unsigned int>(matches[2].str());
unsigned int depth = boost::lexical_cast<unsigned int>(matches[3].str());
}
struct ScreenResolution {
int width, height, depth;
};
istream& operator >> ( istream& stream, ScreenResolution& r ) {
ScreenResolution temp;
array<char,2> delim;
auto pos = stream.tellg();
if ( (stream >> temp.width >> delim[0] >> temp.height >> delim[1] >> temp.depth) && count(delim.begin(),delim.end(),'x') == 2 )
r = temp;
else {
stream.clear( stream.rdstate() | ios::failbit );
stream.seekg( pos );
}
return stream;
}
int main() {
istringstream stream("800x600x32");
ScreenResolution r;
if ( stream >> r )
cout << r.width << 'x' << r.height << 'x' << r.depth << endl;
else
cout << "error" << endl;
}