Herzlich Willkommen, lieber Gast!
  Sie befinden sich hier:

  Forum » FAQ Linux » Eingaben mit Timeout

Forum | Hilfe | Team | Links | Impressum | > Suche < | Mitglieder | Registrieren | Einloggen
  Quicklinks: MSDN-Online || STL || clib Reference Grundlagen || Literatur || E-Books || Zubehör || > F.A.Q. < || Downloads   

Autor Thread - Seiten: > 1 <
000
03.11.2003, 12:46 Uhr
virtual
Sexiest Bit alive
(Operator)


Manchmal will man, daß der Benutzer innerhalb einer vorgegebenen Zeit eine Eingabe macht. Das folgende Programm zeigt exemplarisch, wie es mit Hilfe von fgets realisierbar ist, mit ein wenig Geschick sollte man es auch auf andere StdIO funktionen (zB scanf) übertragen können.
Leider kann man nicht behaupten, daß dies immer funktioniert, weil es sehr von dem Bufferungsverhalten der darunterliegenden Datei abhängt: Ist stdin mit dem terminal verknüpft ("Normalfall"), sollte es mit fgets funktionieren, weil dann stdin meist Zeilegepuffert ist. Ansonsten wird man mehr in die Trickkiste greifen müssen und die ncurses Library und oder termios benutzen müssen.

C++:
#include <stdio.h>
#include <stdlib.h>
#include <sys/poll.h>
#include <errno.h>

/* fgets_with_timeout
* Diese routine macht das gleiche wie fgets, mit einem kleinen aber
* feinen unterschied: sie hat einen Timeout. Wenn der Benutzer nicht
* Innerhalb dieser Zeit seine Eingabe gemacht hat, kehrt die Routine
* zurück.
* Parameter und rückgabe wie bei fgets. millis gibt die Zeit in Milli-
* sekunden an, wielange auf eine Eingabe gewartet werden soll. Ist
* milli negativ, wird ewig gewartet (dann verhält sich die routine
* also genau wie fgets).
* Bei der Rückgabe wird errno auf ETIME gesetzt, wenn der Timeout
* erreicht wurde.
*/

char* fgets_with_timeout(
    char* buffer,
    int size,
    FILE* in,
    int millis)
{
    int ret;
    int h = fileno(in);
    struct pollfd poll_fd;

    /*
     * Prepare pool_fd;
     */

    poll_fd.fd = h;
    poll_fd.events = POLLIN;
    poll_fd.revents = 0;

    /*
     * Call poll on the handle
     */

    ret = poll(&poll_fd, 1, millis);
    if (1 == ret)
    {
        return fgets(buffer, size, in);
    }else if (0 == ret)
    {
        /* Timed out */
        errno = ETIME;
    }
    return NULL;
}

/* fgets_with_default
* Dies ist einfahc nur eine Erweiterung zu fgets_with_timeout:
* Wenn fgets_with_timeout NULL zurückgibt und der Benutzer keine eigene
* eingabe gemacht hat, wird die Default anwort def genommen. Der Rest ist
* genau wie oben.
*/

char* fgets_with_default(
    char* buffer,
    int size,
    FILE* in,
    const char* def,
    int millis)
{
    if (NULL == fgets_with_timeout(buffer, size, in, millis))
    {
        if (ETIME == errno && NULL != def)
        {
            strcpy(buffer, "");
            strncat(buffer, def, size);
            return buffer;
        }
        return NULL;
    }
    return buffer;
}


/*** DEMO *********************************************************************/


/* Kleines Demo der beiden Routinen oben:
* Generell schreibt das Demo in eine Datei den text, den der Benutzer eingeben
* soll. Nun kann es sein, daß die Datei bereits existiert. Daher fragt das
* Programm nach, ob die Datei überschrieben werden soll. Wird vom Benutzer
* Innerhaqlb von5 Sekunden keine Eingabe gemacht, bricht das Programm ab.
* Ebenso verändert das Programm nichts, wenn der Benutzer nicht innerhalb
* von 10 Sekunden etwas eingeben hat.
*/

#define DATEI "hallo.txt"


int main()
{
    char buffer[1000];
    FILE* file;
    int exists = 0;

    /*
     * Teste, ob Datei existiert
     */

    file = fopen(DATEI, "r");
    exists = NULL!=file;
    if (exists)
    {
        fclose(file);
    }

    /*
     * Abfrage, ob datei überschrieben werden soll
     */

    if (exists)
    {
        printf("Soll "DATEI" wirklich überschrieben werden (Abbruch nach 5 Sekunden)? ");
        fflush(stdout);

        if (NULL == fgets_with_default(buffer, sizeof(buffer), stdin, "N", 5000))
        {
            fprintf(stderr,
                    "\nAllgemeiner Dateifehler beim Lesen von stdin: %s (%d)\n",
                    strerror(errno),
                    errno);
            exit(EXIT_FAILURE);
        }
        if (*buffer=='n' || *buffer=='N')
        {
            printf("\nAbbruch durch benutzer!\n");
            exit(EXIT_FAILURE);
        }
    }

    /*
     * Eingabe des textes
     */

    printf("Welcher text soll in "DATEI" stehen? (Abbruch nach 10 Sekunden)? ");
    fflush(stdout);

    if (NULL == fgets_with_timeout(buffer, sizeof(buffer), stdin, 10000))
    {
        fprintf(stderr,
                "\nFehler beim Lesen von stdin oder keine Benutzereingabe\n");
        exit(EXIT_FAILURE);
    }

    /*
     * Erstelle Datei mit neuem Inhalt
     */

    file = fopen(DATEI, "w");
    if (NULL == file)
    {
        fprintf(stderr,
                "\nAllgemeiner Dateifehler beim Schreiben nach "DATEI": %s (%d)\n",
                strerror(errno),
                errno);
        exit(EXIT_FAILURE);
    }

    fprintf(file, "%s\n", buffer);
    fclose(file);
}


--
Gruß, virtual
Quote of the Month
Ich eß' nur was ein Gesicht hat (Creme 21)
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
Seiten: > 1 <     [ FAQ Linux ]  


ThWBoard 2.73 FloSoft-Edition
© by Paul Baecher & Felix Gonschorek (www.thwboard.de)

Anpassungen des Forums
© by Flo-Soft (www.flo-soft.de)

Sie sind Besucher: