Informatik: Abschnitt 4 Inhalt: 4. Programmiersprache C 4.1 Programmaufbau in C 4.2 Basisdatentypen und einfache Anweisungen 4.3 Steuerfluss-Konstrukte 4.4 Arbeit mit indizierten Größen (Felder) und Zeiger 4.5 Zeichen und Zeichenketten 4.6 Funktionen (Unterprogramme) 4.7 Strukturen (Datensätze) 4.8 Typen, Variable und Konstante Danach folgen noch Abschnitte zu: Funktionen der Standardbibliothek, Speicherverwaltung, Datei-Ein und -Ausgabe Peter Sobe 1 Programmiersprache C Die C-Sprachfamilie: K&R – C (1972, Kerningham-/Ritchie, Entwickler von C) ANSI/ISO-C89 ANSI/ISO-C99 Weiterentwickelt zu C++ C++ (1985, Bjarne Stroustrup) ANSI/ISO-C++ 98 ANSI/ISO-C++ 0x Weitere C-ähnliche Sprachen: Java – C++-ähnliche Programmiersprache, SUN 1995 C# – C++-ähnlich, Microsoft 2001 Peter Sobe 2 Programmiersprache C Imperative Programmiersprache: C-Anweisungen werden in der im Programm angegebenen Reihenfolge ausgeführt: zeilenweise (von oben nach unten) innerhalb Zeile möglicherweise mehrere Anweisungen, dann von links nach rechts Steuerfluss-Anweisungen (if, for, while, repeat, break, continue) zur Beeinflussung der Abarbeitungsreihenfolge Zum Vergleich: manch andere Programmiersprachen (logische und funktionale, beispielsweise PROLOG) arbeiten die Ausdrücke nicht notwendigerweise in der im Programm angegebenen Reihenfolge ab. Peter Sobe 3 Programmiersprache C Ein Programm besteht aus: Variablenvereinbarungen: hier werden Bezeichner für die Verarbeitungselemente festgelegt. Es wird ein Typ für jede Variable angegeben, z.B. Ganzzahl (int) oder Zeichen (char) Anweisungen: zur Verarbeitung der Variablen zur Beeinflussung des Steuerflusses Mehrfach auftretende Anweisungsfolgen werden oft in Funktionen gekapselt. Eine Hauptfunktion (main-Funktion) ist der Punkt, an dem mit der Ausführung eines C-Programms begonnen wird. Peter Sobe 4 Programmiersprache C Peter Sobe ausführbarer Code Bibliotheken Linker Maschinencode Compiler (2. Stufe) Assembler Programm C-Compiler C-Programm C-Präprozessor Header vorgegebene C-Programm Vor dem Ausführen des Programms: 5 Inhalt Inhalt: 4. Programmiersprache C 4.1 Programmaufbau in C 4.2 Basisdatentypen und einfache Anweisungen 4.3 Steuerfluss-Konstrukte 4.4 Arbeit mit indizierten Größen (Felder) und Zeiger 4.5 Zeichen und Zeichenketten 4.6 Funktionen (Unterprogramme) 4.7 Strukturen (Datensätze) 4.8 Typen, Variable und Konstante Peter Sobe 6 4.1 Programm-Aufbau in C // Beispielprogramm fakultaet.c #include <stdio.h> Kommentar Include-Präprozessor-Anweisung int main() { int fakultaet; int i,n; main-Funktion printf("Geben Sie bitte n ein >"); scanf("%d",&n); fakultaet = 1; for (i=2;i<=n;i++) fakultaet = fakultaet * i; Variablen-Deklarationen Anweisungen printf("Die Fakultaet von %d betraegt %d \n",n, fakultaet); return 1; SteuerflussAnweisung } Peter Sobe 7 Kommentare Zur Kommentierung gibt es in C++ (nicht in C) die Zeichenfolge „//“ (sog. Inline-Kommentare). Alles ab hier, bis zum Ende der Zeile wird vom Compiler als Kommentar betrachtet: int anzahl = 0; // Zähler für die Anzahl der Häuser, // die ein weißes Dach haben int i; Bei den Kommentarzeichen “/*” wird alles bis zu den Kommentarendezeichen “*/” als Kommentar vom Compiler überlesen (in C und C++): int anzahl = 0; /* Zähler für die Anzahl der Häuser, die ein weißes Dach haben */ int i; Peter Sobe 8 Kommentare Kommentare in Kommentaren Kommentare der Form „/*...*/“ können nicht geschachtelt werden: /* int anzahl = 0; /* Zähler für die Anzahl der Häuser, die ein weißes Dach haben */ int i;*/ falsch Inline-Kommentare können dagegen in Kommentaren der Form „/*...*/“ geschachtelt werden: /* int anzahl = 0; // Zähler für die Anzahl der Häuser, // die ein weißes Dach haben int i; */ richtig Probleme, wenn Codeteile durch Auskommentieren deaktiviert werden müssen! Peter Sobe 9 Präprozessor-Anweisungen Präprozessor-Anweisungen beginnen mit ‚#‘ und werden vor der Übersetzung verarbeitet Hier können z.B.Text-Ersetzungen vorgenommen werden. #define EPS 0.000001 …. if ( diff < EPS ) return value; else { /* berechne weitere Werte */ …} Einbinden von so genannten Header-Dateien (*.h) zur Bekanntgabe von Funktionsinterfaces, z.B. #include <stdio.h> Peter Sobe 10 Präprozessor-Anweisungen Präprozessor-Anweisungen können zur Versionierung des Codes benutzt werden #ifdef VERSION_1 int a = 0,b = 0, c =0; // hier alles mit Integerzahlen #endif #ifdef VERSION_2; float a = 0.0, b = 0.0, c = 0.0; // jetzt alles mit Fließkommazahlen #endif Präprozessor-Anweisungen auch zum “Auskommentieren“ von Code – anstelle geschachtelter Kommentare Peter Sobe #ifdef IRGENDETWAS_UNDEFINIERTES int anzahl = 0; // Zähler für die Anzahl der Häuser, // die ein weißes Dach haben int i; #endif 11 Die main-Funktion Der Beginn der main-Funktion ist der Startpunkt des Programms. Die main-Funktion kann aus dem Aufruf des Programms Parameter übernehmen Das Ende der main-Funktion bedeutet das Ende des Programmlaufs. int main() { // hier beginnt die Verarbeitung … return 1; // hier ist alles zu Ende } exit oder return aus der main-Funktion bedeutet auch das Ende der Programmverarbeitung Peter Sobe 12 Die Form eines C-Progamms C ist eine formatfreie Sprache, d.h. das Aussehen, Zeilenumbrüche, Einrückungen haben keinen Einfluss auf die Funktion. Beispiele: main() { scanf("%d",&a); main() printf(" quadrat = %d\n", a*a); { return 1; } scanf("%d",&a); printf(" quadrat = %d\n", a*a); return 1; } Trotzdem sollte Code wie links dargestellt aussehen, um bessere Lesbarkeit zu gewährleisten. Peter Sobe 13 Inhalt Inhalt: 4. Programmiersprache C 4.1 Programmaufbau in C 4.2 Basisdatentypen und einfache Anweisungen 4.3 Steuerfluss-Konstrukte 4.4 Arbeit mit indizierten Größen (Felder) und Zeiger 4.5 Zeichen und Zeichenketten 4.6 Funktionen (Unterprogramme) 4.7 Strukturen (Datensätze) 4.8 Typen, Variable und Konstante Peter Sobe 14 4.2 Basisdatentypen und einfache Anweisungen Die Verarbeitung erfolgt durch Anweisungen, die die Werte der Variablen verändern. Variablen können Zahlenwerte, logische Werte (wahr, falsch), Zeichen, Zeichenketten, Zeiger, Felder aufnehmen Variablen müssen vor ihrer ersten Benutzung auf jeden Fall deklariert worden sein. Bezeichner (Namen für Variable, Funktionen, ...) • Namen beginnen mit einem Buchstaben oder einem Unterstrich. • Die weiteren Zeichen sind Buchstaben, Zahlen oder Unterstriche. • Schlüsselworte der Sprache dürfen nicht als Name verwendet werden Peter Sobe 15 Variablennamen Zulässige Variablennamen: • a; i; j; k; • _pointer; • ganz_langer_name_24_undNochLaenger; • name; Name; // Groß- und Kleinschreibung wird unterschieden Nicht als Variablenname zulässig: • 34Name; // Fehler Zahl am Anfang nicht erlaubt • Strassen Name; // Leerzeichen nicht erlaubt: Strassen_Name • Ölinhalt // Fehler, Umlaute verboten • C&A; // Fehler; Sonderzeichen verboten • while; // da es ein Schlüsselwort while bereits gibt Variablenname sollten kurz sein, aber inhaltlich ihre Bedeutung wiedergeben Peter Sobe 16 Variablennamen Variablenname sollten kurz sein, aber inhaltlich ihre Bedeutung wiedergeben, z.B. int anzahl_patienten; float gewicht; Indexvariable und Zähler werden oft mit i, j, k oder z bezeichnet. Beispiele für schlecht gewählte Variablennamen: int meinkleinerschleifenzähler=0; int grosserschleifenzaehler; Peter Sobe 17 Schlüsselwörter Folgende C-Schlüsselworte dürfen nicht als Variablennamen benutzt werden: auto double int struct break else long switch case enum register typedef char extern return union const float short unsigned continue for signed void default goto sizeof volatile do if static while In C++ weitere Schlüsselwörter: asm export private true bool false protected try catch friend public typeid class inline reinterpret_cast typename const_cast mutable static_cast using delete namespace template virtual dynamic_cast new this wchar_t explicit operator throw Peter Sobe 18 Konstanten Konstanten und Zeichenfolgen (Literale) Konstanten sind • ganze Zahlen, z.B. 123, -465, 033, 0xab, 0XFF, 123L, 123UL, • Gleitkommazahlen, z.B. 12.34, 12.45e-3, 0123, 1e20, • Zeichenkonstanten, z.B. ‘a‘, ‘X‘, ‘\07‘, ‘\xb‘ und • Aufzählungswerte, z.B. rot, Montag, ... (wenn vorher entsprechend definiert) Zeichenfolgen sind z.B. • "Guten Morgen" (besteht aus Ein-Byte-Zeichen) und • L"Guten Morgen" (besteht aus Mehr-Byte-Zeichen) Peter Sobe 19 Operatoren Operatoren zur Anwendung auf eine oder zwei Variablen: [] () . -> ++ -- & * + - ~ ! sizeof / % << >> < > <= >= == != ^ | && || ? : = *= /= %= += -= <<= >>= &= ^= |= Beispiele: a++; // a=a+1; if (aussage1 && aussage2) {printf("zwei Aussagen \n");} // logisch UND glück = liebe || geld; // logisch ODER Interpunktionszeichen in C: { } . ; Peter Sobe 20 Trennzeichen (white spaces) Trennzeichen der Sprache C sind: Zwischenraum (space, blank), horizontaler Tabulator, neue Zeile vertikaler Tabulator, Seitenvorschub (form feed) → siehe formatfreie Sprache Leerzeichen und Zeilenumbrüche dürfen in C / C++ an beliebiger Stelle außer in Namen stehen: int var_i=17; int var_i = 17; int var_i = 17; int var_ i=17; // ist aber verboten Peter Sobe 21 Elementare Datentypen (1) Wertebereich Genauigkeit char = signed char unsigned char 1 Byte 1 Byte -2^7 ... +2^7-1 0 ... 2^8-1 2 Dezimalstellen, z.B. ‚88‘ ist genau int = signed int unsigned int 4 Byte 4 Byte -2^31 ... +2^31-1 0 ... 2^32-1 9 Dezimalstellen short int = signed short int unsigned short int 2 Byte 2 Byte -2^15 ... +2^15-1 0 ... 2^16-1 4 Dezimalstellen long int = signed long int unsigned long int 8 Byte 8 Byte -2^63 ... +2^63-1 0 ... 2^64-1 19 Dezimalstellen (ab C99, 64 Bit) bool (nur C++) 1 Byte {true,false} Die angegebenen Werte stellen Beispiele für 32-Bit Umgebungen dar, sie sind implementierungsabhängig Peter Sobe 22 Elementare Datentypen (2) Wertebereich Genauigkeit enum { list } enum id { list } enum id 4 Byte 4 Byte 4 Byte 2^32 verschiedene Werte float double long double 4 Byte 8 Byte 10 Byte ca. -10^38 ... +10^38 ca. –10^308 ... +10^308 ca. -10^4932 ... +10^4932 6 Dezimalstellen 15 Dezimalstellen 19 Dezimalstellen type* void* 4 Byte 4 Byte 0...2^32-1 0...2^32-1 einzelne Bytes im Speicher adressierbar type& 4 Byte 0...2^32-1 Peter Sobe 23 Elementare Datentypen (3) Datentypen für ganze Zahlen in C: int, signed int, unsigned int, long, signed long, unsigned long, short, signed short, unsigned short Beispiel: int i = -64; long li = 3; Integer-Variablen werden für beispielsweise für zählbare Dinge benutzt, oder für Index-Berechnungen. Peter Sobe 24 Elementare Datentypen (4) Gleitkommazahlen: float, double, long double Beispiele: double d = 64.3345; double d1 = 1.234e-22; // ohne Leerzeichen zu schreiben float f = 67.31f; float f1 = 2.9744e-22f; double x = 5.; // 5. entspricht 5.0 Gleitkommazahlen werden für Eigenschaften, Größen verwendet, die als rationale oder reelle Zahlen angegeben werden, z.B. Spannung (=4.5 V). Peter Sobe 25 Elementare Datentypen (5) Wahrheitswerte (bool) mit den Werten true und false (nur C++) Beispiele: bool gefunden = true; bool ende = false; Einzelne Zeichen (char) - die Werte entsprechen in der Regel dem ASCII-Zeichensatz Beispiele: char c = 64; char c1 = ‘h’; char c2 = ‘\n’; Peter Sobe Spezielle Zeichenkonstanten: Zeilenvorschub: ‘\n’ Horizontaler Tabulator: ‘\t‘ Backslash: ‘\\’ Fragezeichen: ‘\?’ Einfaches Anfuehrungszeichen: ‘\’’ Doppeltes Anfuehrungszeichen: ‘\”’ 26 Elementare Datentypen (6) Einzelne Zeichen (char) können auch zur Aufnahme von ganzzahligen Werten benutzt werden: unsigned char … kann 0 bis 255 repräsentieren (vorzeichenlos) char … kann Werte von -128 bis +127 repräsentieren Ob eine char-Variable als Zeichen, oder als Zahl benutzt wird, hängt immer vom Kontext ab. Benutzung als Zahlenwert: Benutzung als Zeichen: char z; int i=0; do { z= getchar(); // Eingabe Zeichen if (z!=‘x‘) i = i+1; else break; } while (true); Peter Sobe char z=0; do { if (z<12) printf(“ %d Uhr morgens\n“,z); else if (z==12) printf(“ %d Uhr mittags\n“,z); else printf(“ %d Uhr nachmittags\n“,z-12); z = z + 1; 27 } while (z<24); Konstanten Die Verwendung von Konstanten erhöht die Lesbarkeit des Programms und macht es änderungsfreundlicher Anstatt: umfang = 2 * radius * 3.14159; Besser: const double PI = 3.14159; umfang = 2 * radius * PI; const heißt nur, dass die Variable nicht mehr verändert werden darf, der Wert muss nicht schon zur Übersetzungs-Zeit bestimmt werden können. Beispiel: const double UmfangMeinKreis = 2.0 * radius * PI; // radius muss keine Konstante sein Peter Sobe 28 Konstanten Guter Programmierstil ist es, außer den Konstanten –1, 0 und 1 keine expliziten Zahlenkonstanten in seinem Programm zu verwenden, sondern diese immer über const einen Namen zuzuweisen. Anstatt: for (int i=0;i<10;i++) spieler[i].anzahl_huetchen= … Besser: const int ANZAHL_DER_MITSPIELER = 10; … for (int i=0; i < ANZAHL_DER_MITSPIELER; i++) spieler[i].anzahl_huetchen=… Peter Sobe 29 Typkonvertierungen Ohne Angabe hat eine Gleitkommakonstante den Typ double. double d = 0.6; float f = 0.6; ... d = f; // ergibt keine Warnung f = d; // ergibt eine Warnung Bei einer Zuweisung eines double an ein float wird eine Warnung erwartet: float ff = 0.5987654321987; // kann man mal ausprobieren Peter Sobe 30 Interne Darstellung von Gleitkommazahlen 0.6 ist im Binärsystem: 1001 1001 1001 1001 1001 1001 1001 1001 ... 32 Bits (Mantisse genannt) Dieses bedeutet: 1* 1/2 + 0 * 1/4 + 0 *1/8 + 1 * 1/ 16 + 1* 1/ 32 ... * 1/268435456 und ergibt: 0.59999999776482500000 Wenn float nur 24-Bit zur Darstellung der Mantisse verwendet (ist üblich, da normalerweise noch 8 Bit zur Darstellung des Exponenten verwendet werden), ist die Genauigkeit noch etwas geringer. Die Zuweisung dieser 24 Bit-Genauigkeit an eine double-Zahl ergibt somit eine Warnung Peter Sobe 31 Explizite Typkonvertierungen In einigen Fällen ist eine explizite Typkonvertierung unbedingt erforderlich: int a = 5; int b = 2; // In C/C++ double x = ((double) a ) / ((double) b); // x ist 2.5, sonst 2.0 In C++ auch erlaubt: double x = double(a) / double(b) // In C++ empfehlenswert: double x = static_cast<double>(a) / static_cast<double>(b); Peter Sobe 32 Aufzählungstypen Manchmal ist es sinnvoll, eine Vielzahl gleichartiger Konstanten zu einer Menge zusammenzufassen. Jedes Element dieser Menge bekommt eine Ordinalzahl Das erste Element erhält z.B. die Ordinalzahl 0, das zweite 1 usw., Beispiel: enum Wochentag { Mon, Die, Mit, Don, Fri, Sam, Son }; Wochentag Tag; Tag = Mon; Syntax von Aufzählungen: enum AufzTyp { Bezeichnerl, Bezeichner2, ... } Variable; enum { Bezeichnerl, Bezeichner2, ... } Variable; enum AufzTyp { Bezeichnerl = 2, Bezeichner2, ... }; Peter Sobe 33 Operatoren (1) Binäre Operatoren + * / % Addition Subtraktion Multiplikation Division Divisionsrest < <= == != >= > Vergl. auf kleiner Vergl. auf kleiner oder gleich Vergl. auf gleich Vergl. auf ungleich Vergl. auf größer oder gleich Vergl. auf größer Vergleich Alle Typen & | ^ << >> bitw. UND-Verknüpfung bitw. ODER-Verknüpfung bitw. Exkl.-Oder-Verknüpfung bitw. Linksverschieben bitw. Rechtsverschieben Bitoperationen Ganzzahlige Typen && || log. UND-Verknüpfung log. ODER-Verknüpfung Logische Verknüpfungen Boolesche Werte Peter Sobe Arithmetik Zahlen, mit Einschränkung Adressen nur ganze Zahlen 34 Operatoren (2) Unäre Operatoren, Postfix- und Präfix-Operatoren & * Adresse von Inhalt von Refernzierung Dereferenzierung alle Typen Zeiger + - pos. Vorzeichen neg. Vorzeichen Arithmetik Zahlen ~ bitw. Invertierung Bitoperationen ganzz. Typen ! logische Invertierung Log. Verknüpfung boolesche Werte Typecast C-Allzweck-Cast viele Typen (type) sizeof sizeof ++ -- sizeof expr.: Speicherbedarf sizeof (type):Speicherbedarf Inkrementierung Dekrementierung Ausdrücke Typen Postfix und Präfix ganzz. Typen und Zeiger Peter Sobe 35 Operatoren (3) Zuweisungs-Operatoren und sonstige Operatoren = Wertzuweisung Zuweisung Alle Typen += -= *= /= %= Addition Subtraktion Multiplikation Division Divisionsrest Arithmetik und Zuweisung Zahlen, mit Einschränkungen, Adressen nur ganze Zahlen &= |= ^= <<= >>= bitw. UND-Verknüpfung bitw. ODER-Verknüpfung bitw. Eckl.-Oder-Verkn. bitw. Linksverschieben bitw. Rechtsverschieben Bitoperationen und Zuweisung ?: , Formulierung bed. Ausdrücke Aufzählung in Klammerausdr. ganzz. Typen Ausdrücke Ausdrücke Fragezeichen-Operator zur verkürzten Formulierung bedingter Ausdrücke, siehe 4.3 Peter Sobe 36 Einfache Anweisungen Arithmetische Operatoren Einfache Zuweisung = Beispiel: summe=64; Addition + bzw. += Beispiele: summe = zahl + 61; summe = summe + 4; summe += 4; Subtraktion - bzw. -= Multiplikation * bzw. *= Division / bzw. /= Modulo-Operator % bzw. %= und weitere Operatoren ... Jede Anweisung wird durch ein Semikolon abgeschlossen Peter Sobe 37 Initialisierung von Variablen, Vergleich Deklaration und Initialisierung: int i = 7; /* Speicherplatz wird reserviert, der mit 7 initialisiert wird */ Zuweisung: i = 8; /* Vorhandener Speicherplatz wird mit neuem Wert belegt.*/ Vergleichsoperatoren gleich == ungleich != kleiner < kleiner gleich <= größer > größer gleich >= Peter Sobe 38 Vergleich Beispiele: if (zahl < 64) ... if (zahl == 16) ... if ((zahl >= 0) && (zahl <= 64)) ... // zahl aus dem Bereich [0..64] bool bo = 5 > 7; // bo erhält den Wert false int a = 5 > 7; // a erhält den Wert 0 int b = 5 < 7; // b erhält den Wert 1 Peter Sobe 39 Logische Verknüpfungen Logische Verknüpfungsoperatoren • Logisches Und && • Logisches Oder || • Logisches Nicht ! Beispiele: if ( (!(zahl < 0)) && (!(zahl > 64))) ... // Alle drei Abfragen sind gleich if ( (zahl >= 0) && (zahl <= 64) ) ... // bedeutend, sie testen, ob zahl if ( zahl >= 0 && zahl <= 64 ) ... // in dem Bereich 0..64 liegt Peter Sobe 40 Inkrement und Dekrement (1) zahl = zahl + 1; // kann verkürzt werden zu zahl += 1; // und nochmals zu zahl++; Entsprechend gibt es zahl--; für das Erniedrigen von zahl um 1. Beachte: „zahl++;“ und „++zahl;“ sind nicht unbedingt das gleiche. Beispiel: int zahl1 = 64; int zahl2 = ++zahl1; // zahl2 und zahl1 sind nun beide 65 int zahl3 = zahl2++; // zahl3 ist 65 und zahl2 66. Peter Sobe 41 Inkrement und Dekrement (2) Pre-Increment und Post-Increment als Funktionen Pre-Increment: Post-Increment: int zahl2 = ++zahl1; int zahl2 = zahl1++; // entspricht int zahl2 =PreInc(zahl1); // entspricht int zahl2 =PostInc(zahl1); // mit int PreInc(int& i) { i = i + 1; return i; } // mit int PostInc(int& i) { int temp=i; i = i + 1; return temp; } Peter Sobe 42 Prioritäten von Operatoren 1 ! ~ ++ -- + - * & sizeof (type) unär, postfix, präfix 2 3 • /% +- binäre arithmetische Operatoren 4 << >> Shift-Operationen 5 6 < <= > >= == != Vergleichsoperatoren 7 8 9 & ^ | Bitoperationen 10 11 && || logische Verknüpfungen 12 = += -= *= /= %= &= = |= <<= >>= Zuweisungsoperatoren 13 , Komma-Operator 1 ist die höchste Priorität, 13 die niedrigste Peter Sobe 43 Inhalt Inhalt: 4. Programmiersprache C 4.1 Programmaufbau in C 4.2 Basisdatentypen und einfache Anweisungen 4.3 Steuerfluss-Konstrukte 4.4 Arbeit mit indizierten Größen (Felder) und Zeiger 4.5 Zeichen und Zeichenketten 4.6 Funktionen (Unterprogramme) 4.7 Strukturen (Datensätze) 4.8 Typen, Variable und Konstante Peter Sobe 44 4.3 Steuerfluss-Konstrukte Verbundanweisung if-Anweisung switch-case-Konstrukt while-Schleife do-Schleife for-Schleife break-Anweisung continue-Anweisung Peter Sobe 45 Verbundanweisung Verbundanweisung • Eine Verbundanweisung dient dazu, mehrere Anweisungen zu einer zusammenzufassen. • Zu Beginn können auch Vereinbarungen stehen, die dann aber nur innerhalb dieser Verbundanweisung gelten. • Eine Verbundanweisung kann auch leer sein, sie kann nur Anweisungen enthalten, und sie kann auch nur Vereinbarungen enthalten. Letzteres ist im allgemeinen nicht sinnvoll. Beispiel in C: { float buffer; buffer = x; x = y; y = buffer; } Peter Sobe 46 Vereinbarungen, Anweisung, Verbundanweisung Jede Vereinbarung oder Anweisung wird in C und C++ durch ein Semikolon beendet. int i; i=99; i=i*2; Am Ende einer Verbundanweisung, d.h. nach der schließenden geschweiften Klammer, steht allerdings kein Semikolon. if (i>100) {printf(" i ist gross \n");} In C ++ können sich Vereinbarungen und Anweisungen beliebig abwechseln. In C stehen die Vereinbarungen vor den Anweisungen. Peter Sobe 47 if-Anweisung (1) Die if-Anweisung ist das Ausdrucksmittel für die Selektion in C, C++. Bedingung ja nein Anw / if ( Bedingung) Anw; if (Bedingung) Verbundanweisung Beispiel: int monat; printf("Bitte Monat Ihres Geburtsdatums eingeben:"); scanf("%d",&monat); if (monat<1 || monat>12) { printf(„falscher Wert für Monat eingegeben!\n"); exit(EXIT_FAILURE); } … Peter Sobe 48 if-Anweisung (2) if ( Bedingung ) Anw1; else Anw2; Bedingung ja Anw1 nein Anw2 if (Bedingung) Verbundanweisung1 else Verbundanweisung2 Beispiel: char kuehlen = 0, heizen = 0; … if (temperatur-zielwert > 2) { printf("zu warm -> kuehlen\n"); kuehlen = 1; } else { if (zielwert – temperatur > 2 ) { printf(„zu kalt -> heizen\n"); heizen = 1; } } Peter Sobe … 49 ?-Operator anstelle if Bedingung ja nein var1 = var2 var1 = var3 If – else – Konstruktion: if ( Bedingung ) var1 = var2; else var1 = var3; Mit ?-Operator: // Bedingte Zuweisung var1 = (Bedingung ? var2 : var3 ); Bedingung ja nein var1 = wert var2 = wert If – else – Konstruktion: if ( Bedingung ) var1 = wert; else var2=wert; Peter Sobe Mit ?-Operator: // Bedingte Zuweisung (Bedingung ? var1 : var2 ) = wert; 50 switch-case-Konstrukt (1) Zur Selektion unter mehreren alternativen Zweigen Fallausdruck Wert1 Wert2 Anw_1 Anw_2 ... sonst ... Anw_n Anw_0 switch(Fallausdruck) { case Wert_1: Anw_1; break; case Wert_2: Anw_2; break; … case Wert_n: Anw_n; break; default: // kann entfallen Anw_0; } Peter Sobe 51 switch-case-Konstrukt (2) Beispiel unsigned int tag, monat, jahr; … // Eingabe des Datums switch(monat) { case 1: printf("Januar"); break; case 2: printf("Februar"); break; case 3: printf("Maerz");break; … default: printf("-undefiniert-"); } Peter Sobe In einen Fall (case) wird bei entsprechendem Wert (Konstante) des Fallausdrucks gesprungen. Nach case folgt eine oder mehrere Anweisungen. Achtung keine Verbundanweisung mit {…} Die break-Anweisung ist erforderlich, damit nicht zusätzlich der jeweils folgende Fall auch abgehandelt wird! 52 while-Schleife (1) Allgemeine Formen: Bedingung while ( Bedingung ) Anweisung; Anweisung while ( Bedingung ) Verbundanweisung Die Anweisung oder Verbundanweisung wird solange wiederholt ausgeführt, wie die Bedingung zutrifft. Durch Änderungen der Variablenwerte wird die Bedingung i.d.R. nach endlich vielen Durchläufen irgendwann nicht mehr zutreffen und die Wiederholung endet. Trifft die Bedingung bei Eintritt in die Schleife nicht zu, wird die Anweisung nicht (auch nicht ein einziges mal) ausgeführt. Peter Sobe 53 while-Schleife (2) Beispiel: int summe = 0; int i = 10; while (i >= 1) { // entspricht while (i>0), entspricht while (i) summe += i; --i; // oder i--; } printf(”Die Summe der Zahlen von 1 bis 10 ist %d \n”, summe); …. Peter Sobe 54 do-while-Schleife (1) Allgemeine Formen: Anweisung Bedingung do Anweisung; while ( Bedingung); do Verbundanweisung while (Bedingung); Die do-while-Schleife wird mindestens einmal durchlaufen. Die Anweisung oder Verbundanweisung wird solange noch einmal ausgeführt, wie die Bedingung nach der Ausführung zutrifft. Typischerweise ändert die Anweisung oder Verbundanweisung den Inhalt der Variable, die für die Bedingung benutzt werden. Damit wird erreicht, dass die Wiederholung irgendwann endet. Peter Sobe 55 do-while-Schleife (2) Beispiel: int summe = 0; int i = 10; do { summe += i; --i; } while (i >= 1); printf(”Die Summe der Zahlen von 1 bis 10 ist %d \n”,summe); … Peter Sobe 56 for-Schleife (1) Entsprechende Form: Zählzyklus: Lv = awert (s) ewert Anw for (Lv=awert; Lv<=ewert ; Lv=Lv+s) Anw Lv dient hier als Zählvariable Allgemeine Form: for ( Init-Ausdruck ; Bedingung ; Schritt-Ausdruck ) Anweisung; for ( Init-Ausdruck ; Bedingung ; Schritt-Ausdruck ) Verbundanweisung Solange die Bedingung erfüllt ist, wird die Anweisung wiederholt. Die Ausdrücke in der for-Schleife können auch leer sein. Peter Sobe 57 for-Schleife (2) Beispiel: int i; int summe = 0; for (i = 10; i > 0; --i) { summe += i; } printf(”Die Summe ist %d \n”,summe); … Peter Sobe 58 for-Schleife (3) Wirkungsweise einer for-Schleife als PAP: for ( Init-Ausdruck ; Bedingung ; Schritt-Ausdruck ) Anweisung Init-Ausdruck nein Bedingung ja Anweisung Schritt-Ausdruck Peter Sobe 59 break-Anweisung Die break-Anweisung kann in allen Schleifen verwendet werden, um die aktuelle Iteration vorzeitig zu beenden, d.h. vor Erreichen der normalen Ende-Bedingung. Es wird danach aus der Schleife herausgegangen. Anwendung für while-, do-while- und for-Schleifen Beispiel: for (i=0; i<imax; i++) { if (bedingung1) { break; } ... if (bedingung2) { break; } ... if (bedingung3) { break; } ... } Peter Sobe 60 continue-Anweisung Die continue-Anweisung kann in allen Schleifen verwendet werden, um die aktuelle Ausführung des Schleifenkörpers vorzeitig zu beenden, d.h. vor Erreichen der normalen Ende-Bedingung. Es wird dann mit der folgenden Iteration weiter gemacht. Anwendung für while-, do-while- und for-Schleifen Beispiel: for (i=0; i<imax; i++) { // do something ... if (bedingung) { continue; } ... // do somethinge else ... } Peter Sobe 61 Nutzung der verschiedenen Schleifen Die drei verschiedenen Varianten einer Schleife – while, do-while und for – können alternativ verwendet werden. Aspekte für eine sinnvolle Auswahl: Verwendung der while-Anweisung, wenn die Anzahl der Iterationen n unbekannt ist, mit n >= 0 (auch null Durchläufe möglich!) Verwendung der do-while-Anweisung, wenn im Gegensatz dazu n>=1 (mindestens ein Durchlauf!) und Bevorzugung der for-Schleife dann, wenn die Anzahl der Iterationen schon bekannt ist. Peter Sobe 62 Inhalt Inhalt: 4. Programmiersprache C 4.1 Programmaufbau in C 4.2 Basisdatentypen und einfache Anweisungen 4.3 Streuerfluss-Konstrukte 4.4 Arbeit mit indizierten Größen (Felder) und Zeiger 4.5 Zeichen und Zeichenketten 4.6 Funktionen (Unterprogramme) 4.7 Strukturen (Datensätze) 4.8 Typen, Variable und Konstante Peter Sobe 63 Felder in C Felder stellen eine Reihung von Elementen gleichen Typs dar. Man spricht auch von Vektoren oder Arrays. Durch die Reihung (hintereinander speichern) wird eine Ordnungsrelation über die Nummer (Position) des Elementes festgelegt. Über diese Nummer (Index) wird dabei auch der Zugriff zum betreffenden Element vorgenommen. In C hat das erste Element die Nummer 0. Element 0 Element 1 Element 2 Element n-1 In C werden Felder durch die Verwendung der Indexklammern [ ] gekennzeichnet: Beispiel: int vektor[10]; R.Großmann / P. Sobe 64 Deklaration von Feldern in C Felder als eine spezielle Datenstruktur müssen deklariert werden. Die Deklarationsanweisung legt den Namen des Feldes, die Anzahl der Elemente und den Typ der Elemente fest. Beispiel: float a[10]; float ist der Typ der Elemente a ist der Name des Feldes 10 ist die Anzahl der Elemente (a0 a1 a2 ... a9) R.Großmann / P. Sobe 65 Deklaration von Feldern in C float a[10]; Man beachte, dass die Anzahl der Elemente eine Konstante sein muss. Auch wenn von Fall zu Fall unterschiedlich viele Elemente benötigt werden, so muss trotzdem das Feld mit einer konstanten, maximal notwendigen Elementeanzahl deklariert werden. Innerhalb dieser maximalen Anzahl kann jeweils mit unterschiedlich vielen Elementen gearbeitet werden. Der Speicherplatz ist für die maximale Anzahl reserviert, aber es werden aktuell ggf. weniger Elemente belegt. R.Großmann / P. Sobe 66 Initialisierung von Feldelementen / Zugriff auf Feldelemente Feldelemente können in der Deklarationsanweisung mit Werten belegt werden. Beispiel: float a[10]={-3.22,0.0,1,-7.234,55.5,6.6,-0.77,8,0.09,3}; Der Zugriff auf die Elemente eines Feldes erfolgt über den Index (Positionsnummer) des Elementes. Dieser Index wird in der Indexklammer angegeben. Beispiel: es soll auf das 7.Element von a zugegriffen werden: x = a[6]; (da das 1.Element den Index 0 hat, ist 6 der Index des 7.Elementes) Bei Zugriffen auf Feldelemente ist stets zu prüfen, ob der Index in den Deklarationsgrenzen des Feldes liegt. R. Großmann / P. Sobe 67 Beispiel eines Feldprogramms #include <stdio.h> #include <math.h> //arithmetisches Mittel einer Messreihe void main() { int i,n; float a[50],s; printf("\nEingabe Anzahl=");scanf("%d",&n); // n<=50 printf("\nEingabe des Vektors:\n"); for (i=0;i<n;i++) //Eingabe der n Feldelemente { printf("a[%2d]=",i); scanf("%f", &a[i] );}; //hier ist der &-Operator zu s=0; // verwenden for (i=0;i<n;i++) s=s+a[i]; //Zählschleifen sind die typischen s=s/n; //Steuerfluss-Konstr. für Felder printf("\n arithmetisches Mittel=%f \n",s); } R.Großmann / P. Sobe 68 Mehrdimensionale Felder Mehrdimensionale Felder (z.B. Matrizen als 2-dimensionale Felder in der Mathematik) werden analog zum eindimensionalen Fall deklariert. Eine zusätzliche Dimension wird durch eine weitere Indexklammer angegeben. Beispiel: float matrix[3][4]; dies ist eine Matrix mit 3 Zeilen und 4 Spalten. Der Zeilenindex wird immer zuerst variiert. Diese Matrix hat die Struktur: a00 a01 a02 a03 a10 a11 a12 a13 a20 a21 a22 a23 R.Großmann / P. Sobe 69 Initialisierung mehrdimensionaler Felder / Zugriff auf Elemente Mehrdimensionale Felder können auch in der Deklarationsanweisung initialisiert werden. Dabei muss die Verarbeitungsreihenfolge Zeile -> Spalte usw. beachtet werden. Beispiel: float matrix[3][4]={ {1,2,3,4}, {5,6,7,8}, {9,10,11,12} }; dies ist eine Matrix mit 3 Zeilen und 4 Spalten. Der Zugriff auf Elemente erfolgt analog durch Angabe der Folge der Indexklammern in der Reihenfolge Zeile, Spalte, usw.. Da die Indizierung mit Null beginnt, selektiert die Angabe matrix[2][3] die dritte Zeile, und darin das vierte Element, also 12. R.Großmann / P. Sobe 70 Mehrdimensionale Felder - Beispiel Beispiel Matrix-Transposition: #define N 10 float matrix[N][N]; float t; int zeile, spalte; // Eingabe Matrix // … for(zeile=0; zeile<N; zeile++) { for(spalte=zeile+1;spalte<N; spalte++) { // Tausch matrix[zeile][spalte] mit matrix[zeile_neu][spalte_neu] // wobei zeile_neu = spalte und spalte_neu = zeile t = matrix[zeile][spalte]; matrix[zeile][spalte] = matrix[spalte][zeile]; matrix[spalte][zeile] = t; } } R.Großmann / P. Sobe 71