int waffelloop(FILE*)

Heute möchten wir uns die Waffel-Schleife von waffel2010 ansehen.

Zunächst noch einmal die Signatur:


00022: int waffelloop(FILE*);

waffelloop erhält also einen FILE-Pointer und gibt einen int zurück. Als FILE-Pointer übergeben wir zunächst eine geöffnete Datei:


00063:         waffelloop(infile);

In dieser ist die bisherige Geschichte gespeichert, damit wir das Programm unterbrechen und später neu starten können. Anschließend gibt die main-Funktion ein bisschen Text aus und startet die waffelloop mit einem Zeiger auf stdin: Nun werden die Eingaben von der Tastatur (alternativ aus einer Pipe) gelesen.


00071:     err = waffelloop(stdin);

Gehen wir doch einmal die Implementation der waffelloop durch. Zunächst deklarieren wir Variablen und allokieren Speicher für einen Eingabe-Puffer:


00133: int waffelloop(FILE* infile)
00134: {
00135:     char* buffer;
00136:     const int buffer_size = 32;
00137:     FILE* outfile = NULL;
00138: 
00139:     buffer = (char*) malloc(buffer_size * sizeof(char));
00140:     if (buffer == NULL)
00141:         return __LINE__;

Wenn die Eingabe nicht aus der der waffel.input stammt (als FILE* also stdin übergeben wurde), öffnen wir diese Datei zum Anhängen, um die Eingaben zu speichern. Kann sie nicht geöffnet werden, geben die Zeilennummer __LINE__ (gcc-Makro) als Fehler zurück:


00143:     if (infile == stdin)
00144:     {
00145:         outfile = fopen("waffel.input", "a");
00146:         if (outfile == NULL)
00147:             return __LINE__;
00148:     }

Nun beginnt die Endlos-Schleife while(1). Wir deklarieren einen Zähler int waffel_count=0 und einen Zeitstempel time_t when=0; ist die Eingabe stdin, geben wir einen Prompt auf stdout aus. Anschließend lesen wir eine Zeile in den Puffer.


00150:     while (1)
00151:     {
00152:         int waffel_count = 0;
00153:         time_t when=0;
00154: 
00155:         if (infile == stdin)
00156:             printf("Waffel $ ");
00157:         fflush(stdout);
00158:         if (fgets(buffer, buffer_size, infile) == NULL)
00159:             break;

Am Dateiende schlägt fgets fehl, wir verlassen die Schleife mit einem break.

Nun ein fieser Hack: Hat der Nutzer nur Enter gedrückt, schreiben wir 1\n in den Puffer:


00161:         if (buffer[0] == '\n')
00162:         {
00163:             buffer[0] = '1';
00164:             buffer[1] = '\n';
00165:         }

Fallunterscheidung zur Behandlung der Eingabe: lesen wir aus der waffel.input, bekommen wir die Zahl der verkauften Waffeln und den Zeitstempel.


00166:         if (infile != stdin)
00167:         {
00168:             int when_int;
00169:             sscanf(buffer, "%d %d", &waffel_count, &when_int);
00170:             when = when_int;
00171:         }

Im anderen Fall müssen wir die Benutzer-Eingabe verarbeiten. Im einfachsten Fall steht in buffer eine Zahl, die wir mittels sscanf in die Variable waffel_count schreiben können; den Zeitstempel bekommen wir von time(0):


00172:         else
00173:         {
00174:             sscanf(buffer, "%d", &waffel_count);
00175:             when = time(0);
00176:             fprintf(outfile, "%3d %d\n", waffel_count, (int)when);
00177:             fflush(outfile);
00178:         }

Hat sscanf jedoch eine 0 gelesen, vergleichen wir das erste Zeichen, buffer[0], mit den erlaubten Befehlen, und springen in die entsprechenden Funktionen (oder verlassen die while(1)-Schleife):


00180:         if (waffel_count == 0)
00181:         {
00182:             if (buffer[0] == 'x' || buffer[0] == 'X')
00183:                 break;
00184:             if (buffer[0] == 'a' || buffer[0] == 'A')
00185:                 start_alsamixer();
00186:             if (buffer[0] == 'h' || buffer[0] == 'H')
00187:                 print_help();
00188:             if (buffer[0] == '?')
00189:                 print_help();
00190:             if (buffer[0] == 's' || buffer[0] == 'S')
00191:                 output_uptime();
00192:             if (buffer[0] == 'l' || buffer[0] == 'L')
00193:                 output_last_waffel();
00194:             if (buffer[0] == 'n' || buffer[0] == 'N')
00195:                 blubber = system("mocp --next");
00196:             if (buffer[0] == 'p' || buffer[0] == 'P')
00197:                 show_plot();
00198:             if (buffer[0] == 't' || buffer[0] == 'T')
00199:                 print_datetime();
00200:         }

Ansonsten wurde eine Zahl gelesen, der Waffel-Zähler entsprechend geändert und der Eintrag in die Datei waffel.input geschrieben:


00201:         else
00202:         {
00203:             save_to_history(waffel_count, when);
00204:             if (infile == stdin)
00205:             {
00206:                 if (waffel_count > 0)
00207:                     alert(waffel_count);
00208:                 printf("\n");
00209:             }
00210:         }

Nach dem Schleifenende schließen wir outfile und geben zurück.


00211:     }
00212: 
00213:     if (infile == stdin)
00214:         fclose(outfile);
00215:     
00216:     return 0;
00217: }

Anmerkungen:

  • Für nächstes Jahr wird das Programm auf die readline-Bibliothek vorbereitet; dann kann man nämlich die Eingabe löschen.
  • Eine falsche Waffel-Zahl kann durch Eingabe einer negativen Zahl korrigiert werden.

Kategorie: Allgemein, Linux Kommentare deaktiviert für int waffelloop(FILE*)

Kommentarfunktion ist deaktiviert.

Zur Werkzeugleiste springen