Programming Language & Its Applications β Virtual Functions and File Handling, NEC licence examination syllabus (Nepal Engineering Council).
Four state bits that tell you what went wrong β and why an unchecked stream fails silently instead of loudly.
#include <iostream>
#include <sstream>
#include <fstream>
#include <string>
void report(const std::string &tag, const std::ios &s) {
std::cout << " " << tag
<< " good=" << s.good()
<< " eof=" << s.eof()
<< " fail=" << s.fail()
<< " bad=" << s.bad() << "\n";
}
int main() {
std::cout << std::boolalpha;
/* 1. a normal successful read */
{ std::istringstream s("42");
int n; s >> n;
report("read 42 :", s); }
/* 2. reading a number where text is β CONVERSION failure */
{ std::istringstream s("abc");
int n = -1; s >> n;
report("read abc:", s);
std::cout << " n is still " << n
<< " β the variable was NOT touched\n"; }
/* 3. reading past the end */
{ std::istringstream s("7");
int a, b; s >> a;
report("after 7 :", s);
s >> b;
report("past end:", s); }
/* 4. a file that does not exist */
{ std::ifstream f("no_such_file_here.txt");
report("bad open:", f); }
/* 5. recovery: clear() then carry on */
{ std::istringstream s("abc 99");
int n;
s >> n;
std::cout << " before clear: fail=" << s.fail() << "\n";
s.clear();
std::string junk; s >> junk; /* consume "abc" */
s >> n;
std::cout << " after clear+skip: n=" << n
<< " fail=" << s.fail() << "\n"; }
return 0;
}
Output:
read 42 : good=true eof=false fail=false bad=false
read abc: good=false eof=false fail=true bad=false
n is still -1 β the variable was NOT touched
after 7 : good=false eof=true fail=false bad=false
past end: good=false eof=true fail=true bad=false
bad open: good=false eof=false fail=true bad=false
before clear: fail=true
after clear+skip: n=99 fail=false
#include <iostream>
#include <sstream>
int main() {
/* WRONG loop */
{
std::istringstream s("10 20 30");
int v = 0, count = 0;
std::cout << " WRONG: ";
while (!s.eof()) { s >> v; std::cout << v << " "; count++; }
std::cout << " -> " << count << " iterations\n";
}
/* RIGHT loop */
{
std::istringstream s("10 20 30");
int v = 0, count = 0;
std::cout << " RIGHT: ";
while (s >> v) { std::cout << v << " "; count++; }
std::cout << " -> " << count << " iterations\n";
}
/* diagnosing WHY a parse stopped */
{
std::istringstream s("10 20 oops 40");
int v, sum = 0, n = 0;
while (s >> v) { sum += v; n++; }
std::cout << " parsed " << n << " values, sum=" << sum << " β ";
if (s.eof()) std::cout << "clean end\n";
else if (s.bad()) std::cout << "stream broken\n";
else if (s.fail()) std::cout << "MALFORMED DATA found\n";
}
return 0;
}
Output:
WRONG: 10 20 30 30 -> 4 iterations
RIGHT: 10 20 30 -> 3 iterations
parsed 2 values, sum=30 β MALFORMED DATA found
while (in >> v) asks "did this read work?", which is the actual question. while (!in.eof()) asks "do I expect the next read to work?", which is a guess β and guesses about I/O are wrong at exactly the boundary you care about.
#include <iostream>
#include <sstream>
#include <limits>
#include <string>
/* Reads an int in [lo,hi] from any istream, rejecting
garbage without ever spinning forever. */
bool readInt(std::istream &in, int &out, int lo, int hi) {
for (;;) {
if (in >> out) {
if (out >= lo && out <= hi) return true;
std::cout << " out of range, try again\n";
} else {
/* distinguish "broken input" from "no more input" */
if (in.eof() || in.bad()) return false;
in.clear(); /* reset failbit */
in.ignore(std::numeric_limits<std::streamsize>::max(),
'\n'); /* DISCARD the junk */
std::cout << " not a number, try again\n";
}
}
}
int main() {
/* simulated user input: junk, out of range, then valid */
std::istringstream fake("abc\n999\n-5\n42\n");
int v;
std::cout << " reading a value in [1,100]:\n";
if (readInt(fake, v, 1, 100))
std::cout << " accepted " << v << "\n";
else
std::cout << " input exhausted\n";
/* and the exhaustion path */
std::istringstream empty("xyz\n");
std::cout << " second attempt:\n";
if (!readInt(empty, v, 1, 100))
std::cout << " input exhausted, gave up cleanly\n";
return 0;
}
Output:
reading a value in [1,100]:
not a number, try again
out of range, try again
out of range, try again
accepted 42
second attempt:
not a number, try again
input exhausted, gave up cleanly
std::expected<T, E>, which makes a function return either a value or an error that the caller cannot ignore β the compiler warns if you drop it. Rust built its whole error story on the same idea with Result<T, E> and the ? operator, and Go returns explicit error values everywhere. All three are reactions to exactly the problem on this page: a failure you can accidentally not notice. Search "std::expected C++23" and "Rust Result error handling".good(), eof(), fail(), bad(), clear(). The while (!eof()) bug β last item processed twice β is a favourite trace question; show both the wrong and right loops. Know that a failed stream ignores all further operations until clear(), and that recovering from bad input needs both clear() and ignore(). Mention that streams do not throw unless you call exceptions().Create a free account to tick topics off, take notes as you read, watch the video lessons and get a day-by-day study plan built around your exam date.
Loadingβ¦