L12 Handling IO Errors and String Streams
handling IO errors
An example of an error-prone input:
#include <iostream>
using namespace std;
int main(void) {
ifstream inputFile("myFile.txt");
int a, b;
inputFile >> a >> b;
return 0;
}
errors:
myFile.txtdoes not existinputFile.fail()returnstrue
- Input format is not expected (e.g.,
intexpected butcharprovided)cin.fail()orinputFile.fail()will returntrue
- End-of-file: searching for a data type, but end of file or user input reached before data type found.
- Returns
cin.eof()orinputFile.eof() - Fail flag does not get returned - detail not testable
- Returns
One way to avoid this is to only read an input one value at a time. In the above code, we don't know if a or b is at fault since they're both read at the same time.
handling file doesn't exist
int main(void) {
ifstream inFile("file.txt");
if (inFile.fail()) {
cerr << "File doesn't exist" << endl;
return 1; // return 1 because did not execute successfully
}
}
cerr is a cout that doesn't have a bufferDoesn't need to wait for program to flush from buffer to terminal; prints to terminal immediately
handling unexpected input format
If your input is:
" 13.4\n"
The following code will error:
int x, y;
cin >> x >> y;
cinwill store 13cinwill fail silently as it reads.which is not part of an intcin.fail()will be equal to true here
- The buffer is not changed
yis zeroed out
If
cin.fail() is true, no cin statements will work.Hence, we first need to reset the fail flag.
To fix this:
- Split the
cinstatement to read onlyxand onlyy - Reset the error flag
cin.clear()
- The
.is still in the buffer, socin >> ywill still fail. So, we can clean the buffer.cin.ignore(int n, char c);- This discard
ncharacters, or discards up toch, whichever comes first
example: handling unexpected error format
e.g., for the following input:
"1010 Vibha"
We can use the following code:
string name;
cin.ignore(1000, ' ');
// ignores the first 1000 lines, OR ignores up to the first space
// whichever comes first, but by specifying 1000 then it basically guarantees
// that the code will only ignore if a space is found
cin >> name;
handling end of file or end of input reached
// loop through the input until end of file reached
// and in each iteration, check for a fail flag
// if fail flag raised then clear it, and then run a .ignore() on input
// then try looking at the input again
while (!cin.eof) {
cin >> x;
if (cin.fail()) {
cin.clear()
cin.ignore()
}
}
Task: write a program that reads from a file integers and prints their sum. If a non-int number is read, ignore it. Numbers are written on separate lines.
e.g.
13 \n
17 \n
8 \n
$ \n
. \n
3 \n
#include <fstream>
#include <iostream>
using namespace std;
int main(void) {
ifstream inFile("File.txt"); // import a file
if (inFile.fail()) { // error code
cerr << "File doesn't exist" << endl;
return 1
}
int x, sum = 0;
inFile >> x;
while (!inFile.eof()) {
if (inFile.fail()) {
inFile.clear();
inFile.ignore(1000, '\n');
} else {
sum += x;
}
inFile >> x;
}
cout << "Reached EOF" << endl;
cout << "Sum is " << sum << endl;
return 0;
}