Sometimes, I need to read two integer parameters in a single input line, separated by a whitespace.
I have these two functions that seem to do the job just fine:
#include <iostream>
#include <sstream>
#include <deque>
// Splits a string by its whitespaces and returns a deque with each item.
deque<string> split(string original) {
deque<string> result;
string buffer;
stringstream stream(original);
while (stream >> buffer) {
result.push_back(buffer);
}
return result;
}
// Reads two integer parameters from a single line, separated by a whitespace
void getTwiceInput(int &a,int &b) {
string input;
getline(cin,input);
deque<string> deck = split(input);
stringstream ss;
ss << deck[0];
ss >> a;
ss.clear();
ss << deck[1];
ss >> b;
}
So in my program I do this call:
int x,y;
getTwiceInput(x, y);
Is there an easier way to achieve this? It is a bit tiring having to type all of that just to achieve this for every programming challenge given.
3 Answers 3
I would recommend to use std::stringstream
for split. Here is how I think this function would look like:
#include <sstream>
#include <vector>
#include <iterator>
template<typename T>
std::vector<T> split(const std::string& line) {
std::istringstream is(line);
return std::vector<T>(std::istream_iterator<T>(is), std::istream_iterator<T>());
}
And here is how to use it:
std::string line = "1.2 3.4 5.6e7";
std::vector<double> vec = split<double>(line);
This method is more general and can split more than two elements as well as parse them to any type provided as template parameter, as long as it is "readable" by operator>>
.
-
\$\begingroup\$ Would
std::assign
be better thanstd::copy
? \$\endgroup\$William Morris– William Morris2013年04月18日 19:17:58 +00:00Commented Apr 18, 2013 at 19:17
I can think of two more ways of doing it.
1. Using iostream iterators. (Following code is from here)
#include <iostream>
#include <iterator>
using namespace std;
int main () {
double value1, value2;
cout << "Please, insert two values: ";
istream_iterator<double> eos; // end-of-stream iterator
istream_iterator<double> iit (cin); // stdin iterator
if (iit!=eos) value1=*iit;
iit++;
if (iit!=eos) value2=*iit;
cout << value1 << "*" << value2 << "=" << (value1*value2) << endl;
return 0;
}
2. Converting string to int using atoi() rest everything will be same.
-
\$\begingroup\$ Streams are nice, but using
atoi()
is not a good idea. Better usestd::stoi()
if your compiler handles C++11 Standard. \$\endgroup\$Archie– Archie2013年04月18日 09:05:54 +00:00Commented Apr 18, 2013 at 9:05
Sorry, what is the problem with:
cin >> x >> y;
Or:
void getTwiceInput(int &a,int &b) {
string input;
getline(cin,input);
stringstream ss(input);
ss >> a >> b;
}
?? Here maybe you need to detect format errors (no mummers or only one per line, or more than two..) But your code dont do that anyway.
std::pair
instead ofstd::deque
. In fact, why do you even usestd::deque
? Use juststd::vector
, it's generally more efficient except cases where you have to insert values in random position, especially in front. \$\endgroup\$std::cin >> x >> y;
\$\endgroup\$