L12 Handling IO Errors and String Streams

#ece244

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:

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 buffer

Doesn'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;
  1. cin will store 13
  2. cin will fail silently as it reads . which is not part of an int
    1. cin.fail() will be equal to true here
  3. The buffer is not changed
  4. y is zeroed out
If cin.fail() is true, no cin statements will work.

Hence, we first need to reset the fail flag.

To fix this:

  1. Split the cin statement to read only x and only y
  2. Reset the error flag
    1. cin.clear()
  3. The . is still in the buffer, so cin >> y will still fail. So, we can clean the buffer.
    1. cin.ignore(int n, char c);
    2. This discard n characters, or discards up to ch, 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;
}