2013-11-03 4 views
0

Я бы хотел, чтобы моя программа читала от stdin до EOF, печатала все входные данные и повторяла. Я попытался очищая состояние EOF из стандартного ввода следующим образом:Повторное чтение в EOF от stdin

#include <string> 
#include <iostream> 
#include <iterator> 

using namespace std; 

int main() { 

    cin >> noskipws; 

    while (1) { 

    printf("Begin"); 
    istream_iterator<char> iterator(cin); 
    istream_iterator<char> end; 
    string input(iterator, end); 
    cout << input << endl; 
    cin.clear(); 

    } 

} 

После того, как первый вход принимается и печатается, однако, программа просто бесконечно печатает «Begin», не дожидаясь дальнейшего ввода.

+1

Как продолжить чтение EOF? Когда данных больше нет, * данных больше нет. * –

+0

@JonathonReinhart EOF не обязательно означает, что больше никогда не будет данных, только чтобы достигнут конец файла. Терминал может поддерживать ввод данных после того, как пользователь входит в EOF escape, и файл может иметь больше данных, записанных на него. – hobbs

+1

@hobbs Я это понимаю. Я действительно рассмотрел то, о чем вы упоминали, но не мог придумать какую-либо стандартную программу UNIX-y, которая продолжает читать, после того, как EOF получит от stdin. Если я нажму Ctrl + D, я ожидаю, что он закончит. –

ответ

1

подход вы принимаете не будет работать - когда «КИН» дает конечным из-файла в контексте, который вы используете, то CIN закрыт.

Для вашей заявленной цели «чтения текста до EOF, а затем делать это снова», извините за пропуск нюанс этого раньше, но если вы клонировать STDIN дескриптор файла, а затем использовать клон, вы можете продолжить чтение из этих дополнительных файловых дескрипторов.

Клонирование iostreams непросто. См. How to construct a c++ fstream from a POSIX file descriptor?

Это немного c-like, но этот код сбрасывает одну копию stdin до тех пор, пока этот stdin не закрывается, после чего он создаст новую копию и слейте ее и снова.

#include <iostream> 
#include <string> 

void getInput(std::string& input) 
{ 
    char buffer[4096]; 
    int newIn = dup(STDIN_FILENO); 
    int result = EAGAIN; 
    input = ""; 
    do { 
     buffer[0] = 0; 
     result = read(newIn, buffer, sizeof(buffer)); 
     if (result > 0) 
      input += buffer; 
    } while (result >= sizeof(buffer)); 
    close(newIn); 

    return input; 
} 

int main(int argc, const char* argv[]) 
{ 
    std::string input; 
    for (;;) { 
     getInput(input); 
     if (input.empty()) 
      break; 
     std::cout << "8x --- start --- x8\n" << input.c_str() << "\n8x --- end --- x8\n\n"; 
    } 
} 
0

Это потому, что у вас есть printf («begin»); внутри вашей петли, чтобы вы собирались распечатывать ее каждый раз по кругу.

Цикл не будет ждать ввода, поэтому каждый раз, когда он считывает данные из stdin - если там ничего нет, он немедленно получает EOF и поэтому продолжает цикл до тех пор, пока не будут представлены некоторые данные.

Сообщите мне, если это не имеет смысла - или если я полностью ошибаюсь.

например:

#include <string> 
#include <iostream> 
#include <iterator> 

using namespace std; 

int main() { 

    cin >> noskipws; 

    printf("Begin"); 

    while (1) { 

    istream_iterator<char> iterator(cin); 
    istream_iterator<char> end; 
    string input(iterator, end); 
    cout << input << endl; 
    cin.clear(); 

    } 

} 
+0

При первом запуске этой программы тело цикла ожидает ввода. Я бы хотел, чтобы он подождал на каждой итерации. Перемещение оператора печати за пределы цикла не помогает. По-прежнему сохраняется запись в cout, которая печатает бесконечное количество пустых строк для консоли и явно указывает, что цикл не ждет. –

+0

, если вы хотите каждый раз брать строку (например, задавать вопрос пользователю, и они набирают ответ, а затем нажимают ввод), возможно, использование чего-то типа getline() может помочь вам немного. http://www.cplusplus.com/reference/string/string/getline/ –

+0

Я ожидаю, что ввод будет содержать произвольное количество строк. –

Смежные вопросы