C++ Detect if input doesn't satisfy conditions

孤街浪徒 提交于 2021-01-28 08:31:25

问题


Update: Please guid me through a clear answer and small example of usage

I am reading data from a binary file in which the first number indicates the number of inputs or values to read, the second tells the length of the first input then the input itself, after that the length of the second input then the input itself and so on.

So wrote the following code:

    std::ifstream infile(filename, std::ios_base::binary);
    unsigned int NumberOfInputs;
    infile.read((char *) &NumberOfInputs, sizeof(unsigned int));

    for (unsigned int i = 0; i < NumberOfInputs; i++) {
        unsigned int Input_Lengh;
        infile.read((char *) &Input_Lengh, sizeof(unsigned int));
        string data;
        while (Input_Lengh) {
        char letter;
        infile.read((char *) &letter, sizeof(char));
        data += letter;
        Input_Lengh--;
        }
    }

But what if the file was corrupted and the user told me that the number of inputs is 10 and I only read 2 (Because I got to EOF for example) How may I detect this?


回答1:


When using std::istream::read() you can test both the eofbit and failbit flags. Both of them are set when end of file is reached. In your case, after every read operation, I would recommend testing if these flags are set. If so, just interrupt your file read sequence.

For example:

if ( (infile.rdstate() & std::ifstream::failbit ) != 0 )
{
/* error handling here*/
}

Alternatively, you can use gcount() std::istream method to obtain the number of characters successfully read.

For example:

if (infile.gcount() < N_EXPECTED_CHARS)
{
    /* error handling here*/
}



回答2:


From the doc. of std::istream::read():

Characters are extracted and stored until any of the following conditions occurs:

  • count characters were extracted and stored
  • end of file condition occurs on the input sequence (in which case, setstate(failbit|eofbit) is called). The number of successfully extracted characters can be queried using gcount().

I made a small MCVE to demonstrate how to check the state of input stream and the usage of std::istream::gcount():

#include <iostream>
#include <fstream>
#include <vector>

int main(int argc, char **argv)
{
  std::ifstream infile(argv[1], std::ios_base::binary);
  unsigned n;
  if (!infile.read((char*)&n, sizeof n)) {
    std::cerr << "ERROR! Failed to read number of inputs.\n";
    return 1;
  }
  for (unsigned i = 0; i < n; ++i) {
    unsigned len;
    if (!infile.read((char*)&len, sizeof len)) {
      std::cerr << "ERROR! Failed to read length of input " << (i + 1) << ".\n";
      return 1;
    }
    std::vector<char> data(len);
    if (!infile.read(&data[0], len)) {
      std::cerr << "ERROR! Failed to read data of input " << (i + 1) << ".\n"
        << "Expected " << len << " bytes but got " << infile.gcount() << ".\n";
      return 1;
    }
  }
  std::cout << "File '" << argv[1] << "' successfully read.\n";
}

Test:

$ g++ -std=c++17 -O2 -Wall -pedantic -pthread main.cpp

$ echo "Good:" ; \
  echo -ne '\x01\x00\x00\x00\x04\x00\x00\x00''abcd' > test.dat ; \
  ./a.out test.dat
Good:
File 'test.dat' successfully read.

$ echo "Bad n:" ; \
  echo -ne '\x02\x00\x00\x00\x04\x00\x00\x00''abcd' > test.dat ; \
  ./a.out test.dat
Bad n:
ERROR! Failed to read length of input 2.

$ echo "Bad len:"; \
  echo -ne '\x01\x00\x00\x00\x04\x00\x00\x00''abc' > test.dat ; \
  ./a.out test.dat
Bad len:
ERROR! Failed to read data of input 1.
Expected 4 bytes but got 3.

Live Demo on coliru

Notes:

  • The size of unsigned depends on the compiler / target architecture. It may be less than 4 bytes.
  • The endianess of unsigned is platform dependent.
    In this sample, little-endian is assumed but there are still platforms with big-endianess.
    (At least, in the past there were platforms with even more exotic endianess.)

To fix both issues, the expected number of bytes can be read and composed to the integral using bit arithmetic operators.

Related Q/As:

  • SO: C++ istream: Is gcount() always set after a read() even if it fails?
  • SO: Ifstream reading error


来源:https://stackoverflow.com/questions/63355962/c-detect-if-input-doesnt-satisfy-conditions

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!