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
Writing a Sequence of Numbers Like: 1 22 333 4444 55555
Divide Array into K Contiguos Partitions Such That Sum of Maximum Partition Is Minimum
C++11 Std::To_String(Double) - No Trailing Zeros
When to Use Virtual Destructors
Is Gcc 4.8 or Earlier Buggy About Regular Expressions
Single Quotes Vs. Double Quotes in C or C++
Why Does Reading a Record Struct Fields from Std::Istream Fail, and How to Fix It
C++11 Rvalues and Move Semantics Confusion (Return Statement)
Explicit Template Instantiation - When Is It Used
C++ Sorting and Keeping Track of Indexes
How to Read in User Entered Comma Separated Integers
Convert from an Infix Expression to Postfix (C++) Using Stacks
Difference Between Const Int*, Const Int * Const, and Int Const *
Do the Parentheses After the Type Name Make a Difference With New
C++ Delete - It Deletes My Objects But I Can Still Access the Data