Reputation: 21
Let's say I have
int a; cin >> a;
int b; cin >> b;
int c; cin >> c;
I would like to know how I can get same results from both inputs:
1.2.3 and 1 2 3
so that a would be 1, b would be 2 and c would be 3 if I input 1.2.3
Upvotes: 2
Views: 652
Reputation: 57749
You could read the text as a string, replace the '.' with space, then use std::istringstream
to convert to numbers:
std::string text_read;
std::getline(cin, text_read);
std::string::size_type position = text_read.find('.');
while (position != std::string::npos)
{
text_read[position] = ' ';
position = text_read.find('.');
}
int a;
int b;
int c;
std::istringstream text_stream(text_read);
text_stream >> a;
text_stream >> b;
text_stream >> c;
This is a brute force technique. You may be able to optimize using std::transform
.
Upvotes: 0
Reputation: 5576
This post is marked as C++.
Here is some C++ to consider:
#include <iostream>
#include <iomanip>
#include <sstream>
#include <string>
#include <cassert>
// forward
// stream input, extract and discard junk char
void trial1(std::string s);
// stream input, ignore() junk char,
// with error check for each integer input
void trial2(std::string s);
// sscanf of string
void trial3(std::string s);
int main(int , char** )
{
std::cout << "\n"; // stream input, extract and discard junk char
trial1("1.2.3");
trial1("1,2,3");
trial1("1 2 3"); // fail
std::cout << "\n"; // stream input, ignore junk char, error checks
trial2("1.2.3");
trial2("1,2,3");
trial2("1 2 3");
trial2("11.12.13");
trial2("111,222,333");
trial2("1234 1234 1234");
trial2("1234 -12345678 1234");
trial2("1x2y3");
trial2("1xx2yy3"); // fail - ignore skips 1 char, not 2
std::cout << "\n"; // sscanf of std::string
trial3("1.2.3");
trial3("1 2 3");
trial3("1,2,3");
trial3("111,222,333");
trial3("1234 -12345678 1234");
trial3("1234,1234,1234");
trial3("1xx2yy3"); // fail
std::cout << "\n"; // requirements?
trial1("foo bar");
trial2("foo bar");
trial3("foo bar");
}
void trial1(std::stringstream& sin)
{
char junk;
int a = -1; sin >> a >> junk;
int b = -1; sin >> b >> junk;
int c = -1; sin >> c >> junk;
std::cout << " --> " << a << " " << b << " " << c;
}
void trial1(std::string s)
{
std::cout << '\n' << __FUNCTION__ << " '" << s << "'";
std::stringstream sin (s);
trial1(sin);
}
void trial2(std::stringstream& sin)
{
int a = -1;
int b = -1;
int c = -1;
do{
sin >> a;
if(!sin.good() && !sin.eof()) // check for error
std::cerr << " error on a " << std::flush;
sin.ignore(); // ignore 1 char
sin >> b;
if(!sin.good() && !sin.eof()) // check for error
std::cerr << " error on b " << std::flush;
sin.ignore();
sin >> c;
if(!sin.good() && !sin.eof()) // check for error
std::cerr << " error on c " << std::flush;
}while(0);
std::cout << " --> " << a << " " << b << " " << c;
}
void trial2(std::string s)
{
std::cout << '\n' << __FUNCTION__ << " '" << s << "'";
std::stringstream sin (s);
trial2(sin);
}
void trial3(std::string s)
{
std::cout << '\n' << __FUNCTION__ << " '" << s << "'";
int a = -1;
int b = -1;
int c = -1; // note added ','----v---------v
if (std::sscanf(s.c_str(), "%d%*1[ .,]%d%*1[ .,]%d", &a, &b, &c) == 3)
std::cout << " --> " << a << " " << b << " " << c;
else
std::cout << " --> " << a << " " << b << " " << c << " FAILED." << std::flush;
}
with output:
trial1 '1.2.3' --> 1 2 3
trial1 '1,2,3' --> 1 2 3
trial1 '1 2 3' --> 1 3 -1
trial2 '1.2.3' --> 1 2 3
trial2 '1,2,3' --> 1 2 3
trial2 '1 2 3' --> 1 2 3
trial2 '11.12.13' --> 11 12 13
trial2 '111,222,333' --> 111 222 333
trial2 '1234 1234 1234' --> 1234 1234 1234
trial2 '1234 -12345678 1234' --> 1234 -12345678 1234
trial2 '1x2y3' --> 1 2 3
trial2 '1xx2yy3' error on b error on c --> 1 0 -1
trial3 '1.2.3' --> 1 2 3
trial3 '1 2 3' --> 1 2 3
trial3 '1,2,3' --> 1 2 3
trial3 '111,222,333' --> 111 222 333
trial3 '1234 -12345678 1234' --> 1234 -12345678 1234
trial3 '1234,1234,1234' --> 1234 1234 1234
trial3 '1xx2yy3' --> 1 -1 -1 FAILED.
trial1 'foo bar' --> 0 -1 -1
trial2 'foo bar' error on a error on b error on c --> 0 -1 -1
trial3 'foo bar' --> -1 -1 -1 FAILED.
Upvotes: 1
Reputation: 663
You could use getline() to get the whole input and strtok() to tokenize the string. You may need to validate input etc. Here is an example.
#include <iostream>
#include <string.h>
using namespace std;
void DoSomething(char* inputChar){
printf("%s\n", inputChar);
}
int main() {
char myInput[256];
char* pch;
char* delimiters = " .";
//Loop Through Input
while (cin.getline(myInput,256)) {
cout << "-" << myInput << endl;
pch = strtok(myInput, delimiters);
while (pch != NULL){
//Individual input chars here
DoSomething(pch);
//Set NULL to find next delimited set of char
pch = strtok(NULL, delimiters);
}
}
return 0;
}
You can modify the delimiter list and whether or not to store or do something else with the inputs. Obviously getline() could be taken out of the outer while() if you only need to use it once. atoi() can try to cast the char* to int for you as well.
I used input
1 2 3
1.2.3
1
Upvotes: 0
Reputation: 727047
You can do it with std::scanf
:
if (std::scanf("%d%*1[ .]%d%*1[ .]%d", &a, &b, &c) == 3) {
... // Input was successful
}
The tricky part is this for mat specifier: %*1[ .]
It scans and ignores a single space or a single dot.
Upvotes: 6