Почему запись пустого std :: istringstream.rdbuf () устанавливает failbit? - PullRequest
1 голос
/ 21 апреля 2020

Я узнал, что я могу скопировать C ++ std :: istream в C ++ std :: ostream, выведя функцию istreams 'rdbuf (). Я использовал его несколько раз, и он работал нормально.

Сегодня у меня возникли проблемы, потому что эта операция устанавливает badbit, если std :: istream пуст (по крайней мере для std :: istringstream). Я написал следующий код, чтобы продемонстрировать мою проблему:

#include <stdio.h>
#include <sstream>

int main(int argc, char *argv[])
{
    std::ostringstream ss;

    ss << std::istringstream(" ").rdbuf(); // this does not set failbit
    printf("fail=%d\n", ss.fail());

    ss << std::istringstream("").rdbuf(); // why does this set failbit ???
    printf("fail=%d\n", ss.fail());
}

Я пробовал Windows / VS2017 и Linux / g cc -9.20, и оба ведут себя одинаково.

Я использую стандартный :: istream & в сигнатуре метода со значением по умолчанию std :: istringstream (""). Вызывающий код должен передавать необязательный istream, который добавляется к некоторым другим данным.

  • Кто-нибудь может объяснить, почему установлен badbit?
  • Есть ли лучший способ реализации этот необязательный std :: istream & параметр?

Я знаю, я мог бы написать два метода, один с дополнительным параметром std :: istream &, но я хочу избежать дублирования кода.

Заранее спасибо,

Марио

Обновление 22-апр-20

Теперь я использую следующий код:

#include <stdio.h>
#include <sstream>

int main(int argc, char *argv[])
{
    std::ostringstream out;
    std::istringstream in("");
    while (in)
    {
        char Buffer[4096];
        in.read(Buffer, sizeof(Buffer));
        out.write(Buffer, in.gcount());
    }
    printf("fail=%d\n", out.fail());
}

Я также добавил предупреждение о настройке битов при копировании пустых файлов в { ссылка }

1 Ответ

1 голос
/ 21 апреля 2020

Документация ostream::operator<< описывает следующее поведение для чтения потоков:

Ведет себя как функция UnformattedOutputFunction. После создания и проверки объекта sentry проверяется, является ли sb нулевым указателем. Если это так, выполняет setstate(badbit) и завершает работу. В противном случае извлекает символы из входной последовательности, управляемой sb, и вставляет их в *this до тех пор, пока не будет выполнено одно из следующих условий:

   * end-of-file occurs on the input sequence;
   * inserting in the output sequence fails (in which case the character to be inserted is not extracted);
   * an exception occurs (in which case the exception is caught). 

Если символы не были вставлены, выполняется setstate(failbit). Если во время извлечения было сгенерировано исключение, он устанавливает failbit и, если failbit установлен в exceptions (), сбрасывает исключение.

Как вы можете сказать, это явно говорит о том, что попытка вставить пустой буфер приведет к установите failbit. Если вы хотите сделать его «необязательным», просто проверьте исправность потока перед вставкой буфера и затем выполните ss.clear(), чтобы очистить бит ошибки.

...