What are the criteria for failbit and badbit in a Std::istream?

Asked

Viewed 96 times

5

In a C++ exercise, it is proposed to store a data (numeric, integer - eg.: 4 or -3650) entered by the user through the console. This is an exercise to deal with exceptions and "defensive programming".

Both the workbook and the exercise itself make apology to the use of std::cin.fail() to identify invalid data and treat it within a try...catch. So far so good - I’ve even completed the exercise - and everything works as proposed.

However, neither the workbook nor the exercise or any other resource I could find gives satisfactory details so that I can measure the criterion which causes the error flag on std::cin. In the documentation of C++ found explanation about the existence of error flags returned by function fail(), including about failbit and badbit - but I was in doubt about the "internal logic of the operation itself".

By observation and according to the section below:

failbit is generally set by an Operation when the error is Related to the Internal Logic of the Operation itself

If we consider:

int x = 0;
std::cout << "Digite um número: ";
cin >> x; // stackoverflow

if (std::cin.fail()) {
    std::cout << "A operação falhou porquê tentei armazenar uma string em int\n";
}

I understand that std::cin.fail() would return true (failbit) in this case why we tried to store a const char*/string in a variable of type int.

That is correct?


[Bonus]: If you’re right, and I’m storing in a string, what could be considered a failure condition (failbit) or error (badbit) to the istream? How could it be possible to cause this mistake?

Remembering that this is a purely educational example. The purpose in the exercise was to use std::cin.fail() to treat simple mistakes but curiosity made me want to expand the context (so it helps to know what the limitations of this technique, advantages/disadvantages). Thank you!

  • 1

    cppreference is a better place to search for information about C++.

  • I think your understanding is correct. Complementando com o que está descrito em cppreference (linkada por @MárioFeroldi), failbit indica uma “falha de conversão de tipos” ou “nenhum caracter lido”, enquanto que badbit tem mais a ver com erros de escrita como “disco cheio”, “falha ao alocar memória”etc. To increase confusion, some operations can set several bits at once and fail() tests both failbit and badbit... (as I am only confirming your assumption and do not have time to do some tests, I posted only as a comment)

1 answer

3


What are the criteria for failbit and badbit in a Std::istream?

The default that specifies the language, Standard for Programming Language C ++, says:

Table 109 - iostate effects

  • badbit indicates a Loss of Integrity in an input or output Sequence (such as an irrecoverable read error from a file);
  • eofbit indicates that an input Operation reached the end of an input Sequence;
  • failbit indicates that an input Operation failed to read the expected characters, or that an output Operation failed to generate the desired characters.

Translating:

  • badbit indicates the loss of integrity of an input or output sequence (such as an unrecoverable error in reading a file);
  • eofbit indicates that an input operation has reached the end of an input sequence;
  • failbit indicates that an input operation failed to read the expected characters, or that an output operation failed to generate the desired characters.

NOTE: The text was copied from the C++17 draft (PDF file). For reference, the C++20 draft offers the same text: https://github.com/cplusplus/draft/blob/master/source/iostreams.tex

A simple and straightforward way of explaining:

  • badbit when some fix-free error happens in the stream. You must destroy the instance as any other operation offers no guarantees that it will work.
  • failbit when the use of some stream resource did not work as expected at this time, but the stream itself is intact. Try again until you hit.

I understand that Std::Cin.fail() would return true (failbit) in this case why we tried to store a const char*/string in a int-type.

That is correct?

Not, but almost there. You’re reading a string from the stream cin, trying to interpret it as a decimal number, and storing it as an integer in the variable x.

You get failbit if the string is not a decimal number, or if the number exceeds the maximum size specified for the type int.

If you’re correct, and I’m storing it in a string, which could be considered a failure (failbit) or error condition (badbit) to istream? How could this error be caused?

There are several ways to cause a badbit. Several causes are listed in the link https://en.cppreference.com/w/cpp/io/ios_base/iostate, quoted by Mário Feroldi. Can be originated by natural and artificial methods.

An example of natural environment is:

std::cin.rdbuf(nullptr);
std::cin.unget();

The artificial method is:

std::cin.setstate(std::ios_base::badbit);

A complete example based on the question code:

#include <iostream>
#include <sstream>
#include <streambuf>

int main()
{
    int x = 0;    
    try {
        std::cout << "Digite um número: ";
        std::cin.exceptions(std::ios_base::failbit | std::ios_base::badbit);
        //std::cin.rdbuf(nullptr);//badbit natural
        //std::cin.unget();//badbit natural
        //std::cin.setstate(std::ios_base::badbit);//badbit artificial
        std::cin >> x;//failbit
        std::cout << (x + 1);//se digitou 11, retornarei 12
    } catch (std::ios_base::failure& fail) {
        std::cout << "\nerro nr " << fail.code().value() << "\n";//igual para fail e bad no GCC
        std::cout << fail.what() << "\n";//igual para fail e bad no GCC    
        if (std::cin.bad()) {
            std::cout << "falha catastrófica \n";
        } else {
            std::cin.clear();
            std::stringbuf stream;
            std::cin >> &stream;
            std::cout << "não foi legal digitar " << &stream << "\n";
        }
    }
}
  • 1

    Interesting! Thank you for elaborating the facts and the examples. I’ll just give Bounty time to see if anyone else shows up and has something else to add. :)

Browser other questions tagged

You are not signed in. Login or sign up in order to post.