Kapitel neun - Benutzereingabe

Eingaben des Benutzers lesen und verarbeiten

Im vorherigen Kapitel haben wir uns mit dem Drucken der Programmausgabe auf dem Terminal befasst. Um jedoch mit dem Benutzer interagieren zu können, muss dies in beide Richtungen erfolgen. In diesem Kapitel wird erläutert, wie wir Eingaben lesen und interpretieren können, die der Benutzer in das Terminal eingibt. Wir haben gesehen, dass die printf-Funktion in den vorherigen Kapiteln häufig verwendet wurde. Dies ist die Standardmethode zum Schreiben von formatiertem Text in die Konsole, die Befehlszeile, über die Sie das Programm ausführen. Aber was ist, wenn Sie Eingaben vom Benutzer erhalten möchten? Wie lesen wir, was der Benutzer in die Konsole eingibt?

In den letzten Kapiteln haben wir uns die Funktion sscanf angesehen, die Werte aus einer Zeichenfolge liest. Es gibt eine äquivalente Funktion namens scanf, die Werte direkt von der Konsole liest, wie im folgenden Beispiel:

#include <stdio.h> void main (void) { char input[256]; int age; printf ("Wie ist Dein Name, User?\n"); scanf ("%s", input); printf ("Hallo, %s. Wie alt bist Du?\n", input); scanf ("%d", &age); printf ("Na gut, %s, Du siehst jung aus, für %d...\n", input, age); }

scanf funktioniert genau wie sscanf, hat jedoch ein Argument weniger, da es eher von der Konsole als von einer Zeichenfolge liest.

Dies ist jedoch nicht der beste Weg, um Konsoleneingaben zu erhalten. Es funktioniert nur dann wirklich, wenn Sie einen Benutzer haben, der genau das eingibt, was Sie erwarten. Leider neigen Benutzer dazu, Dinge einzugeben, die Sie nicht erwarten, und scanf kommt damit nicht gut zurecht. Wenn der Benutzer im obigen Code beispielsweise 257 Zeichen eingibt, wenn er nach seinem Namen gefragt wird, wird der für die Eingabezeichenfolge zugewiesene Speicherplatz überlaufen, und es können eigenartige Dinge passieren …

Ein besserer Weg

Ein besserer Ansatz besteht darin, jede Zeile zu lesen, die der Benutzer in eine Pufferzeichenfolge eingibt, und dann mit sscanf Werte aus dieser Zeichenfolge zu lesen. Die C-Libaryfunktion fgets ist hierfür hilfreich. Schauen Sie sich dieses Beispiel an:

#include <stdio.h> void main (void) { char input[256], name[256]; int age; printf ("Wie ist Dein Name, User?\n"); fgets (input, 256, stdin); sscanf (input, "%s", name); printf ("Hallo, %s. Wie alt bist Du?\n", name); while (1) { fgets (input, 256, stdin); if (sscanf (input, "%d", &age) == 1) break; printf ("Das ist kein Alter - versuche es nochmal!\n"); } printf ("Na gut, %s, Du siehst jung aus, für %d...\n", name, age); }

fgets nimmt drei Argumente an. Der erste ist der Puffer, in dem die Eingabe gespeichert werden soll. Die zweite ist die maximale Anzahl von Bytes, die in diesen Puffer geschrieben werden. Dies ist nützlich, um die oben erwähnte Überlaufsituation zu verhindern. Schließlich braucht es ein Argument, das angibt, woher es lesen soll. In diesem Fall ist dies auf stdin (kurz für „standard input“) eingestellt, wodurch es angewiesen wird, von der Konsole zu lesen.

[STDIN UND STDOUT] Wir sprechen in diesem Artikel über stdin, den Stream „standard input“, was der Benutzer an der Konsole eingibt. Manchmal werden Verweise auf stdout angezeigt, bei dem es sich um den Stream „standard output“ handelt. Wie zu erwarten, handelt es sich hierbei um eine Ausgabe, die auf der Konsole gedruckt wird, normalerweise über printf.

Jedes Mal, wenn wir den Benutzer um Eingabe bitten, lesen wir mit fgets bis zu 256 Zeichen, was auch immer sie eingeben (bis zu dem Punkt, an dem sie die Eingabetaste drücken), und interpretieren sie dann mit sscanf. Wenn Sie nach dem Alter des Benutzers fragen, verwenden wir außerdem den von sscanf zurückgegebenen Wert (beschrieben im vorherigen Kapitel), um zu überprüfen, ob der Benutzer das eingegeben hat, was Sie erwarten, und führen eine Schleife durch, bis er eine gültige Antwort gibt. Sie können diese Methode verwenden, um so ziemlich alles zu interpretieren, was ein Benutzer eingibt, und um alle Fälle sicher zu behandeln, in denen er etwas Unerwartetes eingibt!

Parameter lesen

Sie können Ihr Programm auch auf andere Weise eingeben, indem Sie es als Parameter angeben, wenn Sie das Programm über die Befehlszeile starten. An dieser Stelle muss ich zugeben, dass ich in den letzten 8 Kapiteln nicht ganz ehrlich war. Ich habe immer die Definition der Hauptfunktion gezeigt als

void main (void)

Dies funktioniert, wie Sie gesehen haben. Das ist jedoch nicht unbedingt korrekt. Die strenge Definition von main sieht folgendermaßen aus:

int main (int argc, char *argv[])

Aber seien wir ehrlich: wenn ich Ihnen das in Kapitel 1 gezeigt hätte wären sie davongelaufen, nicht wahr? Was bedeutet das alles?

Zunächst können wir sehen, dass main eine Ganzzahl zurückgibt. Dies ist ein Erfolgs- oder Fehlercode, den einige Betriebssysteme zur Verarbeitung in einem Shell-Skript oder dergleichen verwenden können. Wenn ein Programm erfolgreich ist, gibt main normalerweise 0 zurück, und wenn es fehlschlägt, gibt es einen Fehlercode ungleich Null zurück. Für Programme, die alleine laufen, brauchen Sie sich wirklich keine Sorgen zu machen!

Was nützlicher ist, sind die beiden anderen Argumente. argc ist eine Ganzzahl, und dies ist die Anzahl der Parameter, die beim Starten des Programms in der Befehlszeile angegeben wurden. Seltsamerweise enthält die Nummer den Programmnamen selbst, sodass dieser Wert immer 1 oder mehr beträgt. Wenn Parameter angegeben wurden, sind es 2 oder mehr.

char * argv []; das ist doch verwirrend, oder? Dies ist eigentlich eine Zusammenstellung einiger Dinge, die wir bereits gesehen haben. Da ist ein * drin, also ein Zeiger. Der Typ ist char, also sind Zeichen darin und es gibt eckige Klammern, also ist es ein Array.

Dies ist eigentlich ein Array von Zeigern auf Zeichen. Jedes Element des Arrays ist eine Zeichenfolge, und jede Zeichenfolge ist einer der Parameter, die dem Programm zur Verfügung gestellt werden.

In der Praxis ist es wahrscheinlich einfacher zu verstehen:

#include <stdio.h> int main (int argc, char *argv[]) { int param = 0; while (param < argc) { printf ("Parameter %d ist %s\n", param, argv[param]); param++; } return 0; }

Oben: Die Argumente argc und argv für die Hauptfunktion können verwendet werden, um auf Parameter zuzugreifen, die in der Befehlszeile eingegeben werden, wenn das Programm ausgeführt wird.

Versuchen Sie, dies wie zuvor auszuführen, indem Sie einfach den Namen eingeben. Versuchen Sie dann, andere Dinge nach dem Namen in der Befehlszeile einzugeben, und sehen Sie, was das Programm druckt.

pi@raspberry:~ $ ./ein
Parameter 0 ist ./ein

oder

pi@raspberry:~ $ ./ein Das ist ein Test
Parameter 0 ist ./ein
Parameter 1 ist Das
Parameter 2 ist ist
Parameter 3 ist ein
Parameter 4 ist Test
pi@raspberry:~ $

[DIE RICHTIGE NUMMER WÄHLEN] Denken Sie daran, dass das erste Element im argv-Array - argv [0] - der Name des Programms selbst ist und nicht der erste Parameter. Die eigentlichen Parameter beginnen bei argv [1].

Hier ist ein Beispiel eines (sehr) einfachen Rechners, der mit Programmparametern geschrieben wurde:

#include <stdio.h> int main (int argc, char *argv[]) { int arg1, arg2; if (argc == 4) { sscanf (argv[1], "%d", &arg1); sscanf (argv[3], "%d", &arg2); if (*argv[2] == '+') printf ("%d\n", arg1 + arg2); if (*argv[2] == '-') printf ("%d\n", arg1 - arg2); if (*argv[2] == 'x') printf ("%d\n", arg1 * arg2); if (*argv[2] == '/') printf ("%d\n", arg1 / arg2); } return 0; }

Beachten Sie, dass wir *argv[2] verwenden, um das erste Zeichen des zweiten Parameters zu erhalten. Dies sollte immer nur ein einzelnes Zeichen sein. Da jedoch jedes der Argumente eine Zeichenfolge sein kann, ist argv[2] (ohne Sternchen) ein Pointer auf ein Zeichen und nicht auf das einzelne Zeichen, das für einen Vergleich mit == erforderlich ist.

[RÜCKGABEWERTE PRÜFEN] Unter Linux wird der Rückgabewert eines Programms nicht angezeigt, sondern gespeichert und kann über die Befehlszeile gelesen werden. Wenn Sie echo $? unmittelbar nach dem Ausführen eines Programms eingeben wird der Wert angezeigt, den das Programm zurückgegeben hat. Rückgabewerte sind hauptsächlich nützlich, wenn Sie Programme aus Skripten aufrufen.

Stellen Sie sicher, dass Sie die Argumente vom Operator durch Leerzeichen trennen, damit sie als separate Parameter identifiziert werden. <Progname> 2 + 2 statt <Progname> 2+2

pi@raspberry:~ $ ./calc 2 + 3
5
pi@raspberry:~ $

Oben: Der Rechner liest die beiden Werte und den Operator aus dem argv-Array und druckt das Ergebnis

Zurück zum Inhalt Vorige Seite Nächste Seite