Почему не работает символ EOF, если он помещен в конец строки?
Я изучаю С++ и пытаюсь понять, почему символ EOF (Ctrl + Z в Windows) не разбивает цикл while, если он помещен в конец строки.
Мой код:
int main() {
char ch;
while(cin >> ch) {
cout << ch;
}
}
Когда я вхожу в ^ Z, цикл прерывается. Но когда я вхожу в 12 ^ Z, это не так. Почему?
Ответы
Ответ 1
Стандарты C и С++ позволяют текстовым потокам делать совершенно нечестивые вещи в текстовом режиме , который по умолчанию. Эти нечестивые вещи включают перевод между внутренними маркерами новой строки и внешними символами управления новой строкой, а также обработку определенных символов или последовательностей символов, обозначающих конец файла. В Unix-land это не сделано, но в Windows-land это делается, поэтому код может относиться только к оригинальным соглашениям Unix-land.
Это означает, что в Windows нет возможности написать переносимую программу C или С++, которая будет скопировать его вход точно на его вход.
Пока в Unix-land, это не проблема вообще.
В Windows строка, состоящая из одного [Ctrl Z], по умолчанию обозначает маркер конца файла. Это происходит не только в консоли, но и в текстовых файлах (в зависимости от инструментов). Windows унаследовала это от DOS, которая, в свою очередь, унаследовала общую идею от CP/M.
Я не уверен, где CP/M получил это, но это только похоже, совсем не то же самое!, как Unix '[Ctrl D].
В Unix-land общее соглашение для конца файла - это просто "больше данных". В консоли [Ctrl D] по умолчанию отправит ваш напечатанный текст немедленно в ожидающую программу. Когда вы еще ничего не набрали на линии, отправляются 0 байт, а чтение, которое возвращает 0 байт, имеет условное обнаружение конца файла.
Основное различие заключается в том, что внутри Windows текстовый конец маркера файла - это данные, которые могут встречаться внутри файла, а внутри Unix - отсутствие данных, которые не могут встречаться в файле. Конечно, Windows также поддерживает обычный конец файла (не более данных!) Для текста. Что усложняет вещи – Windows просто сложнее.
#include <iostream>
using namespace std;
int main()
{
char ch;
while(cin >> ch) {
cout << 0+ch << " '" << ch << "'" << endl;
}
}
Ответ 2
Вы не найдете ответа на свой вопрос в стандарте С++.
cin >> ch
будет "истинным" условием, если не существует условия конца файла или ошибки ввода. Как запускается условие конца файла, язык не указывается, и он может и будет варьироваться от одной операционной системы к другой и даже с параметрами конфигурации в той же ОС. (Например, Unix-подобные системы используют control-D по умолчанию, но это может быть изменено командой stty
.)
Windows использует Control-Z для запуска условия конца файла для потока ввода текста; это просто не так, как в начале строки.
Unix ведет себя по-другому; он использует Control-D (по умолчанию) в начале строки или два Control-Ds в середине строки.
Для Unix это применяется только при чтении с терминала; если вы читаете из файла, control-D - это еще один непечатаемый символ, и он не вызывает условие конца файла. Windows, похоже, распознает control-Z как триггер конца файла даже при чтении из файла диска.
Итог: разные операционные системы ведут себя по-разному, в основном по неясным историческим причинам. С++ предназначен для работы с любым из этих поведений, поэтому он не является специфическим для некоторых деталей.
Ответ 3
Это вызвано cin → ^ Z будет оцениваться как false.
Подробнее: cin.eof() вернет true, так что
while, которое неявно вызывает eof(), вернет false
и, следовательно, завершите цикл.
Если вы введете 12 ^ Z, eof() вернет false, поскольку он может анализировать
допустимое входное значение, поэтому он не остановит цикл.
Вам может быть интересно это также:
SO по семантике флагов