Stream exceptions

1
2
3
4
5
6
7
8
9
10
11
std::istringstream iss;
iss.str(*line);
// stream syntax: value>value
for (int z=0; z<2; z++) {
	iss.clear(); // clear flags from previous iterations
	std::getline(iss, container[z], '>');
	if (iss.good()) // goodbit
	if (iss.bad()) // badbit
	if (iss.eof()) // eofbit
	if (iss.fail()) // failbit
}


I run this code for this stream: "\n" (just a newline character to test how it would react). These are the results:

First iteration (contents: "\n"):
good() == false;
bad() == false;
eof() == false;
fail() == true;
At this point, the newline should already be discarded from the stream.

Second iteration (supposedly with a completely empty stream):
good() == false;
bad() == false;
eof() == FALSE (sic!);
fail() == true;

According to cplusplus.com/reference/string/string/getline/ - getline should stop before the newline, discard it from the stream and return empty string. The first iteration's results could be understood like this - internal logic of the operation was disrupted (it didn't found the delimeter (although it found the newline)). I could argue that the logic wasn't disrupted, because it succesfully returned a string, empty, but a string nonetheless.

However, what struck me the most, were the second iterations' results. eof() still returned FALSE on an empty stream. Why?

Could somebody clarify to me:
- what happens to the newline character after it's found (apart from the fact that it stops the extraction)
- is not finding the delimeter/newline critical for the function or not?
Last edited on
Please post real code because it's not easy to guess what is going on in your code that we cannot see.
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
// --------------TOKENIZE PHRASES INTO MATRIXES--------------
	// SYNTAX FOR FILE (each line): word,word,...>word,word,word,...
	selected_dir_stream.close();
	selected_dir_stream.open(dir_chosen);
	std::string* container = new std::string[2];
	std::string* line = new std::string;
	std::string* token = new std::string;
	bool bad_segment=false;
	unsigned bad_segments=0, units_accepted=0;

	for (size_t i=0; i<number_of_lines; i++) {
		bad_segment=false;
		for (int y=0; y<2; y++)
			container[y].erase(0,std::string::npos);
		// get line from std::ifstream to *line
		std::getline(selected_dir_stream, *line);
		// convert it to istd::stringstream object
		std::istringstream language_split;
		language_split.str(*line);
		// two languages are separated by '>' sign
		for (int z=0; z<2; z++) {
			// read line anyway, but if line is not properly formatted - omitt it
			language_split.clear();
			std::getline(language_split, container[z], '>');
			if (language_split.fail()) {
				bad_segment=true;
				bad_segments++;
				break;
			}
		}
		// less vocabulary units, but at least they'll be all valid
		if (!bad_segment) {
			// nest vector<vector>
			source_words.push_back(std::vector<std::string>());
			target_words.push_back(std::vector<std::string>());
			// first language synonyms
			std::istringstream synonym_source_split(container[0]);
			while (std::getline(synonym_source_split, *token, ','))
				source_words.at(units_accepted).push_back(*token);
			// second language synonyms
			std::istringstream synonym_target_split(container[1]);
			while (std::getline(synonym_target_split, *token, ','))
				target_words.at(units_accepted).push_back(*token);
			units_accepted++;
		}
	}
I suspect that *line doesn't contain what you think it does. Here is your code in a program that works as I'd expect it:
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
#include <sstream>
#include <iostream>
#include <string>

using std::cin;
using std::cout;
using std::istringstream;
using std::string;

int main()
{
    string line = "\n";
    cout << "Line is: " << line << '\n';

    std::istringstream iss;
    iss.str(line);
    // stream syntax: value>value
    for (int z=0; z<2; z++) {
	cout << "==== Z=" << z << " ====\n";
	iss.clear(); // clear flags from previous iterations
	string str;
	std::getline(iss, str, '>');
	cout << "After getline, str = \"" << str << "\"\n";
	cout << "good = " << iss.good() << '\n';
	cout << " bad = " << iss.bad() << '\n';
	cout << " eof = " << iss.eof() << '\n';
	cout << "fail = " << iss.fail() << '\n';
    }
}

Output:
Line is:

==== Z=0 ====
After getline, str = "
"
good = 0
 bad = 0
 eof = 1
fail = 0
==== Z=1 ====
After getline, str = ""
good = 0
 bad = 0
 eof = 1
fail = 1
Last edited on
Topic archived. No new replies allowed.