2015-03-09 9 views
5

Ich möchte ein Timeout-Feature in C++ implementieren.Wie verwende ich einen Timer in C++, um Eingaben innerhalb einer bestimmten Zeit zu erzwingen?

Wenn die Benutzereingabe nicht der Wert innerhalb von 2 Sekunden dann das Programm die Time-out-Anweisung angezeigt werden muss und die Eingabe noch einmal fragen

EX (OUTPUT SCREEN):

Timer=0; 
Please enter the input:  //if input is not given within 2 seconds then 
Time-out: 2 seconds 
Timer again set to 0 
Please enter the input: //if input is not given within 2 seconds then 
Time-out: 2 seconds 
Timer again set to 0 
Please enter the input:22 
Data accepted 
Terminate the program` 

Code:

#include<iostream> 
#include<time.h> 
using namespace std; 
int main() 
{ 
    clock_t endwait; 
    endwait = 2000 ; 
    cout<<endwait; 
    while (clock() < endwait) 
    { 
     cout<<"Please enter the input:"; 
    } 
    return 0; 
} 

Ich habe an dem obigen Code gearbeitet. Dies geschieht jedoch nur während der Eingabe der WHILE-Schleife. Wie soll ich es so machen, dass ich die benötigte Leistung bekomme?

+0

Es gibt keinen Standard saubere Art und Weise Eingang für eine begrenzte Zeit nur zu akzeptieren, würden – chris

+0

Sie müssen den Funktionseingang einen Thread machen und verwenden [wait_for] (http: // en.cppreference.com/w/cpp/thread/future/wait_for) – NathanOliver

+0

@NathanOliver können Sie das ausarbeiten? – Walter

Antwort

4
#include <iostream> 
#include <thread> 
#include <chrono> 
#include <mutex> 
#include <condition_variable> 
using namespace std; 
condition_variable cv; 

int value; 

void read_value() { 
    cin >> value; 
    cv.notify_one(); 
} 

int main() 
{ 
    cout << "Please enter the input: "; 
    thread th(read_value); 

    mutex mtx; 
    unique_lock<mutex> lck(mtx); 
    while (cv.wait_for(lck, chrono::seconds(2)) == cv_status::timeout) 
    { 
     cout << "\nTime-Out: 2 second:"; 
     cout << "\nPlease enter the input:"; 
    } 
    cout << "You entered: " << value << '\n'; 

    th.join(); 

    return 0; 
} 

Ausgang:

Please enter the input: 
Time-Out: 2 second: 
Please enter the input: 
Time-Out: 2 second: 
Please enter the input:22 
You entered: 22 
+1

Während dies scheint zu funktionieren, ist dies nicht wirklich Time-out cin. Beispiel: Wenn ein Benutzer nach der Eingabe einen Wert eingeben soll, aber vor dem Timeout nicht die Eingabetaste gedrückt hat, sondern bei einer nachfolgenden Eingabeaufforderung, hat der Benutzer die Eingabetaste gedrückt. Alle Werte, die der Benutzer eingegeben hat, unabhängig davon, ob er die Taste Enter drückt oder nicht, würden an den Wert angehängt, da der Stream nie geleert wird. Möglicherweise möchten Sie Ihren Stream anhalten und neu starten oder den Eingabestream an einem bestimmten Punkt leeren. Netter Gebrauch von condition_variable! –

1

Ich fürchte, es ist nicht auf eine Standard-Art möglich, weil E/A-Operationen standardmäßig den aufrufenden Prozess blockieren, bis er abgeschlossen ist oder ein Fehler auftritt.
Sie könnten es umgehen, indem Sie einen Thread erstellen, der überprüft, ob die Eingabe abgeschlossen wurde und bei Bedarf schlafen gehen. Aber das ist nicht wirklich praktisch.

Das Problem liegt in der Abstraktion iostream/FILE s Sie geben: Sie Zugriff nicht auf die zugrunde liegende Quelle haben, die man das Betriebssystem „versteht“ so gut und deshalb in der Lage Sie diese Art von Funktionalität zu geben (nämlich E/A-Abfrage).

1

Ein separater Thread ist nicht genug, da die Konsolenlesefunktion nach dem Timeout noch läuft.

Auf POSIX können Sie einen Timer setzen, der ein Signal erzeugt und das Lesen mit -EINTR fehlschlägt.

Unter Windows können Sie Low-Level-Konsolen-E/A-Timeouts mit ReadConsoleInput und WaitForSingleObject implementieren ... aber dann müssen Sie Ihre eigene Zeilenpufferung durchführen.

wäre ein andere Idee ReadFile in OVERLAPPED-Modus zu verwenden und mit einem Timeout auf die Fertigstellung Ereignis warten, aber das für Konsolen nicht funktioniert, sehen lassen Using overlapped IO for console input?

Schließlich neue Windows-Versionen (Vista und höher) Sie überwinden das Problem "blockierendes Lesen wird nicht durch Zeitüberschreitung abgebrochen" unter Verwendung von CancelIoEx. Wenn Sie das aus einem separaten Thread aufrufen, wird ReadFile vorzeitig ausgelöst werden; Sie müssen die Zeilenpufferung nicht selbst implementieren.

0

Ich denke, es gibt keine Notwendigkeit (Multithreading oder Mutex) zu verwenden, um komplexen Code ist für diesen Zweck. Siehe Code unten:

#include <iostream> 
#include <time.h> 
#include <conio.h> 

using namespace std; 

int main() 
{ 
    int numInput; 

    clock_t start = clock(); 

    cout << "Timer: 2 sec"<<endl; 

    cout << "Please enter the input: "; 

    while (! _kbhit()) //Check for keyboard hit 
    { 
     //Check if 2 sec timer expired or not 
     if (((clock() - start)/ CLOCKS_PER_SEC) >= 2) 
     { 
      cout << "\nTimeout 2 sec . . ." << endl; 
      cout << "Please enter the input: "; 
      start = clock();       //Set new timer 
     } 
    } 

    //Get the input here 
    cin >> numInput; 

    cout << "Data accepted: " << numInput << endl; 

    _getch(); 

    return 0; 
} 
0

Ich habe kbhit() Funktion verwendet, um Ihr Problem zu lösen. Der Code ist wie folgt: -

#include <conio.h> 
    #include <iostream> 
    #include <windows.h> 

    using namespace std; 

    int main() 
    { 
     int i; 
     DWORD start_time, check_time; 
     start_time=GetTickCount(); 
     check_time=start_time+2000; 
     while(!kbhit()) 
     { 
      cout<<"Please enter the input:"<<endl; 
      while((check_time>GetTickCount())) 
      { 
       if (kbhit()) 
       { 
        i=getch(); 
        cout<<"Data accepted"<<endl; 
        return 0; 
       } 
      } 
      cout<<"Time-out: 2 seconds"<<endl; 
      cout<<"Timer again set to 0"<<endl; 
      start_time=GetTickCount(); 
      check_time=start_time+2000; 
     } 
    return 0; 

    }