Would istream tried to read again where it failed after recovering from fail state

According to C++ regulation, we can recover istream (ist) from fail state if not encountered serious problems using ist.clear() statement.

But there is a question, if ist encountered an exception while reading and lead fail bit being set, with clear() statement we can recover istream to normal state.

Here is the question, would we start from where it failed? Which would mean the same position in the stream would be read twice, which seems controversy to its normal behavior: the content of a file can be read only once if sequentially? Many thanks!


Following is the code snippet with revision while I'm reading Bjarne Stroustrup's Programming: Principles and Practice Using C++ (2nd Edition)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
#include <iostream>
#include <vector>
using namespace std;

void fill_vector(istream &ist, vector<int> &v, char terminator)
{
	int i = 0;
	for(int l; ist >> l; cout << "ist is " << (ist.good() ? "good" : "bad") << endl)
	{
		cout << ++i << endl;
		v.push_back(l);
	}

	if (ist.eof())
		return;

	if (ist.bad())
		cerr << "ist is bad!" << endl;

	if (ist.fail())
	{
		ist.clear();

		char c;
		cin >> c;
		if (c != terminator)
		{
			ist.unget();
			ist.clear(ios_base::failbit);
		}
	}
}



int main(int argc, char*argv[])
{

	vector<int> vec;
	fill_vector(cin, vec, '*');

	for (auto &v:vec)
		cout << v << endl;

	char c; cin >> c;

	return 0;
}
closed account (48T7M4Gy)
std::cin.clear() to reset the fail state, then follow with std::cin.ignore(1000, '\n') to clear the stream, keeping in mind the figure of 1000 is sufficiently large generally but the 'real' approach to that number uses <limit> which is easy to chase up by a quick google .

http://www.cplusplus.com/reference/istream/basic_istream/ignore/
Last edited on
> would we start from where it failed?
> Which would mean the same position in the stream would be read twice

The same character would not be extracted twice.
(unless we undo the extraction of the last character with unget or reposition the stream with seekg).

Typically, when input failure occurs, the next character has been peeked at, but not extracted.
See: http://en.cppreference.com/w/cpp/io/basic_istream/peek
@kemort
Thank you sir, but does cin.ignore() really matter with the code above?

@JLBorges
Thank you so much, FYI, the code above especially the case where ist failed does not try to extract the stream twice but clears the state and advances to process the next, which is expected to be a terminator?

Am I correct?
Also, the code snippet above is expected to do something like this:
1 2 3 4 5 *
> does not try to extract the stream twice but clears the state and advances to process the next, > which is expected to be a terminator? Am I correct?

Yes.

If the last digit of an integer in the stream is followed by the terminartor (say, a '*'):

The extraction the first int would stop at the terminator; the terminator will remain in the input stream.

The attempt to extract another int would fail because it encounters the terminator first-up; it will put the stream into a failed state without extracting the terminator.

Clear the failed state and extract a char; the terminator would be extracted.

To examine the contents of the stream buffer (on some implementations):
http://www.cplusplus.com/forum/general/207602/#msg979644
@JLBorges

Thanks for your detailed explanation.
To be brief, the character would remained in the stream unless it is successfully extracted into a variable.
closed account (48T7M4Gy)
Thank you sir, but does cin.ignore() really matter with the code above?

Given what Stroustrup is demonstrating now that I have read his explanation and less obscure sample you are correct in questioning the use of ignore() as I suggested. In fact using it would be very unhelpful if data was still to be read after the terminator.
Topic archived. No new replies allowed.