Jedem Programm, das du aus einem Terminal startest, können Argumente übergeben werden: gcc -Wall hello.c -o hello übergibt vier davon. Deine eigenen C-Programme lesen ihre über zwei Parameter von main, und das ist der ganze Mechanismus - kein Bibliotheksaufruf, keine Einrichtung.
Die Signatur
Bisher hat jedes Beispiel in dieser Dokumentation int main(void) verwendet. Die andere Standardform nimmt die Kommandozeile entgegen:
int main(int argc, char *argv[]) {
/* ... */
}
argc(„argument count") ist die Anzahl der Argumente, einschließlich des Programmnamens.argv(„argument vector") ist ein Array von Zeichenketten.char *argv[]bedeutet „Array von Zeigern auf char", also ein Array von C-Zeichenketten.
char **argv ist eine gleichwertige Schreibweise, die du genauso oft sehen wirst; Array-Parameter zerfallen zu Zeigern, die beiden deklarieren also dasselbe.
Benutze das Args-Feld des Editors, um Argumente anzugeben (jedes Feld ist ein Argument), und drücke dann Run. Probiere drei Felder: hallo, welt, 42.
Der Aufbau
./greet Ada Lovelace auszuführen ergibt:
| Index | Wert | |
|---|---|---|
argv[0] | "./greet" | der Programmname wie aufgerufen |
argv[1] | "Ada" | erstes echtes Argument |
argv[2] | "Lovelace" | zweites echtes Argument |
argv[3] | NULL | der Abschluss |
argc | 3 | Anzahl einschließlich argv[0] |
Vier Tatsachen, die man sich merken sollte:
argcist in der Praxis mindestens 1, weilargv[0]der Programmname ist. Echte Argumente beginnen bei Index 1, weshalb Schleifen über sie beii = 1starten.- Alles ist eine Zeichenkette.
./prog 42gibt dir"42", die beiden Zeichen, nie die Zahl 42. Das Umwandeln ist deine Aufgabe. argv[argc]istNULL. Vom Standard garantiert, du kannst das Array also auch ohneargcdurchlaufen:for (char **p = argv + 1; *p != NULL; p++).- Die Shell teilt die Wörter auf, nicht dein Programm.
./prog "Ada Lovelace"ist ein Argument; die Anführungszeichen verbraucht die Shell und sie erreichenargvnie.
Prüfen, bevor du liest
Ein nicht übergebenes Argument ist keine leere Zeichenkette - es ist Speicher, den du nicht anfassen darfst. Prüfe immer zuerst argc:
Zwei Konventionen in diesem winzigen Programm, beide unter Unix-Werkzeugen Standard:
- Die Benutzungsmeldung geht nach
stderr, nicht nachstdout, damit sie eine Ausgabe, die irgendwohin weitergeleitet wird, nicht verunreinigt. - Ein Rückgabewert ungleich null aus
mainsignalisiert einen Fehlschlag an das, was das Programm gestartet hat.0bedeutet Erfolg, alles andere, dass etwas schiefging. Shell-Skripte prüfen das.
argv[0] statt eines fest eingetragenen Namens auszugeben sorgt dafür, dass die Meldung zu dem passt, wie der Benutzer das Programm aufgerufen hat - auch wenn es umbenannt oder über einen anderen Pfad erreicht wurde.
Numerische Argumente umwandeln
argv[1] ist Text. Um zu rechnen, musst du ihn umwandeln, und die dafür zuständige Funktion ist strtol aus <stdlib.h>:
Füge 10, 20, 30 als drei Args-Felder hinzu, und ersetze dann eines durch banane, um den Fehlerpfad zu sehen.
Der dritte Parameter von strtol ist die Basis: 10 für dezimal, 16 für hexadezimal oder 0, um sie an einem 0x- oder führenden Nullpräfix automatisch zu erkennen. Der zweite ist der Ort, an dem ein Zeiger auf das erste nicht verbrauchte Zeichen abgelegt wird, und genau das macht die Fehlerprüfung möglich:
end == textbedeutet, dass nichts gelesen wurde - das Argument begann nicht mit einer Zahl.*end != '\0'bedeutet, dass hinter der Zahl Text übrig war,"12abc"wird also abgelehnt, statt still zu 12 zu werden.errno == ERANGEbedeutet, dass der Wertlongüberschritten hat.
Vergleiche mit atoi, das kürzer ist und nichts davon melden kann:
int n = atoi(argv[1]); /* "banane" -> 0, "0" -> 0, Überlauf -> undefiniert */
atoi liefert 0 für ungültige Eingaben, was von einer echten Null nicht zu unterscheiden ist. Verwende strtol (und strtod für Gleitkommazahlen), wann immer die Eingabe von außerhalb deines Programms kommt. Mehr unter Zeichenkettenumwandlung.
Ein kleiner Rechner
Alles zusammen - ein Programm, das eine Zahl, einen Operator und eine Zahl entgegennimmt:
Probiere 12 + 30, dann 7 x 6, dann 5 / 0.
Beachte strcmp(op, "+") == 0 statt op == "+". char *-Werte mit == zu vergleichen vergleicht Adressen, nicht Inhalte, und wäre selbst bei identischem Text falsch. Siehe Zeichenkettenfunktionen.
Das x statt * ist ein Detail aus der Praxis: Die meisten Shells ersetzen ein nacktes * durch die Liste der Dateien im aktuellen Verzeichnis, bevor dein Programm überhaupt läuft. Es zu quoten ('*') funktioniert auch, aber ein Zeichen zu wählen, das die Shell ignoriert, ist freundlicher.
Optionen auswerten
Optionen beginnen konventionell mit -. Eine einfache selbstgeschriebene Schleife deckt die üblichen Fälle ab:
Probiere es mit vier Args-Feldern: -v, -n, 3, hallo.
Die Prüfung i + 1 >= argc vor argv[++i] ist die wichtige Zeile: Eine Option, die einen Wert erwartet, muss bestätigen, dass der Wert tatsächlich da ist, sonst liest -n als letztes Argument über das Ende des Arrays hinaus. Auf echten Unix-Systemen erledigt getopt aus <unistd.h> all das für dich, einschließlich gebündelter Kurzoptionen wie -vn3; danach zu greifen lohnt sich, sobald ein Programm mehr als zwei oder drei Optionen hat.
Argumente im Browser-Editor
Die Editorblöcke auf dieser Seite werden für dich kompiliert und ausgeführt, und im Args-Feld tippst du, was in einem Terminal hinter dem Programmnamen stünde. Jedes Feld, das du mit Add arg hinzufügst, wird zu genau einem Eintrag in argv - dazwischen steht keine Shell, es wird also nichts an Leerzeichen getrennt und es sind keine Anführungszeichen nötig: ein Feld mit dem Inhalt hallo welt kommt als das einzelne Argument hallo welt an. Um -n 3 hallo zu übergeben, füge drei Felder hinzu. Ein leeres Feld ergibt argc == 1 - weshalb die Prüfung argc < 2 beim ersten Lauf greift und weshalb es sich lohnt, sie zu schreiben.
Häufige Fehler
argv[1]lesen, ohneargczu prüfen. Undefiniertes Verhalten, wenn keine Argumente übergeben wurden - und der häufigste Absturz in diesem Bereich.- Die Schleife bei
i = 0beginnen. Das verarbeitet den Programmnamen, als wäre er ein Datum. argv[1]als Zahl behandeln. Es ist Text, bis du es umwandelst.atoiauf Benutzereingaben anwenden. Kein Weg, ein schlechtes Argument von einer Null zu unterscheiden.- Zeichenketten mit
==vergleichen. Nimmstrcmp. - In die
argv-Zeichenketten schreiben. Sie zu verändern ist vom Standard erlaubt, aber der Platz ist begrenzt und plattformabhängig; kopiere in deinen eigenen Puffer, wenn du etwas ändern musst.
Häufig gestellte Fragen
Was sind argc und argv in C?
Sie sind die beiden Parameter von int main(int argc, char *argv[]). argc ist die Anzahl der Kommandozeilenargumente einschließlich des Programmnamens; argv ist ein Array dieser Argumente als Zeichenketten. argv[0] ist der Programmname, argv[1] das erste echte Argument, und argv[argc] ist immer NULL.
Wie übergibt man einem C-Programm Argumente?
Tippe sie im Terminal hinter den Namen der ausführbaren Datei: ./program hallo 42. Das ergibt argc == 3, mit argv[1] als Zeichenkette "hallo" und argv[2] als "42". Im Editor auf dieser Seite gehören die Argumente stattdessen in das Args-Feld.
Wie wandelt man ein Kommandozeilenargument in C in ein int um?
Benutze strtol: char *end; long n = strtol(argv[1], &end, 10); und prüfe dann, dass end nicht noch am Anfang steht (nichts gelesen) und dass *end gleich '\0' ist (kein Rest). atoi ist kürzer, liefert aber 0 sowohl für "0" als auch für "banane" und kann daher keinen Fehler melden.
Was ist argv[0] in C?
Der Name, mit dem das Programm aufgerufen wurde - typischerweise ./program oder der volle Pfad. Er ist nützlich in Benutzungshinweisen (fprintf(stderr, "Aufruf: %s DATEI\n", argv[0])), damit die Meldung dazu passt, wie der Benutzer es tatsächlich aufgerufen hat. In ungewöhnlichen Fällen kann er eine leere Zeichenkette sein, nimm also nicht an, dass er da ist.