Programmieren mit C


Inhalt


Willkommen

Installation

Das Terminal

Exkurs: Scanf und Sonderzeichen

Exkurs: continue & break

Statische Arrays

Exkurs: sizeof

Dynamische Arrays

Exkurs: Speicherbereiche

Funktionen

Exkurs: Funktionen & Arrays

Kommandozeilenparameter

Structs

Dateien

Anwendung: Textdatei einlesen

Hintergrund: Unicode

Stringbibliothek

Ausblick

Dark Mode

Kommandozeilenparameter

In der letzten Vorlesung haben wir Kommandozeilenparameter kennengelernt. In der Vergangenheit haben wir Nutzereingaben durch scanf-Aufrufe erledigt. Schauen wir uns die üblichen Programme auf der Kommandozeile an - ls, rm, mv, gcc - sehen wir, dass wir alle Eingaben als Strings hinter den Aufruf schreiben. Die meisten dieser Programme sind auch in C geschrieben, wir sollten uns diese gängige Praxis also auch aneignen.

Wie bekommen wir die Strings in unser Programm? Um die Strings aus der Kommandozeile in unserem Programm nutzen zu können, nutzen wir folgende Signatur für die main Funktion.

int main(int argc, char **argv)

Die Integer argc speichert hierbei die Anzahl an Argumenten, das Array von Strings argv die tatsächlichen Zeichenfolgen. Wir erinnern uns: Strings sind Arrays von Buchstaben (chars), wollen wir also mehrere Strings speichern, müssen wir ein Array anlegen, das Arrays von chars speichert. Der Datentyp ist also char**.

Wie nutzen wir die Argumente? Schauen wir uns die Nutzung anhand eines bekannten Beispiels an.

int main() {
    char str[100];

    printf("String eingeben:\n");
    scanf("%[^\n]s", str);

    int i=0;
    while( str[i] != 0 ) {
        if( str[i] >= 'A' && str[i] <= 'Z' ) {
            str[i] += 'a' - 'A';
        }
        ++i;
    }

    printf("%s\n", str);
}

Dieser Code wandelt alle Großbuchstaben eines Strings in Kleinbuchstaben um. Ersetzen wir nun die Eingabe mit scanf durch ein Kommandozeilenargument. Lassen wir uns zur Orientierung zuerst alle Argumente ausgeben.

int main(int argc, char** argv) {
    for(int i=0; i<argc; ++i) {
        printf("%s\n", argv[i]);
    }
}

Rufen wir nun das Programm mit dem Argument “Test” auf, so bekommen wir folgende Ausgabe.

mia@surface-mia:~/.../Zusatzmaterial$ ./a.out Test
./a.out
Test

Das erste Argument, also argv[0] ist immer der Name des Programms selbst, bei uns also ./a.out. Erst an der zweiten Stelle beginnen die von uns übergebenen Argumente. Wollen wir also unseren String “Test” nutzen, so müssen wir den Inhalt von argv[1] auslesen.

int main(int argc, char **argv) {
    char *str = malloc(strlen(argv[1])+1);
    strcpy(str, argv[1]);

    int i=0;
    while( str[i] != 0 ) {
        if( str[i] >= 'A' && str[i] <= 'Z' ) {
            str[i] += 'a' - 'A';
        }
        ++i;
    }
    printf("%s\n", str);

    free(str);
}

Wir kopieren zunächst den String aus argv[1] in unseren neu angelegten String str. Dieser Schritt ist nicht notwendig, aussagekräftige Namen erleichtern aber das Verständnis. Der Rest des Programms muss dann nicht verändert werden.

Aufpassen müssen wir nur bei Strings mit Leerzeichen. Diese sollten, wie immer auf der Kommandozeile, in Anführungszeichen übergeben werden. Anonsten werden die Wörter als einzelne Argumente verarbeitet. Befehle können durch Verwendung des -Zeichens auch in mehrere Zeilen getrennt werden.

mia@surface-mia:~/.../Zusatzmaterial$ ./a.out \
> "Dies ist ein Testsatz!"
dies ist ein testsatz!