2017-01-09 3 views
1

Есть ли способ вызвать getline() и, если нет ввода данных, а не блокировать и ждать?Как использовать getline без блокировки ввода?

У меня есть следующий код:

while(true){ 
    if(recv(sd, tBuffer, sizeof(tBuffer), MSG_PEEK | MSG_DONTWAIT) > 0) break; 
    getline(cin,send); 
} 

Я хочу ждать входа, но если я получаю некоторые данные в sd гнездо, я хочу прекратить ожидание данных и выхода из while. Мой код прямо сейчас, просто на первой итерации на getline(). Я хочу оценить getline(), а если нет ввода, вернитесь на if.

Возможно ли это?

PS: Я пробовал с cin.peek(), но это блокирует для ввода тоже.

+1

Чтобы ответить на заданный вопрос: да, это возможно. По крайней мере, в Linux. –

+0

Я использую Ubuntu .. Как это возможно? Можете ли вы дать мне несколько ссылок или объяснить мне? – Darius

+1

Короткий ответ: 1) Используйте низкоуровневый ввод-вывод, а не 'getline'. 2) Используйте 'select'. –

ответ

3

Вы должны быть в состоянии сделать это, установив неблокируемому режим на стандартный ввод, дескриптор файла 0:

int flags = fcntl(0, F_GETFL, 0); 
fcntl(0, F_SETFL, flags | O_NONBLOCK); 

Теперь, если есть сигнал отсутствует в наличии, лежащий в основе read() системный вызов возвращает 0, и std::cin будет думать, что это конец файла, и установить eof() на std::cin.

Если вы хотите снова прочитать стандартный ввод, просто clear() состояние потока.

Единственным осложняющим фактором здесь является то, что это затрудняет обнаружение реального состояния конца файла на std::cin. Не большая проблема, когда стандартный ввод является интерактивным терминалом; но если стандартный ввод может быть файлом, это будет проблемой.

В этом случае, ваш единственный реальный вариант отказаться от std::cin полностью, поставить неблокируемому режим на файловый дескриптор 0, poll() или select() его, чтобы определить, когда есть что-то читать, то read() это.

Хотя вы также можете использовать poll() или select() с std::cin, это будет получить сложнее, так как вам нужно будет явно проверить, есть ли что-нибудь уже в буфере std::cin «s streambuf, потому что это, очевидно, выгрузить любой вид poll() или select() проверка; но, пытаясь что-то прочитать с std::cin, вы по-прежнему рискуете прочитать буферизованные данные, а затем попытаетесь выполнить read() из базового файлового дескриптора, который теперь находится в режиме без блокировки, что приводит к поддельному состоянию конца файла.

Подводя итог: вам нужно потратить некоторое дополнительное время на чтение и понимание того, как работают потоки файлов и потоковые буферы; и как файловые дескрипторы действительно работают, и как работает неблокирующий режим; чтобы выяснить правильную логику, которую вам нужно будет использовать.

Да, и если вы настаиваете на идя нелипкий маршрут с std::cin и getline(), вы не будете иметь простой способ определить, является ли строка, возвращаемая getline() заканчивается, потому что getline() фактически читать строку из стандартного ввода, или достигли преждевременного поддельного состояния файла, а не вся строка ввода действительно была прочитана.

Итак, с неблокирующим режимом и std::cin вы будете вынуждены использовать read(), а не getline().