How to Test Whether Stringstream Operator≫≫ Has Parsed a Bad Type and Skip It

How to test whether stringstream operator has parsed a bad type and skip it

The following code works well to skip the bad word and collect the valid double values

istringstream iss("2.832 1.3067 nana 1.678");
double num = 0;
while(iss >> num || !iss.eof()) {
if(iss.fail()) {
iss.clear();
string dummy;
iss >> dummy;
continue;
}
cout << num << endl;
}

Here's a fully working sample.


Your sample almost got it right, it was just missing to consume the invalid input field from the stream after detecting it's wrong format

 if (parser.fail()) {
std::cout << "Failed!" << std::endl;
parser.clear();
string dummy;
parser >> dummy;
}

In your case the extraction will try to read again from "nana" for the last iteration, hence the last two lines in the output.

Also note the trickery about iostream::fail() and how to actually test for iostream::eof() in my 1st sample. There's a well known Q&A, why simple testing for EOF as a loop condition is considered wrong. And it answers well, how to break the input loop when unexpected/invalid values were encountered. But just how to skip/ignore invalid input fields isn't explained there (and wasn't asked for).

How to save and restore an std::istringstream's buffer?

You can use tellg() and seekg() to save and restore your position if you like:

#include <string>
#include <sstream>

int main()
{
std::istringstream iss("some text");

std::string word;

// save the position
std::streampos pos = iss.tellg();

// read a word
if(iss >> word)
std::cout << word << '\n';

iss.clear(); // clear eof or other errors
iss.seekg(pos); // move to saved position

while(iss >> word)
std::cout << word << '\n';

}

Validating Input C++ [duplicate]

This:

cin >> num;
if(!(num))

Should be this:

if (!(cin >> num))

You are checking the value of num when you should instead be checking the error state of cin. operator>> returns a reference to the input stream, which is then implicitly convertible to bool, where false means the stream encountered an error.

Also, this is completely useless:

else if(static_cast<double>(static_cast<int>(num)) != num)

Casting an int value to an int is a no-op, and casting an int value to a double back to an int will get you the original int value.

num is an int, it can't read in anything else. So, by the time your code reaches this point, you know num must be holding a valid int value. However, if the user had actually entered a floating-point number instead, operator>> would have stopped reading at the decimal point, leaving it and the remaining fractional value in cin's input buffer for later reading.

Also, the 2nd call to cin.ignore() is wrong. By that point, operator>> was able to read in an int value, it just wasn't satisfactory to you. So don't ignore subsequent input yet.

If you really need to differentiate between integer and floating-point input, you will have to read in the input as a string first, and then parse it to see what it actually holds, eg:

int num = 0;
string s;
size_t pos;

while (true){
cout << "enter num: ";
if (!(cin >> s)){
cin.clear();
cin.ignore(numeric_limits<streamsize>::max(), '\n');
cout << "input error, try again" << endl;
}
else{
try{
num = stoi(s, &pos);
if (pos != s.size()) throw invalid_argument("");
if (num > 0){
break;
}
cout << "num must be greater than 0" << endl;
}
catch (const exception &){
cout << "num must be an int" << endl;
}
}
}

Online Demo

std::cin doesn't throw an exception on bad input

C++ iostreams don't use exceptions unless you tell them to, with cin.exceptions( /* conditions for exception */ ).

But your code flow is more natural without the exception. Just do if (!(cin >> input)), etc.

Also remember to clear the failure bit before trying again.

The whole thing can be:

int main()
{
int input;
do {
cout << "Please enter an integral value \n";
cin.clear();
cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
} while(!(cin >> input));
cout << input;
return 0;
}

c++ moving to next element in a file.txt [duplicate]

You can do the following

int num = 0;
while(myfile >> num || !myfile.eof()) {
if(myfile.fail()) { // Number input failed, skip the word
myfile.clear();
string dummy;
myfile >> dummy;
continue;
}
cout << num << endl; // Do whatever necessary with the next number read
}

See a complete, working sample here

not exiting while loop with cin as condition c++

It is possible to use getline function to get data line-by-line, then read values via a stringstream:

#include <iostream>
#include <stdio.h>
#include <sstream>

using namespace std;

int main() {
string line;
while(getline(cin, line)) {
stringstream str_stream(line);
int num;
while(str_stream >> num) {
cout << "..." << num << "..." << endl;
}
cout << "----" << endl;
}
}


Related Topics



Leave a reply



Submit