После freopen (.., "r", stdin) + fclose (stdin) дальнейший std :: cin не работает - PullRequest
0 голосов
/ 21 марта 2019
int main(){

    int a,b;

    std::cin >> a >> b;           // first

    freopen("test.txt","r",stdin);
    std::cin >> a >> b;           // second
    fclose(stdin);
    cout << a << ", " << b << endl;

    freopen("test2.txt","r",stdin);
    std::cin >> a >> b;          // third
    fclose(stdin);
    cout << a << ", " << b << endl;

    std::cin >> a >> b;          // fourth

    return 0;
}

Этот блок кода должен содержать смесь ввода из терминала и файлов. Первый, второй и третий cin работают нормально, но четвертый не удался. Похоже, что fclose (stdin) не имеет здесь никакой функции.

1 Ответ

0 голосов
/ 21 марта 2019

Согласно проекту c ++ 27.4.2 :

Объект cin управляет вводом из буфера потока, связанного с объектом stdin, объявленным в .

Чтение из std::cin аналогично чтению из stdin. Это означает, что после fclose(stdin) использование std::cin похоже на вызов scanf("%d", &a).

Это именно то, что происходит в третьем случае, когда fclose(stdin) вызывается перед чтением std::cin. В отличие от случаев 1-3 код читает std::cin до fclose(stdin).

Чтение из закрытого stdin возможно не определено. Вот что говорит c11 об этом:

7.21.7.1 Функция fgetc

...

int fgetc(FILE *stream);

...

Возвращает: Если индикатор конца файла для потока установлен, или если поток находится в конце файла, конец для потока установлен индикатор of-file, а функция fgetc возвращает EOF. В противном случае Функция fgetc возвращает следующий символ из входного потока, на который указывает поток. Если происходит ошибка чтения, устанавливается индикатор ошибки для потока и функция fgetc возвращает EOF.

Этот текст охватывает все случаи чтения с открытого стандартного ввода (успешное завершение, конец файла и ошибка чтения), но они не относятся к случаю, когда поток закрыт из-за fclose. Я не смог найти ничего в стандарте, который покрывает этот случай, что означает, что случай не определен.

Вывод : чтение из std::cin после fclose(stdin) без каких-либо дальнейших действий freopen является неопределенным поведением. Попытка прочитать закрытый поток C может ссылаться на освобожденные ресурсы.

...