Programmieren in C: Unterschied zwischen den Versionen
Zur Navigation springen
Zur Suche springen
Admin (Diskussion | Beiträge) |
Admin (Diskussion | Beiträge) |
||
(71 dazwischenliegende Versionen desselben Benutzers werden nicht angezeigt) | |||
Zeile 1: | Zeile 1: | ||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
== Grundsätzliches Wissen für angehende Programmierer/-innen == | == Grundsätzliches Wissen für angehende Programmierer/-innen == | ||
+ | [[Datei:Raspi400.jpg|mini|rechts|Der Raspberry Pi 400 für knapp 100.- € zum Anschluss an den Fernseher (hier mit englischem Netzteil!)]] | ||
* Jede Anwendung eines persönlichen Computers, jede Website, jede App ist ein '''Computerprogramm'''. | * Jede Anwendung eines persönlichen Computers, jede Website, jede App ist ein '''Computerprogramm'''. | ||
* Computerprogramme sind Listen von '''Anweisungen''', die vom Computer der Reihe nach abgearbeitet werden. | * Computerprogramme sind Listen von '''Anweisungen''', die vom Computer der Reihe nach abgearbeitet werden. | ||
* Diese Listen werden in ein Textprogramm eingegeben, in Bits und Bytes übersetzt und dann ausgeführt. | * Diese Listen werden in ein Textprogramm eingegeben, in Bits und Bytes übersetzt und dann ausgeführt. | ||
− | |||
* Anweisungen in Programmen bestehen aus '''Schlüsselwörtern und Parametern''', die die Anweisungen genauer spezifizieren. | * Anweisungen in Programmen bestehen aus '''Schlüsselwörtern und Parametern''', die die Anweisungen genauer spezifizieren. | ||
− | * Ein | + | * Ein Beispiel "aus dem richtigen Leben" wäre ''Starte das Auto'', wobei ''Starte'' das Schlüsselwort und ''das Auto'' der Parameter ist. |
− | * | + | * Ein Schlüsselwort sagt dem Computer, '''was''' zu tun ist, ein Parameter erklärt, '''womit''' etwas zu tun ist. |
− | + | ||
+ | == Besonderheiten von C == | ||
+ | * C ist eine sehr kompakte Programmiersprache von immerhin 1968. | ||
+ | * Sie ist damit oft älter als ihre Programmierer. :-) | ||
+ | * C wird auch heute noch benutzt. | ||
+ | * Sehr viele große Projekte sind in C geschrieben (Windows, Linux, Office). | ||
+ | * Dennoch laufen sehr viele C-Programme aus alter Zeit unverändert auch heute noch. | ||
+ | * C ist also sehr ''kompatibel'' zu sich selbst. | ||
+ | * C ermöglicht es, sehr kleine und schnelle Compiler zu bauen, denn | ||
+ | ** die Prüfung von 10.000 Klammern ({}) schafft der Compiler schnell. | ||
+ | ** die Prüfung von 10.000 Wörtern (BEGIN...END) dauert dagegen länger. | ||
+ | * C ist eine Sprache, die auf sehr kleinen Computern gut ablaufen kann. | ||
+ | * C++ ist eine objektorientierte Version von C. | ||
+ | * Compiler für C++ können immer auch C. | ||
+ | |||
+ | == Programmieren in C auf dem eigenen Computer == | ||
+ | [[Datei:Geany.png|mini|links|Die Entwicklungsumgebung GEANY in Aktion auf dem Raspi 400.]] | ||
+ | * Um ein Programm in einer Programmiersprache zu schreiben, braucht man ein passendes Übersetzungsprogramm für diese Sprache. | ||
+ | * Solche Übersetzungsprogramme übersetzen eine Programmiersprache in die universelle Sprache aller Computer (Bits und Bytes). | ||
+ | * Solcher Übersetzungsprogramme heißen '''Compiler'''. | ||
+ | * Man benötigt also für C einen '''C-Compiler''' und | ||
+ | ** einen Editor (Textverarbeitung für Programmierer) zum Erfassen des Programms oder | ||
+ | ** am besten alles zusammen: eine "Integrierte Entwicklungsumgebung (IDE)". | ||
+ | * Ich zum Beispiel benutze diese [https://github.com/Embarcadero/Dev-Cpp/releases hier] (Windows, MacOS). | ||
+ | * Auf einem Raspberry Pi kann man einfach [https://de.wikipedia.org/wiki/Geany Geany] benutzen. | ||
+ | * Oder Sie programmieren einfach hier und jetzt [https://www.onlinegdb.com/online_c_compiler online]. | ||
== Funktionen == | == Funktionen == | ||
− | * Programme können in kleine Abschnitte eingeteilt werden, die einzelne Aufgaben erfüllen (Funktionen). | + | * Ein Problem wird zur Lösung in viele kleine Probleme zerlegt. |
− | * Diese Funktionen haben einen festgelegten Namen, Parameter und können Werte an das Hauptprogramm zurück geben. | + | * Beispiel: "Kuchen backen" kann in "Mische Mehl, Eier...", "Heize den Backofen", "Knete den Teig" etc. aufgeteilt werden. |
− | * | + | * Programme können in kleine Abschnitte eingeteilt werden, die einzelne Unter-Aufgaben erfüllen ('''Funktionen'''). |
+ | * Diese Funktionen haben einen festgelegten '''Namen''', '''Parameter''' und können '''Werte''' an das Hauptprogramm zurück geben. | ||
+ | * Den '''Typ des Rückgabewertes''' steht vor der Funktion (hier: int = integer = ganze Zahlen). | ||
* main ist die ''erste'' Funktion, die in jedem Programm aufgerufen wird. Hier startet also immer das Programm. | * main ist die ''erste'' Funktion, die in jedem Programm aufgerufen wird. Hier startet also immer das Programm. | ||
− | * | + | * In C-Programmen muss es ''immer genau eine'' Funktion mit dem Namen '''main''' geben. |
+ | * Von main aus werden die erwähnten Funktionen des selben Programms '''aufgerufen''', sofern welche existieren. | ||
+ | * Die Hauptfunktion, das ganze Programm, gibt nach der Abarbeitung des Programms einen Wert an den Computer zurück. | ||
+ | * Ein einfaches Programm sieht also jetzt so aus ("//" leitet einen Kommentar ein): | ||
<pre> | <pre> | ||
int main () | int main () | ||
{ | { | ||
− | // Hier stehen | + | // Hier startet das Hauptprogramm |
− | printf (" | + | printf ("Zahlenraten - ich denke mir eine Zahl und Du errätst sie. \n"); |
+ | } | ||
+ | </pre> | ||
+ | |||
+ | == Variable == | ||
+ | * Variable sind '''benannte Speicherstellen''', in denen Zwischenergebnisse gespeichert werden können. | ||
+ | * Variable müssen dem C-Compiler '''erklärt''' werden, damit sie verwendet werden können: sie werden '''deklariert'''. | ||
+ | * Da Programme linear (von oben nach unten) ablaufen, sind '''Variablen erst ab der Deklaration''' nutzbar. | ||
+ | * Der Compiler muss wissen, was in den Variablen stehen soll: der '''Variablentyp'''. | ||
+ | * Typen für Variable in C: Ganzzahlen (int), Fließkommazahlen (float), Zeichen (char) | ||
+ | * Eine Deklaration sieht typischerweise so aus: <Typ><Leerzeichen><Name><Semikolon> | ||
+ | * Beispiel: <pre>int nGedachteZahl;</pre> | ||
+ | * Das "n" vor dem Namen "GedachteZahl" ist nicht notwendig. Es ist aber [https://de.wikipedia.org/wiki/Ungarische_Notation gute Sitte], den Typ (int, also numerisch) im Namen zu erwähnen. | ||
+ | * Variable können auch einen Anfangswert (Initialisierung) enthalten, der einfach dahinter geschrieben wird. | ||
+ | * Beispiel: <pre>int nGedachteZahl = 24;</pre> | ||
+ | * Die Variable nGedachteZahl ist dem Compiler ab diesem Zeitpunkt als Ganzzahl-Speicherstelle bekannt und hat den Wert 24. | ||
+ | * Eine nicht initialisierte Variable hat übrigens '''nicht''' den Wert Null sondern einen unbestimmten Wert (Vorsicht!). | ||
+ | * In unserem Beispiel brauchen wir zwei Variable: in einer steht die gedachte Zufallszahl, in der anderen die Vermutung des Benutzers. | ||
+ | * Nach der Erwähnung des Datentyps kann man weitere Variablen definieren. | ||
+ | * Unser Programm sieht bis hierher also so aus: | ||
+ | <pre> | ||
+ | |||
+ | int nGedachteZahl = 24; // muss erraten werden | ||
+ | nVermutung = 0; // sicher ist sicher | ||
+ | |||
+ | int main () | ||
+ | { | ||
+ | // Hier startet das Hauptprogramm | ||
+ | printf ("Zahlenraten - ich denke mir eine Zahl und Du errätst sie. \n"); | ||
} | } | ||
</pre> | </pre> | ||
== Ein- und Ausgabe == | == Ein- und Ausgabe == | ||
− | + | * Ein Programm braucht grundsätzlich Anweisungen für die '''Eingabe''', die '''Verarbeitung''' und die '''Ausgabe''' von Daten. | |
− | * Ein Programm | + | * Speziell in der Programmiersprache C gibt es '''keine''' Anweisungen zur Ein- und Ausgabe. |
− | + | * C soll auf sehr vielen Computern nutzbar sein und jedes Computersystem hat andere Funktionen für Ein- und Ausgabe. | |
− | * Speziell in der Programmiersprache C gibt es | + | * Deshalb liegt jedem C-Compiler eine Bibliothek von Dateien bei, die Ein- und Ausgabe des jeweiligen Computersystems ermöglicht. |
− | * Wir verwenden hier zur Eingabe das Schlüsselwort '''scanf''' und zur Ausgabe '''printf'''. | + | * Die Funktionen in diesen Dateien werden aber alle in der gleichen Art und Weise aufgerufen ("C-Standard-Bibliotheken"). |
+ | * Wir verwenden hier zur Eingabe das Schlüsselwort '''scanf''' und zur Ausgabe '''printf''' wegen ihrer Ähnlichkeit. | ||
+ | * Im "echten Leben" tun Sie das bitte nicht: die Funktionen sind [https://dasdev.de/nachteile-von-scanf/ nicht krisensicher]. | ||
+ | * Das Format von '''printf''' ist <pre> printf ("<Format>", <Variable>, <Variable>...)</pre> | ||
+ | * Im <Format>-Teil geben Sie an, was ausgegeben werden soll. | ||
+ | * Dabei schaffen Sie ''Platzhalter'' dort, wo später der Wert der Variablen erscheinen soll. | ||
+ | * Platzhalter bestehen aus einem Prozentzeichen und einem Buchstaben für den Typ der Variable. | ||
+ | * Die erlaubten Typen sind vielfältig. Hier einige gebräuchliche: | ||
+ | <pre> | ||
+ | d Dezimalzahl | ||
+ | f Gleitkommazahl | ||
+ | c Einzelnes Zeichen | ||
+ | s String (Mehrere Zeichen) | ||
+ | </pre> | ||
+ | * Nach der Angabe des Typs sind auch Längenangaben u. a. möglich. | ||
+ | * Dieselben Formatvorschriften gelten auch für Eingaben mit ''scanf''. | ||
+ | |||
+ | == Bedingungen == | ||
+ | * Bedingungen sind '''WENN-DANN-Anweisungen'''. | ||
+ | * In C ist das entsprechende Schlüsselwort '''if'''. | ||
+ | * Der weitere Programmlauf hängt dann von '''Bedingungen''' ab: | ||
+ | <pre> | ||
+ | > größer als | ||
+ | < kleiner als | ||
+ | == gleich | ||
+ | != ungleich | ||
+ | >= größer oder gleich | ||
+ | <= kleiner oder gleich | ||
+ | ! nicht | ||
+ | </pre> | ||
+ | * Beispiel: Ob eine eingegebene Zahl größer oder kleiner 1 ist soll in Worten ausgegeben werden: | ||
+ | <pre> | ||
+ | #include <stdio.h> | ||
+ | |||
+ | int nZahl; | ||
+ | |||
+ | int main() | ||
+ | { | ||
+ | printf ("Bitte geben Sie eine Zahl ein: "); | ||
+ | scanf ("%d", &nZahl); | ||
+ | |||
+ | if (nZahl > 1) | ||
+ | printf ("Die Zahl %d ist größer als Eins. \n", nZahl); | ||
+ | else | ||
+ | printf ("Die Zahl %d ist kleiner als Eins. \n", nZahl); | ||
+ | } | ||
+ | </pre> | ||
+ | * Die Befehle nach ''else'' werden immer ausgeführt, wenn <b>das Gegenteil</b> der Bedingung erfüllt ist. | ||
+ | * Das Gegenteil von '''gleich''' ist dann '''ungleich''', das Gegenteil von '''größer''' ist '''kleiner''' und umgekehrt. | ||
+ | * Man könnte ''else'' also mit ''sonst'' übersetzen: Wenn...Sonst. | ||
+ | |||
+ | == Fallunterscheidungen == | ||
+ | * if-Abfragen kann man beliebig wiederholen. | ||
+ | * Bei sehr häufigen Abfragen kann das sehr unübersichtlich werden. | ||
+ | * Deshalb gibt es so genannte Fallunterscheidungen, in denen ein Wert oder eine Variable mehrfach geprüft wird. | ||
+ | * Bei Fallunterscheidungen wird jeder '''Bedingung ein Programmlauf''' zugeordnet. | ||
+ | * In C sind die entsprechenden Schlüsselwörter '''switch''' und '''case'''. | ||
+ | * Beispiel: Eine Zahl zwischen 1 und 3 soll als Wort ausgegeben werden: | ||
+ | <pre> | ||
+ | #include <stdio.h> | ||
+ | |||
+ | int iZahl; | ||
+ | |||
+ | int main () | ||
+ | { | ||
+ | printf ("Geben Sie eine Zahl ein: "); | ||
+ | scanf ("%d", &iZahl); | ||
+ | |||
+ | switch (iZahl) | ||
+ | { | ||
+ | case 1: printf ("Eins \n"); break; | ||
+ | case 2: printf ("Zwei \n"); break; | ||
+ | case 3: printf ("Drei \n"); break; | ||
+ | default: printf ("Zahl ist nicht zwischen 1 und 3! \n"); | ||
+ | } | ||
+ | } | ||
+ | </pre> | ||
+ | * Beachten Sie, dass nach der Ausführung eines Falles mit ''break'' die Abfrage verlassen werden '''muss'''. | ||
+ | * Wenn keine Bedingung zutrifft, wird der Code hinter ''default'' ausgeführt. | ||
+ | * In ''switch'' können keine Variablen vom Typ ''char'' geprüft werden! | ||
+ | |||
+ | == Schleifen mit Zähler == | ||
+ | * Bei Zählerschleifen werden Schlüsselwörter eine '''bestimmte Anzahl oft''' wiederholt. | ||
+ | * Dabei läuft eine Variable mit, die bei jedem Durchlauf '''verändert''' wird. | ||
+ | * In C ist das entsprechende Schlüsselwort '''for'''. | ||
+ | * Das Format von ''for'' ist | ||
+ | <pre>for (Startwert, Ablaufbedingung, Änderungsmaßnahme);</pre> | ||
+ | * Die Zahlen von 1 bis 10 werden also durch folgendes Programm ausgegeben: | ||
+ | <pre> | ||
+ | |||
+ | #include <stdio.h> | ||
+ | |||
+ | int nZaehler; | ||
+ | |||
+ | int main () | ||
+ | { | ||
+ | for (nZaehler = 1; nZaehler < 11; nZaehler++) | ||
+ | { | ||
+ | printf ("Zahl ist %d \n", nZaehler); | ||
+ | } | ||
+ | } | ||
+ | |||
+ | </pre> | ||
+ | * Am Anfang der Schleife wird nZaehler mit 1 belegt (der '''Startwert''') | ||
+ | * Die Schleife läuft so lange nZahler kleiner als 11 ist (die '''Ablaufbedingung''') | ||
+ | * Bei jedem Durchlaufen der Schleife wird nZaehler um 1 erhöht (die '''Änderungsmaßnahme''', ''nZaehler = nZaehler + 1'' kann man mit ''nZaehler++'' abkürzen). | ||
+ | * Beim Durchlaufen der Schleife wird alles zwischen den folgenden Klammern { und } ausgeführt (hier also die Ausgabe von nZaehler). | ||
+ | * Die Zahlen von 1 bis 10 werden nur ausgegeben, wenn die Ablaufbedingung ''< 11'' heißt, da am Anfang entschieden wird, ob die Schleife durchlaufen werden soll. | ||
+ | * for bildet also eine so genannte Kopfgesteuerte Schleife! | ||
+ | |||
+ | == Kopfgesteuerte Schleifen == | ||
+ | * Kopfgesteuerte Schleifen prüfen '''am Anfang''' der Schleife, ob die Schleife durchlaufen wird. | ||
+ | * Kopfgesteuerte Schleifen werden mit dem Wort ''while'' gebildet. | ||
+ | * Kopfgesteuerte Schleifen machen Sinn, wenn eine Schleife unter bestimmten Bedingungen keinen Sinn ergibt. | ||
+ | * Beispielsweise kann man eine Datei nicht auslesen, wenn am Anfang der Schleife das Ende der Datei bereits erreicht oder sie leer ist. | ||
+ | * Man könnte die Zahlen von 1 bis 10 auch mit einer kopfgesteuerten Schleife ausgeben: | ||
+ | <pre> | ||
+ | #include <stdio.h> | ||
+ | |||
+ | int nZaehler; | ||
+ | |||
+ | int main () | ||
+ | { | ||
+ | nZaehler = 0; | ||
+ | while (nZaehler < 10) | ||
+ | { | ||
+ | nZaehler++; | ||
+ | printf ("Zahl ist %d \n", nZaehler); | ||
+ | } | ||
+ | } | ||
+ | </pre> | ||
+ | * Sie werden alle Anweisungen aus der for-Schleife hier wiederfinden! | ||
+ | * Aber überlegen Sie mal, warum die Werte der Variablen anders sind. | ||
+ | |||
+ | == Fußgesteuerte Schleifen == | ||
+ | * Fußgesteuerte Schleifen prüfen '''am Ende''' der Schleife, ob die Bedingung zum Beenden erreicht ist. | ||
+ | * Fußgesteuerte Schleifen werden mit den Schlüsselwörter ''do''..''while'' gebildet. | ||
+ | * Fußgesteuerte Schleifen machen Sinn, wenn die Bedingung innerhalb der Schleife verändert wird. | ||
+ | * Beispielsweise kann eine Schleife so lange laufen, bis während der Schleife ein bestimmter Wert eingegeben wird. | ||
+ | * Die Zahlen von 1 bis 10 mit einer fußgesteuerten Schleife: | ||
+ | <pre> | ||
+ | #include <stdio.h> | ||
+ | |||
+ | int nZaehler; | ||
+ | |||
+ | int main () | ||
+ | { | ||
+ | nZaehler = 0; | ||
+ | do | ||
+ | { | ||
+ | nZaehler++; | ||
+ | printf ("Zahl ist %d \n", nZaehler); | ||
+ | } while (nZaehler < 10); | ||
+ | } | ||
+ | </pre> | ||
+ | * Beachten Sie, wo ein Semikolon gesetzt ist (und wo nicht). | ||
+ | |||
+ | == Dateien == | ||
+ | * Normalerweise kommt an dieser Stelle die Behandlung von Dateien. | ||
+ | * Programme können Dateien erzeugen, verwalten und löschen. | ||
+ | * Dateien werden heute aber "in Reinform" kaum noch benutzt. | ||
+ | * Daher verweise ich hier auf die [https://de.wikipedia.org/wiki/Embedded_SQL Einbettung von Datenbank-Befehlen in C-Programme]. | ||
+ | * Nutzen Sie Datenbanken wo Sie können. Dateien sind immer nur die zweitbeste Lösung! | ||
+ | * Sie brauchen keinen Datenbank-Server. Forschen Sie z. B. nach [https://de.wikipedia.org/wiki/SQLite SQLite]. | ||
+ | |||
+ | == Zahlenraten == | ||
+ | * Zum Schluss ein kleines Spiel, in dem Sie einige der erklärten Regeln betrachten können: | ||
+ | |||
+ | <pre> | ||
+ | |||
+ | // (1) zahlenraten.c - Ein kleines Spiel, bei dem der Computer sich eine Zahl | ||
+ | // ausdenkt und Sie diese erraten müssen. 27.04.2021 | ||
+ | |||
+ | // (2) Damit alle Befehle funktionieren, müssen wir sie dem C-Compiler | ||
+ | // bekannt machen. Denn viele Befehle kennt C nicht. Die werden dann | ||
+ | // aus sogenannten Standard-Bibliotheken eingelesen. | ||
+ | |||
+ | #include <stdio.h> // printf und scanf | ||
+ | #include <stdlib.h> // srand und rand | ||
+ | #include <time.h> // time | ||
+ | |||
+ | // (3) Jedes C-Programm hat einen Abschnitt (eine "Funktion") namens | ||
+ | // main. Hier beginnt und endet ein C-Programm immer. main muss immer | ||
+ | // da sein und muss immer main heißen! | ||
+ | |||
+ | int main () | ||
+ | { | ||
+ | |||
+ | // (4) Wir beschreiben ("deklarieren") Speicherstellen ("Variable"), die | ||
+ | // wir im Programm benutzen wollen mit möglichst aussagekräftigen Namen | ||
+ | // und einem Buchstaben am Beginn, der die Art des Inhalts bezeichnet. | ||
+ | // i = int = integer = ganze Zahl, also keine Fließkommazahlen | ||
+ | |||
+ | int iGedachteZahl; // Hier wird die vom Computer gedachte Zahl gespeichert | ||
+ | int iVermutung; // Hier wird die vom Benutzer vermutete Zahl gespeichert | ||
+ | |||
+ | // In C kann man Variable auch gleich mit einem Startwert belegen | ||
+ | |||
+ | int iZahlMin = 0; // Minimale Größe der gedachten Zahl | ||
+ | int iZahlMax = 100; // Maximale Größe der gedachten Zahl | ||
+ | |||
+ | // (5) Das Programm wurde gestartet. Wir geben einen Text aus: | ||
+ | // \n = mit Zeilenumbruch | ||
+ | // \n weglassen = ohne Zeilenumbruch | ||
+ | |||
+ | printf ("Zahlenraten - Ich denke mir eine Zahl und Sie erraten diese. \n"); | ||
+ | printf ("Ich denke mir also eine Zahl zwischen %d und %d", iZahlMin, iZahlMax); | ||
+ | |||
+ | // (6) Zufallszahl generieren: hier rufen wir die Funktionen auf, die wir | ||
+ | // bei (2) mit #include oben bekannt gemacht haben: srand, time und rand. | ||
+ | |||
+ | srand (time (0)); | ||
+ | iGedachteZahl = (rand() % (iZahlMax - iZahlMin + 1)) + iZahlMin; | ||
+ | |||
+ | printf ("...fertig. \n"); // wird in der selben Zeile wie (5) ausgegeben | ||
+ | |||
+ | // (7) Eine Schleife: die Anweisungen in den Klammern nach do | ||
+ | // werden immer wiederholt ... | ||
+ | |||
+ | do { | ||
+ | |||
+ | printf ("Ihre Vermutung? "); | ||
+ | scanf ("%d", &iVermutung); | ||
+ | |||
+ | if (iVermutung > iGedachteZahl) { | ||
+ | printf ("Die Zahl ist kleiner! \n"); | ||
+ | }; | ||
+ | |||
+ | if (iVermutung < iGedachteZahl) { | ||
+ | printf ("Die Zahl ist größer! \n"); | ||
+ | } | ||
+ | |||
+ | } while (iVermutung != iGedachteZahl); | ||
+ | |||
+ | // ... solange iVermutung ungleich iGedachteZahl ist, sonst zurück zu (7) | ||
+ | |||
+ | // (8) Hierher kommt der Computer nur, wenn iVermutung gleich iGedachteZahl ist, | ||
+ | // die Zahl vom Benutzer also erraten wurde | ||
+ | |||
+ | printf ("Richtig geraten!!!! Es war die %d!", iGedachteZahl); | ||
+ | |||
+ | // (9) Unser Programm ist beendet. 0 zurück geben an das Betriebssystem, | ||
+ | // damit es erkennt, dass das Programm fehlerfrei abgelaufen ist | ||
+ | |||
+ | return 0; | ||
+ | } | ||
+ | </pre> |
Aktuelle Version vom 1. Februar 2024, 12:11 Uhr
Inhaltsverzeichnis
- 1 Grundsätzliches Wissen für angehende Programmierer/-innen
- 2 Besonderheiten von C
- 3 Programmieren in C auf dem eigenen Computer
- 4 Funktionen
- 5 Variable
- 6 Ein- und Ausgabe
- 7 Bedingungen
- 8 Fallunterscheidungen
- 9 Schleifen mit Zähler
- 10 Kopfgesteuerte Schleifen
- 11 Fußgesteuerte Schleifen
- 12 Dateien
- 13 Zahlenraten
Grundsätzliches Wissen für angehende Programmierer/-innen
- Jede Anwendung eines persönlichen Computers, jede Website, jede App ist ein Computerprogramm.
- Computerprogramme sind Listen von Anweisungen, die vom Computer der Reihe nach abgearbeitet werden.
- Diese Listen werden in ein Textprogramm eingegeben, in Bits und Bytes übersetzt und dann ausgeführt.
- Anweisungen in Programmen bestehen aus Schlüsselwörtern und Parametern, die die Anweisungen genauer spezifizieren.
- Ein Beispiel "aus dem richtigen Leben" wäre Starte das Auto, wobei Starte das Schlüsselwort und das Auto der Parameter ist.
- Ein Schlüsselwort sagt dem Computer, was zu tun ist, ein Parameter erklärt, womit etwas zu tun ist.
Besonderheiten von C
- C ist eine sehr kompakte Programmiersprache von immerhin 1968.
- Sie ist damit oft älter als ihre Programmierer. :-)
- C wird auch heute noch benutzt.
- Sehr viele große Projekte sind in C geschrieben (Windows, Linux, Office).
- Dennoch laufen sehr viele C-Programme aus alter Zeit unverändert auch heute noch.
- C ist also sehr kompatibel zu sich selbst.
- C ermöglicht es, sehr kleine und schnelle Compiler zu bauen, denn
- die Prüfung von 10.000 Klammern ({}) schafft der Compiler schnell.
- die Prüfung von 10.000 Wörtern (BEGIN...END) dauert dagegen länger.
- C ist eine Sprache, die auf sehr kleinen Computern gut ablaufen kann.
- C++ ist eine objektorientierte Version von C.
- Compiler für C++ können immer auch C.
Programmieren in C auf dem eigenen Computer
- Um ein Programm in einer Programmiersprache zu schreiben, braucht man ein passendes Übersetzungsprogramm für diese Sprache.
- Solche Übersetzungsprogramme übersetzen eine Programmiersprache in die universelle Sprache aller Computer (Bits und Bytes).
- Solcher Übersetzungsprogramme heißen Compiler.
- Man benötigt also für C einen C-Compiler und
- einen Editor (Textverarbeitung für Programmierer) zum Erfassen des Programms oder
- am besten alles zusammen: eine "Integrierte Entwicklungsumgebung (IDE)".
- Ich zum Beispiel benutze diese hier (Windows, MacOS).
- Auf einem Raspberry Pi kann man einfach Geany benutzen.
- Oder Sie programmieren einfach hier und jetzt online.
Funktionen
- Ein Problem wird zur Lösung in viele kleine Probleme zerlegt.
- Beispiel: "Kuchen backen" kann in "Mische Mehl, Eier...", "Heize den Backofen", "Knete den Teig" etc. aufgeteilt werden.
- Programme können in kleine Abschnitte eingeteilt werden, die einzelne Unter-Aufgaben erfüllen (Funktionen).
- Diese Funktionen haben einen festgelegten Namen, Parameter und können Werte an das Hauptprogramm zurück geben.
- Den Typ des Rückgabewertes steht vor der Funktion (hier: int = integer = ganze Zahlen).
- main ist die erste Funktion, die in jedem Programm aufgerufen wird. Hier startet also immer das Programm.
- In C-Programmen muss es immer genau eine Funktion mit dem Namen main geben.
- Von main aus werden die erwähnten Funktionen des selben Programms aufgerufen, sofern welche existieren.
- Die Hauptfunktion, das ganze Programm, gibt nach der Abarbeitung des Programms einen Wert an den Computer zurück.
- Ein einfaches Programm sieht also jetzt so aus ("//" leitet einen Kommentar ein):
int main () { // Hier startet das Hauptprogramm printf ("Zahlenraten - ich denke mir eine Zahl und Du errätst sie. \n"); }
Variable
- Variable sind benannte Speicherstellen, in denen Zwischenergebnisse gespeichert werden können.
- Variable müssen dem C-Compiler erklärt werden, damit sie verwendet werden können: sie werden deklariert.
- Da Programme linear (von oben nach unten) ablaufen, sind Variablen erst ab der Deklaration nutzbar.
- Der Compiler muss wissen, was in den Variablen stehen soll: der Variablentyp.
- Typen für Variable in C: Ganzzahlen (int), Fließkommazahlen (float), Zeichen (char)
- Eine Deklaration sieht typischerweise so aus: <Typ><Leerzeichen><Name><Semikolon>
- Beispiel:
int nGedachteZahl;
- Das "n" vor dem Namen "GedachteZahl" ist nicht notwendig. Es ist aber gute Sitte, den Typ (int, also numerisch) im Namen zu erwähnen.
- Variable können auch einen Anfangswert (Initialisierung) enthalten, der einfach dahinter geschrieben wird.
- Beispiel:
int nGedachteZahl = 24;
- Die Variable nGedachteZahl ist dem Compiler ab diesem Zeitpunkt als Ganzzahl-Speicherstelle bekannt und hat den Wert 24.
- Eine nicht initialisierte Variable hat übrigens nicht den Wert Null sondern einen unbestimmten Wert (Vorsicht!).
- In unserem Beispiel brauchen wir zwei Variable: in einer steht die gedachte Zufallszahl, in der anderen die Vermutung des Benutzers.
- Nach der Erwähnung des Datentyps kann man weitere Variablen definieren.
- Unser Programm sieht bis hierher also so aus:
int nGedachteZahl = 24; // muss erraten werden nVermutung = 0; // sicher ist sicher int main () { // Hier startet das Hauptprogramm printf ("Zahlenraten - ich denke mir eine Zahl und Du errätst sie. \n"); }
Ein- und Ausgabe
- Ein Programm braucht grundsätzlich Anweisungen für die Eingabe, die Verarbeitung und die Ausgabe von Daten.
- Speziell in der Programmiersprache C gibt es keine Anweisungen zur Ein- und Ausgabe.
- C soll auf sehr vielen Computern nutzbar sein und jedes Computersystem hat andere Funktionen für Ein- und Ausgabe.
- Deshalb liegt jedem C-Compiler eine Bibliothek von Dateien bei, die Ein- und Ausgabe des jeweiligen Computersystems ermöglicht.
- Die Funktionen in diesen Dateien werden aber alle in der gleichen Art und Weise aufgerufen ("C-Standard-Bibliotheken").
- Wir verwenden hier zur Eingabe das Schlüsselwort scanf und zur Ausgabe printf wegen ihrer Ähnlichkeit.
- Im "echten Leben" tun Sie das bitte nicht: die Funktionen sind nicht krisensicher.
- Das Format von printf ist
printf ("<Format>", <Variable>, <Variable>...)
- Im <Format>-Teil geben Sie an, was ausgegeben werden soll.
- Dabei schaffen Sie Platzhalter dort, wo später der Wert der Variablen erscheinen soll.
- Platzhalter bestehen aus einem Prozentzeichen und einem Buchstaben für den Typ der Variable.
- Die erlaubten Typen sind vielfältig. Hier einige gebräuchliche:
d Dezimalzahl f Gleitkommazahl c Einzelnes Zeichen s String (Mehrere Zeichen)
- Nach der Angabe des Typs sind auch Längenangaben u. a. möglich.
- Dieselben Formatvorschriften gelten auch für Eingaben mit scanf.
Bedingungen
- Bedingungen sind WENN-DANN-Anweisungen.
- In C ist das entsprechende Schlüsselwort if.
- Der weitere Programmlauf hängt dann von Bedingungen ab:
> größer als < kleiner als == gleich != ungleich >= größer oder gleich <= kleiner oder gleich ! nicht
- Beispiel: Ob eine eingegebene Zahl größer oder kleiner 1 ist soll in Worten ausgegeben werden:
#include <stdio.h> int nZahl; int main() { printf ("Bitte geben Sie eine Zahl ein: "); scanf ("%d", &nZahl); if (nZahl > 1) printf ("Die Zahl %d ist größer als Eins. \n", nZahl); else printf ("Die Zahl %d ist kleiner als Eins. \n", nZahl); }
- Die Befehle nach else werden immer ausgeführt, wenn das Gegenteil der Bedingung erfüllt ist.
- Das Gegenteil von gleich ist dann ungleich, das Gegenteil von größer ist kleiner und umgekehrt.
- Man könnte else also mit sonst übersetzen: Wenn...Sonst.
Fallunterscheidungen
- if-Abfragen kann man beliebig wiederholen.
- Bei sehr häufigen Abfragen kann das sehr unübersichtlich werden.
- Deshalb gibt es so genannte Fallunterscheidungen, in denen ein Wert oder eine Variable mehrfach geprüft wird.
- Bei Fallunterscheidungen wird jeder Bedingung ein Programmlauf zugeordnet.
- In C sind die entsprechenden Schlüsselwörter switch und case.
- Beispiel: Eine Zahl zwischen 1 und 3 soll als Wort ausgegeben werden:
#include <stdio.h> int iZahl; int main () { printf ("Geben Sie eine Zahl ein: "); scanf ("%d", &iZahl); switch (iZahl) { case 1: printf ("Eins \n"); break; case 2: printf ("Zwei \n"); break; case 3: printf ("Drei \n"); break; default: printf ("Zahl ist nicht zwischen 1 und 3! \n"); } }
- Beachten Sie, dass nach der Ausführung eines Falles mit break die Abfrage verlassen werden muss.
- Wenn keine Bedingung zutrifft, wird der Code hinter default ausgeführt.
- In switch können keine Variablen vom Typ char geprüft werden!
Schleifen mit Zähler
- Bei Zählerschleifen werden Schlüsselwörter eine bestimmte Anzahl oft wiederholt.
- Dabei läuft eine Variable mit, die bei jedem Durchlauf verändert wird.
- In C ist das entsprechende Schlüsselwort for.
- Das Format von for ist
for (Startwert, Ablaufbedingung, Änderungsmaßnahme);
- Die Zahlen von 1 bis 10 werden also durch folgendes Programm ausgegeben:
#include <stdio.h> int nZaehler; int main () { for (nZaehler = 1; nZaehler < 11; nZaehler++) { printf ("Zahl ist %d \n", nZaehler); } }
- Am Anfang der Schleife wird nZaehler mit 1 belegt (der Startwert)
- Die Schleife läuft so lange nZahler kleiner als 11 ist (die Ablaufbedingung)
- Bei jedem Durchlaufen der Schleife wird nZaehler um 1 erhöht (die Änderungsmaßnahme, nZaehler = nZaehler + 1 kann man mit nZaehler++ abkürzen).
- Beim Durchlaufen der Schleife wird alles zwischen den folgenden Klammern { und } ausgeführt (hier also die Ausgabe von nZaehler).
- Die Zahlen von 1 bis 10 werden nur ausgegeben, wenn die Ablaufbedingung < 11 heißt, da am Anfang entschieden wird, ob die Schleife durchlaufen werden soll.
- for bildet also eine so genannte Kopfgesteuerte Schleife!
Kopfgesteuerte Schleifen
- Kopfgesteuerte Schleifen prüfen am Anfang der Schleife, ob die Schleife durchlaufen wird.
- Kopfgesteuerte Schleifen werden mit dem Wort while gebildet.
- Kopfgesteuerte Schleifen machen Sinn, wenn eine Schleife unter bestimmten Bedingungen keinen Sinn ergibt.
- Beispielsweise kann man eine Datei nicht auslesen, wenn am Anfang der Schleife das Ende der Datei bereits erreicht oder sie leer ist.
- Man könnte die Zahlen von 1 bis 10 auch mit einer kopfgesteuerten Schleife ausgeben:
#include <stdio.h> int nZaehler; int main () { nZaehler = 0; while (nZaehler < 10) { nZaehler++; printf ("Zahl ist %d \n", nZaehler); } }
- Sie werden alle Anweisungen aus der for-Schleife hier wiederfinden!
- Aber überlegen Sie mal, warum die Werte der Variablen anders sind.
Fußgesteuerte Schleifen
- Fußgesteuerte Schleifen prüfen am Ende der Schleife, ob die Bedingung zum Beenden erreicht ist.
- Fußgesteuerte Schleifen werden mit den Schlüsselwörter do..while gebildet.
- Fußgesteuerte Schleifen machen Sinn, wenn die Bedingung innerhalb der Schleife verändert wird.
- Beispielsweise kann eine Schleife so lange laufen, bis während der Schleife ein bestimmter Wert eingegeben wird.
- Die Zahlen von 1 bis 10 mit einer fußgesteuerten Schleife:
#include <stdio.h> int nZaehler; int main () { nZaehler = 0; do { nZaehler++; printf ("Zahl ist %d \n", nZaehler); } while (nZaehler < 10); }
- Beachten Sie, wo ein Semikolon gesetzt ist (und wo nicht).
Dateien
- Normalerweise kommt an dieser Stelle die Behandlung von Dateien.
- Programme können Dateien erzeugen, verwalten und löschen.
- Dateien werden heute aber "in Reinform" kaum noch benutzt.
- Daher verweise ich hier auf die Einbettung von Datenbank-Befehlen in C-Programme.
- Nutzen Sie Datenbanken wo Sie können. Dateien sind immer nur die zweitbeste Lösung!
- Sie brauchen keinen Datenbank-Server. Forschen Sie z. B. nach SQLite.
Zahlenraten
- Zum Schluss ein kleines Spiel, in dem Sie einige der erklärten Regeln betrachten können:
// (1) zahlenraten.c - Ein kleines Spiel, bei dem der Computer sich eine Zahl // ausdenkt und Sie diese erraten müssen. 27.04.2021 // (2) Damit alle Befehle funktionieren, müssen wir sie dem C-Compiler // bekannt machen. Denn viele Befehle kennt C nicht. Die werden dann // aus sogenannten Standard-Bibliotheken eingelesen. #include <stdio.h> // printf und scanf #include <stdlib.h> // srand und rand #include <time.h> // time // (3) Jedes C-Programm hat einen Abschnitt (eine "Funktion") namens // main. Hier beginnt und endet ein C-Programm immer. main muss immer // da sein und muss immer main heißen! int main () { // (4) Wir beschreiben ("deklarieren") Speicherstellen ("Variable"), die // wir im Programm benutzen wollen mit möglichst aussagekräftigen Namen // und einem Buchstaben am Beginn, der die Art des Inhalts bezeichnet. // i = int = integer = ganze Zahl, also keine Fließkommazahlen int iGedachteZahl; // Hier wird die vom Computer gedachte Zahl gespeichert int iVermutung; // Hier wird die vom Benutzer vermutete Zahl gespeichert // In C kann man Variable auch gleich mit einem Startwert belegen int iZahlMin = 0; // Minimale Größe der gedachten Zahl int iZahlMax = 100; // Maximale Größe der gedachten Zahl // (5) Das Programm wurde gestartet. Wir geben einen Text aus: // \n = mit Zeilenumbruch // \n weglassen = ohne Zeilenumbruch printf ("Zahlenraten - Ich denke mir eine Zahl und Sie erraten diese. \n"); printf ("Ich denke mir also eine Zahl zwischen %d und %d", iZahlMin, iZahlMax); // (6) Zufallszahl generieren: hier rufen wir die Funktionen auf, die wir // bei (2) mit #include oben bekannt gemacht haben: srand, time und rand. srand (time (0)); iGedachteZahl = (rand() % (iZahlMax - iZahlMin + 1)) + iZahlMin; printf ("...fertig. \n"); // wird in der selben Zeile wie (5) ausgegeben // (7) Eine Schleife: die Anweisungen in den Klammern nach do // werden immer wiederholt ... do { printf ("Ihre Vermutung? "); scanf ("%d", &iVermutung); if (iVermutung > iGedachteZahl) { printf ("Die Zahl ist kleiner! \n"); }; if (iVermutung < iGedachteZahl) { printf ("Die Zahl ist größer! \n"); } } while (iVermutung != iGedachteZahl); // ... solange iVermutung ungleich iGedachteZahl ist, sonst zurück zu (7) // (8) Hierher kommt der Computer nur, wenn iVermutung gleich iGedachteZahl ist, // die Zahl vom Benutzer also erraten wurde printf ("Richtig geraten!!!! Es war die %d!", iGedachteZahl); // (9) Unser Programm ist beendet. 0 zurück geben an das Betriebssystem, // damit es erkennt, dass das Programm fehlerfrei abgelaufen ist return 0; }