Как читать из std::cin до конца потока?

Моя проблема в том, что я хочу прочитать ввод из std::cin, но не знаю, как долго он идет. Также я должен char и не могу использовать std::string. Есть два способа справиться с этим: а) Пользователь вводит текст, и когда он нажимает [ENTER], программа прекращает чтение. б) Пользователь перенаправляет std::cin в файл (например, .\a.oput < file), который может содержать несколько строк.

Редактировать: Только что заметил, что std::cin.eof() всегда имеет значение false, даже в случае чтения из файла.

Для а) я мог читать, пока не произойдет \n. Для б) Редактировать: Нет (я мог читать до тех пор, пока не произойдет std::cin.eof().) Но когда я не знаю, возникает ли у меня проблема а) или б), как можно ли прервать процесс чтения?

Это то, что у меня есть для а) ...

char buffer = ' ';
while(std::cin >> std::noskipws >> buffer && buffer != '\n')
{
    // do some stuff with buffer
}

... и б)

char buffer = ' ';
while(std::cin >> std::noskipws >> buffer)
{
    // do some stuff with buffer
}

Также я знаю, что есть std::cin.tellg(), чтобы получить текущую позицию в потоке.

Редактировать: Похоже, что в случае с файлом входные потоки прерываются таким же образом, как std::cin >> std::noskipws >> buffer получает false. Что код выше делает для a):

  • Он ждет, пока пользователь сделает ввод и нажмет [ENTER]
  • Затем он перебирает каждый символ, введенный пользователем в последней строке.
  • Затем он снова ждет, пока пользователь сделает ввод, и нажмет [ENTER].
  • Бесконечный цикл ожидания-обработки

Итак, как мне это сделать?


person Lukas    schedule 22.11.2011    source источник
comment
Расскажите, почему вы не можете использовать std::string. Возможно, мы сможем помочь вам и с этой проблемой.   -  person Robᵩ    schedule 23.11.2011
comment
Для нестандартного кода вы можете использовать kbhit() в conio.h   -  person Mooing Duck    schedule 23.11.2011
comment
@Rob Это из упражнений, и мы еще не «знаем» std::string. Мы также не можем использовать нестандартный код. То, о чем я спрашиваю, не требуется напрямую в упражнениях, но мне просто любопытно...   -  person Lukas    schedule 23.11.2011
comment
Я настоятельно рекомендую просто изменить дизайн из этого требования. Интерфейс ввода программы должен быть последовательным. Если это одна строка, она должна быть одной строкой. Если он прочитан до конца файла, он должен быть прочитан до конца файла. Для непереносимого кода есть isatty, но лучше было бы установить флаг опции, чтобы установить режим, если это абсолютно необходимо.   -  person David Schwartz    schedule 23.11.2011
comment
почему бы не объединить два условия, как в while(std::cin>>std::noskipws>>buffer && !std::cin.eof() && buffer != '\n') ?   -  person Walter    schedule 23.11.2011
comment
@Walter Потому что я не смогу читать файлы с несколькими строками ...   -  person Lukas    schedule 23.11.2011
comment
этот код кажется очень опасным, поскольку вы пытаетесь прочитать (в некоторых случаях) несколько символов в одном символе (переполнение буфера)   -  person Sim    schedule 23.11.2011
comment
@Sim Да, но это только похоже. Потому что происходит то, что он перебирает весь ввод и помещает один символ в буфер за другим. Таким образом, не будет нескольких символов, сжатых в один символ.   -  person Lukas    schedule 23.11.2011


Ответы (2)


Вы можете потребовать, чтобы ввод всегда заканчивал EOF (имеется в виду из командной строки, требующей нажатия ^D), а затем использовать процесс для b, как всегда. Это также позволит включить многострочный ввод из cmdline.

person DanZimm    schedule 22.11.2011
comment
Я мог бы потребовать этого, но что, если я не могу? (Что такое нажатие клавиши ^D в оболочке linux/windows?) - person Lukas; 23.11.2011

Вы можете использовать (старую) функцию getline, которая принимает указатель на массив символов и может использовать разделитель. Но вы не сможете гарантировать, что в каждом случае он будет читаться в eof (так как буфер символов может быть слишком мал), но использовать char-массив и не обращать внимания на его размер очень опасно (и из вопрос безопасности катастрофичен), так как это может привести к переполнениям буфера, которые можно легко использовать .

Этот код должен позволить вам извлекать строку за строкой из ввода:

char buffer[256];
while(getline(buffer,256,'\n')) { //get a line
   /* do something with the line */
}

Это для чтения максимального количества символов:

char buffer[256];
while(getline(buffer,256)) {//get a maximum amount out of the input
   /* do something with the line */
}
person Sim    schedule 22.11.2011