Notes 1

Sie können diese Seite ausdrucken oder mit einem PDF-Drucker in ein PDF umwandeln, um Ihre eigenen Notizen hinzuzufügen.

Sie können bereits C? Schauen Sie sich doch einmal die Shorts zu dieser Vorlesung an. Gerade in den „Drei Extra-Minuten“ gibt es ein paar anspruchsvollere Inhalte.

Willkommen!

  • In der letzten Sitzung haben wir Scratch kennengelernt, eine visuelle Programmiersprache.
  • Alle grundlegenden Programmierkonzepte, die in Scratch vorgestellt werden, können beim Erlernen einer beliebigen Programmiersprache verwendet werden.
  • Erinnern Sie sich daran, dass Maschinen nur binäre Codes verstehen. Während Menschen Quellcode schreiben, also eine Liste von Anweisungen für den Computer, die für Menschen lesbar ist, verstehen Maschinen nur das, was wir Maschinencode nennen. Dieser Maschinencode ist ein Muster aus Einsen und Nullen, das einen gewünschten Effekt erzeugt.
  • Wir können Quellcode in Maschinencode umwandeln, indem wir ein spezielles Programm benutzen, das wir Compiler nennen. Heute werden wir Ihnen einen Compiler vorstellen, mit dem Sie Quellcode in der Programmiersprache C in Maschinencode umwandeln können.
  • Heute werden Sie nicht nur lernen, wie man programmiert, sondern auch, wie man guten Code schreibt.
  • Die Codequalität kann nach drei Kriterien bewertet werden. Erstens, hinsichtlich der Korrektheit, was die Frage “Läuft der Code wie beabsichtigt?” betrifft. Zweitens kann man sich das Design ansehen, also sich fragen: “Wie gut ist der Code aufgebaut?”. Schließlich bezieht sich die Frage nach dem Stil darauf, wie ästhetisch ansprechend und konsistent der Code geschrieben ist.

Hello World

  • Die integrierte Entwicklungsumgebung (IDE), die für diesen Kurs verwendet wird, ist Visual Studio Code, meist als VS Code abgekürzt.

  • Einer der wichtigsten Gründe, warum wir VS Code verwenden, ist, dass wir damit alle für den Kurs benötigten Tools dort vorinstallieren können. Dieser Kurs und die darin enthaltenen Anleitungen wurden für diese Umgebung entwickelt.

  • Die manuelle Installation der für den Kurs erforderlichen Software auf Ihrem eigenen Computer (Dev Container, offline) ist eine etwas mühsamere Angelegenheit. In den Tutorien wird Ihnen dabei geholfen, falls Sie diesen Weg gehen wollen.

  • Am einfachsten für einen schnellen Start ist es, VS Code im Browser zu verwenden (setzt GitHub-Account voraus). Sie können VS Code dazu unter cs50.dev öffnen.

  • Die IDE kann in mehrere Bereiche unterteilt werden:

    IDE
    IDE

  • Auf der linken Seite gibt es einen Dateiexplorer, in dem Sie Ihre Dateien finden können. Außerdem gibt es in der Mitte einen Bereich, der als Texteditor bezeichnet wird und in dem Sie Ihr Programm bearbeiten können. Schließlich gibt es eine “Kommandozeile” (command line interface, CLI), die man auch Befehlszeile oder Terminal nennt, wo wir Befehle eingeben können. Wenn man VS Code im Browser ausführt, werden die Befehle an den Computer in der Cloud gesendet.

  • Wir werden drei Befehle verwenden, um unser erstes Programm zu schreiben, zu kompilieren und auszuführen:

    code hello.c
    
    make hello
    
    ./hello
  • Der erste Befehl, code hello.c, erstellt eine Datei und erlaubt uns, Anweisungen für dieses Programm im Texteditor einzugeben. Der zweite Befehl, make hello, kompiliert die Datei aus unseren Anweisungen in C und erstellt eine ausführbare Datei namens hello. Der letzte Befehl, ./hello, führt das Programm namens hello aus.

  • Man schreibt make hello, nicht make hello.c, weil hello.c haben wir ja schon angelegt.

  • Um Ihr erstes Programm in C zu erstellen, müssen Sie also code hello.c in das Terminal-Fenster eintippen. Beachten Sie, dass es Absicht ist, dass wir den Dateinamen kleingeschrieben haben, keine Leerzeichen verwendet haben und die Erweiterung .c hinzugefügt haben. Wenn sich die Datei im Texteditor öffnet.

  • Tipp: Damit Sie Schreibroutine bekommen, sollten Sie den Code selbst schreiben, nicht einfach nur kopieren und einfügen.

    #include <stdio.h>
    
    int main(void)
    {
    	printf("hello, world\n");
    }
  • Sobald man eine geschweifte Klammer oder eine andere Klammer schreibt, wird die zweite erzeugt. Wenn man Enter drückt, wird die nächste Zeile eingerückt.

  • In CS50 wird automatisch gespeichert.

  • Jedes einzelne Zeichen oben erfüllt einen Zweck. Wenn Sie das Programm falsch eingeben, wird das Programm nicht kompiliert werden können oder bei der Ausführung einen Fehler ausgeben. printf ist eine Funktion, die eine Textzeile ausgeben kann. Beachten Sie die Platzierung der Anführungszeichen (doppelte!) und des Semikolons. Beachten Sie auch, dass das \n nach den Worten “hello, world” eine neue Zeile erzeugt.

  • Danach klicken Sie wieder in das Terminalfenster. Nun können Sie Ihren Code kompilieren, indem Sie dort make hello ausführen. Beachten Sie, dass wir .c weglassen. make startet den Compiler, der nach unserer Datei “hello.c” sucht und sie in ein Programm namens “hello” verwandelt. Wenn die Ausführung dieses Befehls zu keinen Fehlern und zu keiner Ausgabe führt, können Sie fortfahren. Wenn ein Fehler ausgegeben wird, überprüfen Sie Ihren Code noch einmal, um sicherzustellen, dass er mit dem oben genannten übereinstimmt.

  • Geben Sie nun ./hello ein und Ihr Programm wird ausgeführt und sagt hello, world.

  • Öffnen Sie nun den Dateiexplorer auf der linken Seite. Sie werden feststellen, dass es jetzt sowohl eine Datei namens hello.c als auch eine andere Datei namens hello gibt. Die Datei hello.c kann vom Compiler gelesen werden: Dort ist Ihr Code gespeichert. hello ist eine ausführbare Datei, die Sie ausführen können, die aber nicht vom Compiler – und auch nicht von Menschen – gelesen werden kann.

Funktionen

  • In Scratch haben wir (in der englischen Version) den Block say benutzt, um einen beliebigen Text auf dem Bildschirm anzuzeigen. In C gibt es eine Funktion namens printf, die genau das gleiche tut.

  • Man sagt, die Ausgabe im Terminal ist ein Seiteneffekt der printf-Funktion. Es ist nicht der Rückgabewert.

  • Beachten Sie, dass unser Code diese Funktion bereits aufruft:

    printf("Hallo, Welt\n");
  • Das Argument, das an printf übergeben wird, ist "hello, world\n". Die Code-Anweisung wird mit einem ; abgeschlossen.

  • Ein häufiger Fehler in der C-Programmierung ist das Auslassen eines Semikolons. Ändern Sie Ihren Code wie folgt:

    #include <stdio.h>
    
    int main(void)
    {
    	printf("hello, world\n")
    }
  • Beachten Sie, dass das Semikolon jetzt weg ist.

  • Führen Sie in Ihrem Terminalfenster make hello aus. Sie werden nun mit zahlreichen Fehlern konfrontiert! Wenn Sie das Semikolon wieder an die richtige Stelle setzen und make hello erneut ausführen, verschwinden die Fehler.

  • Beachten Sie auch das spezielle Symbol \n in Ihrem Code. Versuchen Sie, diese Zeichen zu entfernen und Ihr Programm erneut zu kompilieren, indem Sie make hello ausführen. Tippen Sie ./hello in das Terminal-Fenster, wie hat sich Ihr Programm verändert? Das Backslash-Zeichen (\) wird als Escape-Zeichen bezeichnet, das dem Compiler mitteilt, dass \n eine spezielle Anweisung ist.

  • Stellen Sie Ihr Programm wie folgt wieder her:

    #include <stdio.h>
    
    int main(void)
    {
    	printf("hello, world\n");
    }
  • Beachten Sie, dass das Semikolon und \n wiederhergestellt wurden.

  • Die Anweisung am Anfang des Codes #include <stdio.h> ist ein sehr spezieller Befehl, der dem Compiler mitteilt, dass Sie die Fähigkeiten einer Bibliothek (engl. library) namens stdio nutzen wollen. Dazu teilen Sie dem Compiler mit, dass er die Header-Datei stdio.h, die zu dieser Bibliothek gehört lesen soll. Dies erlaubt Ihnen, neben vielen anderen Dingen, die printf-Funktion zu nutzen. Mehr über die Möglichkeiten, die Ihnen diese Bibliothek bietet, erfahren Sie auf den Manual Pages von CS50. Die Manual Pages erläutern, was verschiedene Befehle tun und wie sie funktionieren.

  • Bibliotheken sind Sammlungen von vorgefertigten Funktionen, die andere in der Vergangenheit geschrieben haben und die wir in unserem Code verwenden können.

  • In Inf-Einf-B nutzen wir gerade anfangs oft die CS50-Bibliothek. Dazu müssen wir immer ihre Header-Datei cs50.h einbinden.

Variablen

  • Erinnern Sie sich, dass wir in Scratch die Möglichkeit hatten, den Benutzer zu fragen: “Wie heißt du?” und “Hallo” mit dem angehängten Namen zu sagen.

  • In C können wir das Gleiche tun. Ändern Sie Ihren Code wie folgt:

    #include <stdio.h>
    
    int main(void)
    {
    	string answer = get_string("What's your name? ");
    	printf("hello, %s\n", answer);
    }
  • Die Funktion get_string wird verwendet, um eine Zeichenkette vom Benutzer zu erhalten. Dann wird die Variable answer an die Funktion printf übergeben. Mit %s wird die Funktion printf angewiesen, sich auf den Empfang eines Strings vorzubereiten.

  • answer ist ein spezieller Speicherplatz, den wir Variable nennen. answer ist vom Typ String und kann eine beliebige Zeichenkette enthalten. Es gibt noch weitere Datentypen, etwa int, bool, char und etliche andere.

  • %s ist ein Platzhalter, der Formatcode genannt wird und der der Funktion printf sagt, dass sie sich auf den Empfang einer Zeichenkette vorbereiten soll. answer ist der String, der dan anstelle von %s ausgegeben wird.

  • Wenn Sie make hello noch einmal im Terminalfenster ausführen, werden Sie feststellen, dass zahlreiche Fehler auftreten.

  • Wenn man sich die Fehler ansieht, werden string und get_string vom Compiler nicht erkannt. Wir müssen dem Compiler diese Funktionen beibringen, indem wir ihm die CS50-Bibliothek bekannt machen:

    #include <cs50.h>
    #include <stdio.h>
    
    int main(void)
    {
    	string answer = get_string("What's your name? ");
    	printf("hello, %s\n", answer);
    }
  • Sehen Sie, wie wir #include <cs50.h> am Anfang Ihres Codes eingefügt haben?

  • Wenn Sie nun wieder make hello im Terminalfenster ausführen, können Sie Ihr Programm durch Eingabe von ./hello starten. Das Programm fragt nun nach Ihrem Namen und sagt dann, wie beabsichtigt, “hello” und danach den eingegebenen Namen.

  • printf kennt viele Formatcodes. Hier ist eine unvollständige Liste von Codes, die Sie in diesem Kurs verwenden können:

    %c
    
    %f
    
    %i
    
    %li
    
    %s
  • %s wird für String-Variablen verwendet. %i wird für int oder Integer-Variablen. Sie können mehr darüber auf den Manual Pages herausfinden.

Bedingte Anweisungen (und Grundlagen von Variablen)

  • Ein weiterer Baustein, den Sie in Scratch verwendet haben, waren die Bedingten Anweisungen. Man möchte zum Beispiel etwas tun, wenn x größer als y ist. Außerdem möchte man vielleicht etwas anderes tun, wenn diese Bedingung nicht erfüllt ist.

  • Wir sehen uns ein paar Beispiele aus Scratch an.

  • Bevor wir zu Bedingten Anweisungen kommen, sehen wir uns an, wie wir mit Variablen arbeiten.

  • In C kann man einem int, also einer Variable, die ganze Zahlen aufnimmt, wie folgt einen Wert zuweisen:

    int counter = 0;
  • Dadurch weisen wir der Variablen counter vom Typ int den Wert 0 zu.

  • Nun können wir zu counter eine Eins addieren

    counter = counter + 1;
  • Dadurch wird 1 zum Wert von counter hinzugefügt.

  • Dies kann auch kürzer dargestellt werden:

    counter += 1;
  • Oder noch kürzer:

    counter++;
  • Beachten Sie, dass auch diese Anweisung “1” zum Wert von counter addiert, aber deutlich kürzer ist.

  • Sie können auch “1” subtrahieren, z.B. so:

    counter--;
  • Beachten Sie, dass “1” aus dem Wert von “Zähler” entfernt wird.

  • Mit diesem neuen Wissen über die Zuordnung von Werten zu Variablen können Sie Ihre erste bedingte Anweisung programmieren.

  • Geben Sie im Terminalfenster code compare.c ein und schreiben Sie folgenden Code:

#include <cs50.h>
#include <stdio.h>

int main(void)
{
	int x = get_int("What's x? ");
	int y = get_int("What's y? ");

	if (x < y)
	{
		printf("x is less than y\n");
	}
}
  • Beachten Sie, dass wir zwei Variablen erstellen, einen int (Ganzzahl) namens x und einen weiteren namens y. Die Werte dieser Variablen werden mit der Funktion get_int eingelesen.

  • Sie können Ihren Code ausführen, indem Sie make compare im Terminalfenster ausführen, gefolgt von ./compare. Wenn Sie eine Fehlermeldung erhalten, überprüfen Sie Ihren Code auf Fehler.

  • Wir schauen uns in der Vorlesung Flussdiagramme an; damit kann man die Funktionsweise eines Computerprogramms zu untersuchen und prüfen, ob das Design des Codes gut ist.

  • Wenn wir uns ein Flussdiagramm des obigen Codes ansehen, können wir zahlreiche Mängel feststellen.

  • Wir können Ihr Programm verbessern, indem wir es wie folgt ändern:

    #include <cs50.h>
    #include <stdio.h>
    
    int main(void)
    {
        int x = get_int("What's x? ");
        int y = get_int("What's y? ");
    
        if (x < y)
        {
            printf("x is less than y\n");
        }
        else if (x > y)
        {
            printf("x is greater than y\n");
        }
        else
        {
            printf("x is equal to y\n");
        }
    }
  • Beachten Sie, dass nun alle möglichen Ergebnisse berücksichtigt werden.

  • Sie können Ihr Programm nun erneut kompilieren, ausführen und testen.

  • Im Flussdiagramm sehen wir, dass der Code nun ein besseres Design hat.

  • Lassen Sie uns einen anderen Datentyp namens char betrachten.

  • Wir schreiben ein neues Programm, indem wir code agree.c in das Terminalfenster eingeben.

  • Während ein string eine Reihe von Zeichen ist, ist ein char ein einzelnes Zeichen (engl. character).

  • Schreiben Sie im Texteditor folgenden Code:

    #include <cs50.h>
    #include <stdio.h>
    
    int main(void)
    {
    	// Prompt user to agree
    	char c = get_char("Do you agree? ");
    
    	// Check whether agreed
    	if (c == 'Y' || c == 'y')
    	{
    		printf("Agreed.\n");
    	}
    	else if (c == 'N' || c == 'n')
    	{
    		printf("Not agreed.\n");
    	}
    }
  • Beachten Sie, dass bei char immer einfache (nicht doppelte) Anführungszeichen verwendet werden. Beachten Sie außerdem, dass == prüft, dass etwas gleich mit etwas anderem ist, während ein einzelnes Gleichheitszeichen in C eine ganz andere Funktion hätte (nämlich die Zuweisung von Werten zu Variablen).

  • Das || bedeutet so viel wie “oder”.

  • Sie können Ihren Code testen, indem Sie make agree in das Terminalfenster eingeben, gefolgt von ./agree.

Schleifen

  • Dem Schleifen-Baustein aus Scratch können wir auch in unseren C-Programmen verwenden.

  • Wir sehen uns ein paar Beispiele aus Scratch an. Betrachten Sie den folgenden Code:

    int counter = 3;
    while (counter > 0)
    {
    	printf("meow\n");
    	counter = counter - 1;
    }
  • Beachten Sie, dass der Code der Variablen counter den Wert “3” zuweist. Dann wird in der while-Schleife “meow” ausgegeben und bei jeder Iteration der Wert “1” vom Zähler abgezogen. Sobald der Zähler nicht mehr größer als Null ist, endet die Schleife.

  • Geben Sie in Ihrem Terminal-Fenster code meow.c ein und schreiben Sie folgenden Code:

#include <stdio.h>

int main(void)
{
	printf("meow\n");
	printf("meow\n");
	printf("meow\n");
}
  • Beachten Sie, dass dies wie beabsichtigt funktioniert, aber es Potenzial für besseres Design gibt.
  • Wir können unser Programm verbessern, indem wir Ihren Code wie folgt abändern:
#include <stdio.h>

int main(void)
{
	int i = 3;
	while (i > 0)
	{
		printf("meow\n");
		i--;
	}
}
  • Beachten Sie, dass wir einen int namens i erstellen und ihm den Wert “3” zuweisen. Dann erstellen wir eine while-Schleife, die läuft, solange i > 0 erfüllt ist. Dann wird der Schleifenkörper durchlaufen. Jedes Mal wird “1” von i mit der Anweisung i-- abgezogen.

  • In ähnlicher Weise können wir es mit Hochzählen implementieren:

    #include <stdio.h>
    
    int main(void)
    {
    	int i = 1;
    	while (i <= 3)
    	{
    		printf("meow\n");
    		i++;
    	}
    }
  • Beachten Sie, dass unser Zähler i bei 1 beginnt. Jedes Mal, wenn die Schleife läuft, wird der Zähler um “1” erhöht. Sobald der Zähler größer als “3” ist, wird die Schleife angehalten.

  • In der Informatik zählen wir in der Regel von Null an. Am besten überarbeiten Sie Ihren Code daher wie folgt:

    #include <stdio.h>
    
    int main(void)
    {
    	int i = 0;
    	while (i < 3)
    	{
    		printf("meow\n");
    		i++;
    	}
    }
  • Beachten Sie, dass wir jetzt von Null an zählen.

  • Ein weiteres Werkzeug in unserem Werkzeugkasten für Schleifen ist eine for-Schleife.

  • Wir können das Design unseres Programms meow.c mit einer for-Schleife weiter verbessern. Ändern Sie Ihren Code dazu wie folgt:

    #include <stdio.h>
    
    int main(void)
    {
    	for (int i = 0; i < 3; i++)
    	{
    		printf("meow\n");
    	}
    }
  • Beachten Sie, dass die for-Schleife drei Argumente enthält. Das erste Argument int i = 0 startet unseren Zähler bei Null. Das zweite Argument i < 3 ist die Bedingung, die überprüft wird. Schließlich weist das Argument i++ die Schleife an, bei jedem Schleifendurchlauf um eins zu erhöhen.

  • Mit dem folgenden Code können wir sogar eine Endlosschleife erstellen:

    #include <cs50.h>
    #include <stdio.h>
    
    int main(void)
    {
    	while (true)
    	{
    		printf("meow\n");
    	}
    }
  • Beachten Sie, dass true die Bedingung immer erfüllt. Daher wird der Code in der Schleife immer wieder ausgeführt. Wenn Sie dieses Programm starten, verlieren Sie die Kontrolle über Ihr Terminalfenster. Sie können das Programm abbrechen, indem Sie Control-C (oder Strg-C) auf Ihrer Tastatur drücken.

  • Später werden wir es uns noch genauer ansehen, aber eine eigene Funktion können Sie in C auch jetzt schon wie folgt erstellen:

    void meow(void)
    {
    	printf("meow\n");
    }
  • Das anfängliche void bedeutet, dass die Funktion keine Werte zurückgibt. Das (void) bedeutet, dass der Funktion keine Werte übergeben werden.

  • Diese Funktion kann in der Hauptfunktion wie folgt verwendet werden:

    #include <stdio.h>
    
    void meow(void);
    
    int main(void)
    {
    	for (int i = 0; i < 3; i++)
    	{
    		meow();
    	}
    }
    
    void meow(void)
    {
    	printf("meow\n");
    }
  • Beachten Sie, dass die Funktion “meow” mit der Anweisung “meow()” aufgerufen wird. Dies ist möglich, weil die “meow”-Funktion am Ende des Codes definiert ist und der Prototyp der Funktion am Anfang des Codes als void meow(void) angegeben ist.

  • Ihre “meow”-Funktion kann weiter modifiziert werden, um Eingaben zu akzeptieren:

    #include <stdio.h>
    
    void meow(int n);
    
    int main(void)
    {
    	meow(3);
    }
    
    // Meow some number of times
    void meow(int n)
    {
    	for (int i = 0; i < n; i++)
    	{
    		printf("meow\n");
    	}
    }
  • Beachten Sie, dass der Prototyp in void meow(int n) geändert wurde, um den Compiler zu informieren, dass meow einen int als Eingabe akzeptiert.

Operatoren und Abstraktion

  • Sie können einen Taschenrechner in C implementieren.
  • Geben Sie in Ihrem Terminal code calculator.c ein und schreiben Sie folgenden Code:

    #include <cs50.h>
    #include <stdio.h>
    
    int main(void)
    {
    	// Prompt user for x
    	int x = get_int("x: ");
    
    	// Prompt user for y
    	int y = get_int("y: ");
    
    	// Perform addition
    	printf("%i\n", x + y);
    }
  • Beachten Sie, wie die Funktion get_int verwendet wird, um zweimal eine Zahl vom Benutzer zu erhalten. Eine Ganzzahl wird in der int-Variablen x gespeichert, eine weitere in der int-Variablen y. Dann druckt die Funktion printf den Wert von x + y aus, und zwar an die Stelle, an der der Formatcode %i steht. Danach wird mit \n ein Zeilenumbruch ausgegeben.

  • Das + ist ein Operator. In C gibt es insbesondere folgende arithmetische Operatoren:

    • + für Addition
    • - für Subtraktion
    • * für Multiplikation
    • / für Division
    • % für Module (Rest nach einer Division)
  • Indem wir unser zuvor erworbenes Wissen über Funktionen anwenden, können wir die Addition in eine Funktion abstrahieren. Ändern Sie Ihren Code dazu wie folgt:

    • Abstraktion ist die Kunst, unseren Code so zu vereinfachen, dass dass wir Probleme schrittweise in kleinere Teile zerlegen und die Details der Lösung vor uns verbergen.
    #include <cs50.h>
    #include <stdio.h>
    
    int add(int a, int b);
    
    int main(void)
    {
    	// Prompt user for x
    	int x = get_int("x: ");
    
    	// Prompt user for y
    	int y = get_int("y: ");
    
    	// Perform addition
    	int z = add(x, y);
    	printf("%i\n", z);
    }
    
    int add(int a, int b)
    {
    	int c = a + b;
    	return c;
    }
  • Beachten Sie, dass die Funktion add zwei Variablen als Eingabe benötigt. Diese Werte werden den Variablen a und b zugewiesen. Die Funktion führt dann die Addition durch und speichert das in der Variablen c. Danach gibt sie den Wert in c zurück dorthin, wo sie aufgerufen wurde.

  • Beachten Sie außerdem, dass der Scope (der Kontext, in dem Variablen existieren) von x die Funktion main ist, sie ist nur dort bekannt. Die Variable c gibt es hingegen nur in der Funktion add.

  • Das Design dieses Programms kann wie folgt weiter verbessert werden:

    #include <cs50.h>
    #include <stdio.h>
    
    int add(int a, int b);
    
    int main(void)
    {
      // Prompt user for x
      int x = get_int("x: ");
    
      // Prompt user for y
      int y = get_int("y: ");
    
      // Perform addition
      printf("%i\n", add(x, y));
    }
    
    int add(int a, int b)
    {
      return a + b;
    }
  • Beachten Sie, dass “c” in der Funktion “add” entfernt wurde.

  • Obwohl es sehr nützlich ist, zu einer “Add”-Funktion zu abstrahieren, ist es etwas umständlich. Sie könnten die Addition auch direkt im Aufruf von printf durchführen:

    #include <cs50.h>
    #include <stdio.h>
    
    int main(void)
    {
        // Benutzer zur Eingabe von x auffordern
        long x = get_long("x: ");
    
        // Benutzer zur Eingabe von y auffordern
        long y = get_long("y: ");
    
        // Addition durchführen
        printf("%li\n", x + y);
    }
  • Beachten Sie, dass die Addition innerhalb des Aufrufs von printf durchgeführt wird.

  • In ähnlicher Weise könnten auch andere Operationen, etwa eine Division durchgeführt werden:

    #include <cs50.h>
    #include <stdio.h>
    
    int main(void)
    {
        // Aufforderung an den Benutzer zur Eingabe von x
        int x = get_int("x: ");
    
        // Aufforderung an den Benutzer zur Eingabe von y
        int y = get_int("y: ");
    
        // Teilen Sie x durch y
        printf("%i\n", x / y);
    }

Linux und die Kommandozeile

  • Linux ist ein Betriebssystem, bei dem die Kommandozeile eine wichtige Rolle spielt. Wenn wir das Terminalfenster von VS Code im Kurs benutzen, steuern wir einen Rechner, auf dem Linux läuft – entweder in der Cloud oder in einer virtuellen Maschine, die jedes Mal auf Ihrem Laptop gestartet wird, wenn Sie VS Code öffnen.
  • Einige übliche Befehlszeilenprogramme, die wir verwenden können, sind:
    • cd, um unser aktuelles Verzeichnis (Ordner) zu wechseln
    • cp, um Dateien und Verzeichnisse zu kopieren
    • ls, zum Auflisten von Dateien in einem Verzeichnis
    • mkdir, um ein Verzeichnis zu erstellen
    • mv, zum Verschieben (Umbenennen) von Dateien und Verzeichnissen
    • rm, zum Entfernen (Löschen) von Dateien
    • rmdir, um Verzeichnisse zu entfernen (zu löschen)
  • Das am häufigsten verwendete Programm ist ls, das alle Dateien im aktuellen Verzeichnis auflistet. Geben Sie einfach ls in das Terminalfenster ein und drücken Sie Enter. Sie werden alle Dateien im aktuellen Verzeichnis sehen.
  • Ein weiterer nützlicher Befehl ist mv, mit dem Sie eine Datei von einer Datei in eine andere verschieben können. Zum Beispiel können Sie diesen Befehl verwenden, um Hello.c (beachten Sie das große H) in hello.c umzubenennen, indem Sie mv Hello.c hello.c eingeben.
  • Sie können auch Verzeichnisse erstellen. Sie können mkdir pset1 eingeben, um ein Verzeichnis namens pset1 zu erstellen.
  • Sie können dann cd pset1 benutzen, um von Ihrem aktuellen Verzeichnis in das neu angelegte Verzeichnis pset1 zu wechseln.
  • In welchem Verzeichnis Sie sind, sehen Sie – je nach Konfiguration – am Zeilenanfang. Wenn Sie sich unsicher sind, können Sie mit pwd (von engl. print working directory) Ihr aktuelles Verzeichnis ausgeben lassen.

Mario

  • Alles, was wir heute besprochen haben, sind Bausteine für Ihre Arbeit als angehende Informatikerinnen und Informatiker.
  • Die folgenden Ausführungen sollen Ihnen helfen, sich auf die Arbeit an einer Problemstellung für diesen Kurs im Allgemeinen einzustellen: Wie geht man an ein Problem aus der Informatik heran?
  • Stellen Sie sich vor, wir wollten die Grafik des Spiels Super Mario Bros. nachbilden. Wie müsste ein Programm aussehen, das so etwas wie die vier horizontalen Fragezeichenblöcke ausgibt?

Mario Question Marks
Mario Question Marks

  • Geben Sie im Terminalfenster code mario.c ein und programmieren Sie Folgendes:

    #include <stdio.h>
    
    int main(void)
    {
    	for (int i = 0; i < 4; i++)
    	{
    		printf("?");
    	}
    	printf("\n");
    }
  • Beachten Sie, dass hier vier Fragezeichen in einer Schleife gedruckt werden.

  • Mit der gleichen Logik können wir auch drei vertikale Blöcke erstellen.

    Mario Blocks
    Mario Blocks

  • Ändern Sie dazu Ihren Code wie folgt:

    #include <stdio.h>
    
    int main(void)
    {
    	for (int i = 0; i < 3; i++)
    	{
    		printf("#\n");
    	}
    }
  • Beachten Sie, dass drei vertikale Ziegelsteine in einer Schleife gedruckt werden.

  • Was wäre, wenn wir diese Ideen kombinieren wollten, um eine drei-mal-drei-Gruppe von Blöcken zu schaffen?

    Mario Grid
    Mario Grid

  • Wir können der obigen Logik folgen, indem wir die bisherigen Ideen kombinieren. Ändern Sie Ihren Code wie folgt:

#include <stdio.h>

int main(void)
{
	for (int i = 0; i < 3; i++)
	{
		for (int j = 0; j < 3; j++)
		{
			printf("#");
		}
		printf("\n");
	}
}
  • Beachten Sie, dass eine Schleife innerhalb einer anderen liegt – man sagt: es sind verschachtelte Schleifen. Die erste Schleife legt fest, welche vertikale Zeile gedruckt wird. Für jede Zeile werden drei Spalten gedruckt. Nach jeder Zeile wird eine neue Zeile gedruckt.

  • Was wäre, wenn wir sicherstellen wollten, dass die Anzahl der Blöcke konstant, d. h. unveränderlich ist? Ändern Sie Ihren Code wie folgt:

    int main(void)
    {
    	const int n = 3;
    	for (int i = 0; i < n; i++)
    	{
    		for (int j = 0; j < n; j++)
    		{
    			printf("#");
    		}
    		printf("\n");
    	}
    }
  • Beachten Sie, dass “n” jetzt eine Konstante ist. Diese Variable kann nach ihrer Initialisierung nicht mehr geändert werden.

  • Mit dem, was wir schon wissen, können wir unseren Code so umbauen, dass der Benutzer nach der Größe des Rasters gefragt wird. Ändern Sie Ihren Code wie folgt:

#include <cs50.h>
#include <stdio.h>

int main(void)
{
	int n = get_int("Size: ");

	for (int i = 0; i < n; i++)
	{
		for (int j = 0; j < n; j++)
		{
			printf("#");
		}
		printf("\n");
	}
}
  • Beachten Sie, dass get_int verwendet wird, um den Benutzer aufzufordern.
  • Ein allgemeiner Ratschlag bei der Programmierung lautet: Vertraue nie darauf, dass sich die Benutzerinnen und Benutzer so verhalten wie du denkst (oder wie man es erwarten würde). Sie werden sich wahrscheinlich falsch verhalten, entweder unabsichtlich oder absichtlich, und zum Beispiel ungültige Werte eingeben. Wir können unser Programm vor schlechtem Verhalten schützen, indem wir überprüfen, ob die Eingaben unseren Anforderungen genügen. Ändern Sie Ihren Code wie folgt:
#include <cs50.h>
#include <stdio.h>

int main(void)
{
	int n;
	do
	{
		n = get_int("Size: ");
	}
	while (n < 1);

	for (int i = 0; i < n; i++)
	{
		for (int j = 0; j < n; j++)
		{
			printf("#");
		}
		printf("\n");
	}
}
  • Beachten Sie, dass der Benutzer ständig zur Eingabe der Größe aufgefordert wird, bis die Eingabe des Benutzers 1 oder größer ist. Dazu haben wir eine do-while-Schleife verwendet, bei der der Schleifenkörper erst ausgeführt wird bevor die Bedingung geprüft wird.

Kommentare

  • Kommentare sind grundlegende Bestandteile von Computerprogrammen. Damit hinterlassen Sie sich selbst und anderen, mit denen Sie zusammenarbeiten, Erklärungen zu Ihrem Code.

  • Code, den Sie in diesem Kurs erstellen und abgeben (insbesondere im Abschlussprojekt und in der Prüfung), muss immer sinnvolle und aussagekräftige Kommentare enthalten.

  • Normalerweise besteht ein Kommentar aus einigen Wörtern oder ein paar Sätzen, die dabei helfen, zu verstehen, was in einem bestimmten Code-Block passiert. Außerdem dienen solche Kommentare als Gedächtnisstütze für Sie, wenn Sie Ihren Code später überarbeiten müssen.

  • Kommentare stehen im Code immer hinter //. Ändern Sie Ihren Code wie folgt, um Kommentare zu integrieren:

    #include <cs50.h>
    #include <stdio.h>
    
    int main(void)
    {
    	// Prompt user for positive integer
    	int n;
    	do
    	{
    		n = get_int("Size: ");
    	}
    	while (n < 1);
    
    	// Print an n-by-n grid of bricks
    	for (int i = 0; i < n; i++)
    	{
    		for (int j = 0; j < n; j++)
    		{
    			printf("#");
    		}
    		printf("\n");
    	}
    }
  • Beachten Sie, dass jeder Kommentar mit einem // beginnt.

Typen

  • Eine der Schwächen von C ist, dass es sich von Haus aus nur in geringem Maß um die Speicherverwaltung kümmert. Zwar bietet C eine enorme Kontrolle über die Nutzung des Speichers, doch müssen Sie sich aller möglichen Fallstricke der Speicherverwaltung bewusst sein, um keine Fehler zu machen.
  • In der allerersten Vorlesung hatten wir gesehen, dass eine bestimmte Bitfolge von einem Rechner sehr unterschiedlich interpretiert werden können, je nachdem ob es eine Zahl, ein Buchstabe oder eine Farbe ist.
  • Mit Datentypen legen wir beim Programmieren fest, wie die Bits, die in einer Variablen gespeichert werden, interpretiert werden sollen. Ein char ist zum Beispiel dafür gedacht, ein einzelnes Zeichen wie a oder 2 zu speichern.
  • Typen sind sehr wichtig, da jeder Typ bestimmte Grenzen hat und Regeln unterworfen ist. Zum Beispiel kann man in einem int wegen der Grenzen des Speichers nur maximal 4294967296 verschiedene Werte ablegen (int-Werte belegen 32 Bit).
  • Die Anzahl der Bits begrenzt, wie hoch und niedrig wir zählen können.
  • Wenn Sie aber versuchen, mit einem int höher als 2147483647 zu zählen, kommt es zu einem Integer Overflow, bei dem ein falscher Wert (nämlich -2147483648) in der Variablen gespeichert wird. Der int ist nämlich eine Ganzzahl mit Vorzeichen (signed) und eines der 32 Bit wird für das Vorzeichen benutzt. Daher können wir – anders als man erwarten würde – nur bis 231 – 1 zählen.
  • Zu den Typen, mit denen Sie während dieses Kurses interagieren könnten, gehören:
    • bool, ein boolescher Ausdruck, der entweder wahr oder falsch ist
    • char, ein einzelnes Zeichen wie a oder 2
    • double, eine Gleitkommazahl mit mehr Stellen als ein Float
    • float, eine Fließkommazahl oder eine reelle Zahl mit einem Dezimalwert
    • int, ganze Zahlen bis zu einer bestimmten Größe oder Anzahl von Bits
    • long, Ganzzahlen mit mehr Bits, die also höher zählen können als ein int
    • string, eine Zeichenkette
  • Achten Sie beim Programmieren besonders auf die Arten von Variablen, die Sie verwenden, um Probleme in Ihrem Code zu vermeiden.
  • Wir haben uns in der Vorlesung einige Beispiele für Katastrophen angesehen, die durch speicherbezogene Fehler entstehen können (Jahr-2000-Problem, Jahr-2038-Problem, Pac Man Level 256, Donkey Kong Level 22, Boeing 787).

Zusammenfassung

In dieser Vorlesung haben Sie gesehen, wie Sie die Bausteine, die Sie in Scratch kennengelernt haben, auf die Programmiersprache C anwenden können. Sie haben gelernt:

  • wie Sie Ihr erstes Programm in C erstellen;
  • vordefinierte Funktionen, die von Haus aus in C enthalten sind, und wie Sie Ihre eigenen Funktionen implementieren;
  • wie Sie Variablen, Bedingte Anweisungen und Schleifen verwenden;
  • wie man Abstraktion einsetzt, um seinen Code zu vereinfachen und zu verbessern;
  • wie man bei der Lösung eines Informatikproblems vorgeht;
  • wie man die Linux-Kommandozeile benutzt;
  • wie man Kommentare in seinen Code einbaut;
  • wie man Typen und Operatoren verwendet.

Dies war Inf-Einf-B. Bis zum nächsten Mal!