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

4

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 exception handling and "defensive programming."

Both the handout and the exercise itself apologize to the use of std::cin.fail() to identify an invalid die and treat it within try...catch . So far so good - I've even completed the exercise - and everything works as intended.

However, neither the handout nor the exercise or any other feature I could find gives satisfactory details so I can gauge the criterion that causes the error flag in std::cin . In the C ++ documentation I found an explanation for the existence of the error flags returned by the function fail() , including 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 const char* / string into a variable of type int .

Is that correct?

[Bonus]: If it is correct, and I am storing it in a string , what could be considered a failure condition ( failbit ) or error ( badbit ) to istream ? How could this error be caused?

  

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

    
asked by anonymous 03.10.2018 / 06:45

1 answer

2
  

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

The standard 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 from 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.
  •   

Translating:

  • badbit indicates the loss of integrity of an input or output sequence (such as an unrecoverable error reading a file);
  • eofbit indicates that an input operation has reached the end of an input string;
  • 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 has been copied from the C ++ 17 draft (PDF file). For reference purposes, the C ++ 20 draft offers the same text: link

One way to explain it simply and directly is:

  • badbit when some error without repair happens in the stream. You should destroy the instance because any other operation does not provide guarantees that will work.
  • failbit when using some stream feature did not work as expected right now, but the stream itself is intact. Please try again until you get it right.
  

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

     

Is that correct?

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

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

  

If it is correct, and I am storing it in a string, what   could be considered a failure (failbit) or error condition   (badbit) for the istream? How could this error be caused?

There are several ways to cause a badbit. Several causes are listed on the link link, Mario Feroldi . It can be originated by natural and artificial methods.

An example of a 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";
        }
    }
}
    
11.10.2018 / 00:31