неблокирующий std :: getline, выход, если вход отсутствует

В настоящее время у меня есть программа, которая читает со стандартного ввода, изредка программа должна просто продолжать работать, если вход не выполняется, обычно это тестовый скрипт, так что «нет».

program -v1 -v2 -v3 output

v1 – v3 – аргументы командной строки, соответственно

В основном программа выплевывает аргументы командной строки и их соответствующее значение программе, если не указан «ввод», а затем должен выйти.

Однако на данный момент, если дать ему пустой тестовый файл или просто запустить без нажатия enter после запуска его блоков на std :: getline, я использую для ввода команд.

 while(std::getline(std::cin,foo) {do stuff} в while(std::getline(std::cin,foo) {do stuff} 

где foo – строка.

Как мне заставить его просто запускать и do stuff хотя бы один раз, а затем выходить в случае отсутствия ввода? В случае ввода данные do stuff один раз для каждой строки стандартного ввода.

Будет ли работать работа с переходом на цикл do-while, с предварительным циклом проверки того, есть ли у него какой-либо вход?

Что-то вроде

 if cin empty set flag do {do stuff check flag} while(getline) 

или не блокирует io невозможно в c ++?

Этот вопрос, кажется, повторяется снова и снова, но я не мог найти окончательного ответа или даже ответа, который был несовместимым с платформой (эта программа носит академический характер, закодирована на windowsх и протестирована в Unix).

Использование std :: cin асинхронно может быть единственным способом сделать эту работу, поскольку iostream не предназначен для неблокирующего поведения. Вот пример:

Асинхронный пример 1 Async Пример 2 (печать пробела каждые 1/10 секунды при одновременном приеме ввода CLI)

Код прокомментирован, поэтому его должно легко понять. Это streamобезопасный class, который позволяет асинхронно получать строку, используя std :: cin.

Очень прост в использовании для асинхронных целей CLI getline с 0% загрузки процессора на моем компьютере. Он отлично работает в Windows 10 в режиме Visual Studio 2015 c ++ Win32 Console Debug и Release. Если это не работает в вашей ОС или среде, это слишком плохо.

 #include  #include  #include  #include  #include  using namespace std; //This code works perfectly well on Windows 10 in Visual Studio 2015 c++ Win32 Console Debug and Release mode. //If it doesn't work in your OS or environment, that's too bad; guess you'll have to fix it. :( //You are free to use this code however you please, with one exception: no plagiarism! //(You can include this in a much bigger project without giving any credit.) //Created 02-15-17 by Andrew Davis, the creator of a new programming language called Basik. //If you like this code, please check it out, thanks! http://thecodingwebsite.com class AsyncGetline { public: //AsyncGetline is a class that allows for asynchronous CLI getline-style input //(with 0% CPU usage!), which normal iostream usage does not easily allow. AsyncGetline() { input = ""; sendOverNextLine = true; continueGettingInput = true; //Start a new detached thread to call getline over and over again and retrieve new input to be processed. thread([&]() { //Non-synchronized string of input for the getline calls. string synchronousInput; char nextCharacter; //Get the asynchronous input lines. do { //Start with an empty line. synchronousInput = ""; //Process input characters one at a time asynchronously, until a new line character is reached. while (continueGettingInput) { //See if there are any input characters available (asynchronously). while (cin.peek() == EOF) { //Ensure that the other thread is always yielded to when necessary. Don't sleep here; //only yield, in order to ensure that processing will be as responsive as possible. this_thread::yield(); } //Get the next character that is known to be available. nextCharacter = cin.get(); //Check for new line character. if (nextCharacter == '\n') { break; } //Since this character is not a new line character, add it to the synchronousInput string. synchronousInput += nextCharacter; } //Be ready to stop retrieving input at any moment. if (!continueGettingInput) { break; } //Wait until the processing thread is ready to process the next line. while (continueGettingInput && !sendOverNextLine) { //Ensure that the other thread is always yielded to when necessary. Don't sleep here; //only yield, in order to ensure that the processing will be as responsive as possible. this_thread::yield(); } //Be ready to stop retrieving input at any moment. if (!continueGettingInput) { break; } //Safely send the next line of input over for usage in the processing thread. inputLock.lock(); input = synchronousInput; inputLock.unlock(); //Signal that although this thread will read in the next line, //it will not send it over until the processing thread is ready. sendOverNextLine = false; } while (continueGettingInput && input != "exit"); }).detach(); } //Stop getting asynchronous CLI input. ~AsyncGetline() { //Stop the getline thread. continueGettingInput = false; } //Get the next line of input if there is any; if not, sleep for a millisecond and return an empty string. string GetLine() { //See if the next line of input, if any, is ready to be processed. if (sendOverNextLine) { //Don't consume the CPU while waiting for input; this_thread::yield() //would still consume a lot of CPU, so sleep must be used. this_thread::sleep_for(chrono::milliseconds(1)); return ""; } else { //Retrieve the next line of input from the getline thread and store it for return. inputLock.lock(); string returnInput = input; inputLock.unlock(); //Also, signal to the getline thread that it can continue //sending over the next line of input, if available. sendOverNextLine = true; return returnInput; } } private: //Cross-thread-safe boolean to tell the getline thread to stop when AsyncGetline is deconstructed. atomic continueGettingInput; //Cross-thread-safe boolean to denote when the processing thread is ready for the next input line. //This exists to prevent any previous line(s) from being overwritten by new input lines without //using a queue by only processing further getline input when the processing thread is ready. atomic sendOverNextLine; //Mutex lock to ensure only one thread (processing vs. getline) is accessing the input string at a time. mutex inputLock; //string utilized safely by each thread due to the inputLock mutex. string input; }; void main() { AsyncGetline ag; string input; while (true) { //Asynchronously get the next line of input, if any. This function automagically //sleeps a millisecond if there is no getline input. input = ag.GetLine(); //Check to see if there was any input. if (!input.empty()) { //Print out the user's input to demonstrate it being processed. cout << "{" << input << "}\n"; //Check for the exit condition. if (input == "exit") { break; } } //Print out a space character every so often to demonstrate asynchronicity. //cout << " "; //this_thread::sleep_for(chrono::milliseconds(100)); } cout << "\n\n"; system("pause"); } 

Вы можете использовать cin.peek чтобы проверить, есть ли что-нибудь для чтения, а затем вызвать getline если есть. Однако нет такой вещи, как неблокирующий getline.