Programmierkurs C - Sommersemester 2011, 3. Vorlesung
Transcrição
Programmierkurs C - Sommersemester 2011, 3. Vorlesung
Programmierkurs C Sommersemester 2011, 3. Vorlesung Stuttgart, den 13. April 2011 Heiko Schulz University of Stuttgart, Math. department Rückschau L Operatoren: Vergleichsoperatoren, Zusammengesetze Zuweisungsoperatoren, Inkrement- und Dekrementoperatoren. L Funktionen: Deklaration in Denition. L Variablen: Gültigkeit. L Kontrolluss: Bedingte Ausführung und Schleifen. L Bedingte Ausführung: if, case, bedingte Auswertung. L Schleifen: for, while, do...while, break, continue. L Dateneingabe mit scanf. 78 Programm: fehlersuche.c 79 Lösungen zum Aufgabenblatt 2: #include 3 int 4 int 1 < s t d i o . h> 2 main ( ) 5 { i , j ,k; p r i n t f ( " Moechten (2) : 6 s c a n f ( "% i " , 7 if 8 9 10 ( k ==1 Sie addieren (1) oder multiplizieren ") ; || &k ) ; k ==2) { p r i n t f ( " Geben Sie die erste ") ; 11 s c a n f ( "% i " , 12 p r i n t f ( " Und die 13 s c a n f ( "% i " , &j ) ; &i ) ; Zweite : ") ; natuerliche Zahl ein : Programm: fehlersuche.c 14 if 15 16 17 } 18 } 22 { else { return else return + %d = %d \n" , i , j , i+j ) ; * = %d \n" , i , j , i %d 0; { p r i n t f (" Falsche 23 25 } 1) } 20 24 == p r i n t f ( "%d p r i n t f ( "%d 19 21 (k 80 } 1; Eingabe !\ n" ) ; *j); Programm: mitternacht.c / * mitternacht . c #include #include int float main 81 */ < s t d i o . h> <m ath . h > () { a ,b,c ,d; printf (" Bitte getrennt : Werte von a ,b,c eingeben , durch Komma ") ; s c a n f ( "%f ,% f ,% f " ,& a ,& b ,& c ) ; d= s q r t ( b * b 4* a * c ) ; p r i n t f ( " Loesungen : ) /(2.0 } return 0; *a)) ; %f u n d %f \ n " , ( b+d ) / ( 2 . 0 * a ) , ( bd Flieÿkommazahlen oat und double L Flieÿkommazahlen (auch Gleitkommazahl oder Gleitpunktzahl; engl. oating point number) sind eine approximative Darstellung der reellen Zahlen. L Festkommazahlen: meistens begrenzte Ziernfolge, an festgelegter Stelle wird das Komma angenommen. Bei gröÿeren Rechnungen Überläufe. Schlecht. L Mantisse m und dem Exponenten 1 B m @ b. L x > R mit zwei Werten: der e: x m be bezüglich Basis b. Flieÿkomma: Darstellung einer Zahl Bei Rechnungen mit Gleitkommazahlen wird jede Zahl und jedes Zwischenergebnis individuell skaliert. Folge: Approximationsfehler, Auslöschungseekte. Ô Ungültigkeit des Assoziativ- und Distributivitätsgesetzes! 82 Beispiel zur Stellenauslöschung L Die Gleichung ax 2 bx c x1~2 Für a D Über 1, b º 200, c b2 4ac R 0 hat die Lösungen b 0.000015 º 83 º b2 4ac . 2a gilt 2002 4 1 0.000015 200.00000015..., sind die Lösungen also x1 x2 200 200.00000015~2 200 200.00000015~2 0.000000075, 200.000000075. Aber für 10-stellige Flieÿpunktzahlen erhält man: x1 x2 200 200.0000001~2 200 200.0000001~2 0.00000005, 200.00000005. Besserer Algorithmus L 84 4 Grund: Stellenauslöschung bei Subtraktion. Beispiel ( über R 104 1 104 Stellen): 1 Aber: 1.000e4 1.000e0 1.000e4 1.0001e4 1.000e4 1.000e4 0.0001e4 1.000e4 1.000e4 1.000e4 0. L Beobachtung: Die betragsmäÿig gröÿere Lösung ist genauer. L Die Lösungen b º x1 b2 4ac 2a und genügen der Identität x1 x2 L x2 2c b º b2 4ac c . a Idee: betragsmäÿig gröÿere Lösung nden und mit Identität andere bestimmen, keine Subtraktion. Im Beispiel (mit 10 Stellen): x2 c ~200.00000005 0.000000075. Modultechnik I L 85 Ein Modul besteht aus der von auÿen sichtbaren Schnittstelle und aus der von auÿen nicht sichtbaren Implementierung (Realisierung). L Die Implementierung kann von auÿen nicht verändert werden. L Alle Deklarationen und Denitionen, welche nicht Bestandteil der Schnittstelle sind, sind von auÿen nicht sichtbar. L Das Verbergen der Implementierung nennt man information hiding, Datenkapselung. Das ist als Schutz vor ungefugtem Zugri von Bedeutung, aber auch für Übersichtlichkeit und Trennung von Programmier-Verantwortlichkeiten. L Ein Programm kann unter Benutzung der Modultechnik aus mehreren Modulen bestehen, welche untereinander nur über Schnittstellen kommunizieren. Modultechnik Beispiel Präprozessor 86 stdio.h programm.c void printf(...); #include <stdio.h> #include <math.h> math.h double sqrt(double x); double sin(double x); int main() {...} Compiler programm.o (Objekt) math.o Linker ausführebare Datei programm (Windows: programm.exe) stdio.o Modultechnik II L 87 Die Schnittstelle enthält Deklarationen von Typen, Konstanten und Funktionen, welche für die Verwendung des Moduls benötigt werden. L In C: sogenannte Header-Dateien, Endung: .h. L Die Implementierung enthält einerseits Deklarationen und Denitionen von ausschlieÿlich intern verfügbaren Typen, Konstanten und Funktionen und andererseits die Denitionen der nach auÿen sichtbaren Routinen. Modultechnik III L 88 Jedes Modul kann einzeln compiliert werden. Kommuniziert es mit anderen Modulen, so müssen lediglich deren Schnittstellen bekannt sein. Dies erreicht man durch Einbinden der Header-Dateien der entsprechenden Module mittels #include. L Ein Modul ist für sich alleine nicht ablauähig, da es nur einen Teil des Programms darstellt (es fehlt main-Funktion!). Um ein Programm zu erstellen, müssen die einzelnen Module mithilfe des Linkers miteinander verbunden werden. L Der Programmierer muss entscheiden, wie er die Zerlegung eines Programms in Module sinnvoll erreicht. Dabei sollen beispielsweise Daten und zugehorige Aufgaben oder Aufgaben, die später an anderer Stelle benötigt werden, gekapselt werden. Funktionen: Rekursion L 89 Rekursion (lat. recurrere zurücklaufen) ist die Technik, eine Funktion durch sich selbst auf der Basis eines Anfangswertes zu denieren. L Prominentes Beispiel: Fakultät, L Es gibt Problemstellungen, welche sich auf natürliche Weise einfach n! n n 1! per Rekursion lösen lassen. L Jede rekursive Funktion kann äquivalent über eine Schleife berechnet werden (Beispiele: fakultät; Fibonnacci-Zahlen). Rekursion Beispiel: Fakultät int int return else return fak ( if } } n) ( n <=0) { { 1; { n * f a k ( n 1) ; } oder noch kürzer int } int return fak ( n) n <=0 { ? 1 : n * f a k ( n 1) ; 90 Eindimensionale Felder I L 91 Oft benötigt man einen zusammengehörigen Block von Variablen gleichen Typs, wie beispielsweise die Komponenten eines Vektors. Dafür verwendet man häug Felder, auch als Arrays oder Vektoren bezeichnet. L Ein Feld ist die Zusammenfassung einer Anzahl von Objekten des gleichen Datentyps. Objekte heiÿen Elemente oder Einträge. L Syntax: Deklaration: datentyp arrayname [ dim ]; mit dim>0 ganzzahlig array[0]=1; array[i]=2; Länge1! Zugri mit dem Index-Operator []: L Achtung: Index immer von L Beispiel: int int for } 0 bis i ; vektor [10]; ( i =0; i <10; // definiert i ++) vektor [ i ]:= i *i ; Feld der Laenge { // a l l e Quadratzahlen <=81 10 Eindimensionale Felder II L 92 Man unterscheidet statische und variable Felder. Statische: Die Dimension ist konstant, variabel: Dimension ist durch eine Variable gegeben: int int int L array1 [10]; // s t a t i s c h dim =20; a r r a y [ dim ] ; // v a r i a b e l Für statische Felder muss die Gröÿe also vor Programmstart festgelegt werden, unexibel. L Oftmals ist es erforderlich, die Gröÿe eines Feldes während des Programmverlaufs festzulegen. L Ô Felder mit variabler Länge. Ausblick: echte dynamische Felder, deren Gröÿe während des Programmlaufs jederzeit angepasst werden kann, sind durch Zeiger realisierbar. Eindimensionale Felder Hinweise L 93 Nur bei der Deklaration ist eine gesammelte Zuweisung der Form int int intarray2 [4] intarray3 [] = = {0 ,1 ,2 ,3}; {0 ,1 ,2 ,3}; // a e q u i v a l e n t zu intarray2 möglich, sonst nur elementweise. Bei einer Deklaration mit kombinierter Zuweisung kann die Gröÿe weggelassen werden. L Noch ein Beispiel mit gesammelter Zuweisung: L Der von einem Feld benötigten Speicherplatz in Bytes kann mithilfe des sizeof-Operators bestimmt werden: 1 2 char sizeof chararray [10]; ( chararray ) ; // l i e f e r t den Wert 10 Eindimensionale Felder Beispiel / / * * " Inneres Produkt " innerproduct3 . c #include int int double double int */ zweier Vektoren 94 aus R^3 */ < s t d i o . h> main () { DIM = 3 ; v 1 [ DIM ] , v 2 [ DIM ] ; ip ; i ; printf (" Skalarprodukt printf (" Bitte for ( i =0; printf scanf printf scanf } geben i <DIM ; ( "a_%d ( "% l f " , ( "b_%d ( "% l f " , i ++) = zweier sie { die // e i n l e s e n " , i ) ; &v 1 [ i ] ) ; = Vektoren \n" ) ; Vektoren " , i ) ; &v 2 [ i ] ) ; der a ,b e i n : \ n" ) ; Vektoren Eindimensionale Felder Beispiel // Berechnen ip for = // Ausgeben Skalarprodukts 0.0; ( i =0; i <DIM ; ip v1 [ i ] printf += return des ( "\ nDer betraegt : } des 95 0; * i ++) v2 [ i ] ; Eregnisses Wert des %f \ n " , i p ) ; Skalarprodukts von a und b Eindimensionale Felder Beispiel / / * * " Inneres Produkt " */ innerproduct . c #include int int double int zweier Vektoren 96 in R^d */ < s t d i o . h> main () { DIM = 3 ; ip ; i ; printf (" Skalarprodukt printf (" Bitte ein : scanf double geben die Vektoren \n" ) ; Dimension der Vektoren ") ; ( "% i " , &DIM ) ; v 1 [ DIM ] , v 2 [ DIM ] ; p r i n t f ( " s i z e o f ( v1 ) printf zweier sie (" Bitte = % l i \n" , geben sie die sizeof ( v1 ) ) ; Vektoren a ,b e i n : \ n" ) ; Eindimensionale Felder Beispiel for ( i =0; i <DIM ; printf scanf ( "% l f " , printf scanf i ++) ( "a_%d ( "b_%d ( "% l f " , = { // e i n l e s e n 97 der Vektoren " , i ) ; &v 1 [ i ] ) ; = " , i ) ; &v 2 [ i ] ) ; } // Berechnen ip for = // Ausgeben ( i =0; i <DIM ; ip v1 [ i ] printf += return des ( "\ nDer betraegt : } des Skalarprodukts 0.0; 0; * i ++) v2 [ i ] ; Eregnisses Wert des %f \ n " , i p ) ; Skalarprodukts von a und b Mehrdimensionale Felder L 98 Oftmals kommt man mit eindimensionalen Feldern nicht aus, beispielsweise bei der Verwendung von Matrizen. L Für solche Fälle ist die Denition mehrdimensionaler Felder möglich. Beispiel: double matrix [7][6]; deniert ein Feld mit 7 Zeilen und 6 Spalten. L Analog: höherdimensionale Felder. L C kennt (intern) nur eindimensionale Felder. Beispielsweise wird ein zweidimensionales Feld dadurch simuliert, dass jedes Feldelement eines zweidimensionalen Feldes wieder ein eindimensionales Feld ist. L Eigene Simulation von mehrdimensionalen Feldern durch eindimensionale: int matrix[m*n]; statt int matrix[i][j];, matrix[i*n+j] statt matrix[i][j] Deklaration: Zugri: Mehrdimensionale Felder Beispielprogramm / * matadd . c #include int int double */ < s t d i o . h> main () { DIM = 3 ; printf for m a t r i x 1 [ DIM ] [ DIM ] , m a t r i x 2 [ DIM ] [ DIM ] , sum [ DIM ] [ DIM ] ; (" Addition int for int ( i =0; ( printf scanf printf scanf j i zweier Matrizen < DIM ; i =0; j < DIM ; ( "A[% d ,% d ] ( "% l f " , = \n\n" ) ; { j ++) { " , i +1 , j +1) ; &m a t r i x 1 [ i ] [ j ] ) ; ( "B[% d ,% d ] ( "% l f " , ++) = " , i +1 , j +1) ; &m a t r i x 2 [ i ] [ j ] ) ; sum [ i ] [ j ] = m a t r i x 1 [ i ] [ j ] + m a t r i x 2 [ i ] [ j ] ; } p r i n t f ( "\n" ) ; } } 99 Zeiger (englisch: pointer) L 100 Der Inhalt einer Zeigervariable ist eine Adresse im Speicher des Computers. L Ein Zeiger zeigt also auf eine Adresse im Speicher. L Die Deklaration von Zeigern erfolgt durch Hinzunahme eines Sterns als Präx zum Variablennamen. Z.B. wird durch int *zeiger ; ein Zeiger deklariert, die auf L int-Speicherplätze zeigen kann. Der Typ und die Gröÿe des Objektes, auf welches ein Zeiger zeigen kann, sind in der Deklaration festgelegt. L 1 Problem: Zuweisung der Form z e i g e r =123; sind gültig, verändert aber nur die Adresse, auf die gezeigt wird, was evtl. nicht die Absicht des Programmierers war. Zeiger Referenzierung und Dereferenzierung L 101 Zugri auf den Wert, auf den gezeigt wird, hat man mit dem Dereferenzierungs-Operator *. Umgekehrt liefert der Referenzierungs-Operator & die Adresse einer Variablen, welche dann einem Zeiger zugewiesen werden kann. Beispiel: 1 float float // f hat // z zeigt irgendwohin 5 z=& f ; // nun zeigt z 6 // d e r Speicherstelle , 7 // d e r float 8 // f 2 3 f ; *z ; irgendeinen 4 f =5.0; *z =1.0; hat nun auf f , Wert *z hat auf den die z Wert 1.0 zugewiesen also den Wert 1.0 Wert 5.0 zeigt , wird Zeiger Typisierung L So wie man sich Variablen als benannte Speicherbereiche vorstellen kann, so kann man sich Zeiger als benannte Speicheradressen vorstellen. L Referenziert man eine Variable, so erhält man den zugehörigen Zeiger, dereferenziert man einen Zeiger, so erhalten wir den Wert der zugehörigen Variable. L 102 Der Typ des Zeigers legt dabei fest, wie groÿ der Speicherbereich, auf den der Zeiger zeigt ist, und wie der Inhalt dieses Speicherbereichs interpretiert wird. Zeiger und Felder L 103 In C besteht ein enger Zusammenhang zwischen Feldern und Zeigern: Der Name eines Felds ist ein konstanter Zeiger auf das erste Feld-Element (Referenz auf das erste Feld-Element). int int int zahl ; vektor [3] *zeiger zeiger zahl = = = {1 ,2 ,3}; ; vektor ; *zeiger ; // o d e r : zeiger // o d e r : zahl = * vektor // o d e r : zahl = vektor [0] // a l s o L zahl jetzt *( z e i g e r +1) ; Allgemeiner sind ; den zeiger auf das erste Element eines Felds, zeiger+1 auf das zweite Element dieses Felds: Zeigt zahl = L hat = &v e k t o r [ 0 ] ; dann zeigt *( v e k t o r +1) ; // o d e r : zahl = // o d e r : zahl=vektor [ 1 ] ; vektor[n] und Wert *(vektor+n) die gleichen Elemente. Der Feld-Zugrisoperator [] ist auch für Zeiger verwendbar. 1 Zeiger und Felder Beispielprogramm / * array . c #include int int double for */ < s t d i o . h> main () i , { n =3; array [ n ] ; ( i =0; i <n ; a r r a y [ i ]= i i ++) *i { ; p r i n t f ( " a r r a y [% d ] } } return 0; = %f \ n " , i , *( array+i ) ) ; 104 Zeiger Hinweise und Gefahren L Zeiger sind mächtig (und) gefährlich uninitialisierte Zeiger sind die gröÿte Fehlerquelle in C-Programmen. L Zeigerdeklaration führt nur zur Bereitstellung des Speichers, welcher die Adresse enthält! Der Speicher für das Objekt, auf das der Zeiger zeigt, muss gegebenenfalls noch beschat (alloziert) werden. Vergisst man die Zuweisung von Speicher für das Objekt, wie in int *iptr ; * i p t r = 5; führt dies zum Überschreiben einer zufälligen Speicheradresse. L Zur Vermeidung solcher Fehler ist eine Initialisierung von Zeigern mit 0 bzw. NULL (Zeigernull) nützlich. 105 Zeiger Hinweise und Gefahren L 106 Eine weitere Gefahr bei Zeigern auf Felder besteht im Darüberhinausschreiben über Feldgrenzen: int *iptr , arr [20]=0; arr [20]; // F e h l e r ! iptr=arr ; *( i p t r +20) =0; iptr [20]=0; L // g l e i c h e r // g l e i c h e r Fehler ! Fehler ! Eine Feldgrenzen-Verletzung ist meist schwieriger zu nden als eine fehlende Initialisierung (Angezeigter Fehler: segmentation fault, deutsch: Speicherzugrisfehler, Zugrisverletzung, Schutzverletzung). Zeiger fehlerhaftes Beispiel Der folgende Quelltext lässt sich problemlos kompilieren / * wrongarray . c #include int main */ < s t d i o . h> () int double for i , { n =3; * array ( i =0; ; i <n ; i ++) *( a r r a y + i )= i * i } } return 0; ; { 107 Zeiger fehlerhaftes Beispiel 108 Man compiliert mit: $ gcc -std=c99 wrongarray.c -o wrongarray Nach dem Programmstart erhält man aber die folgende Fehlermeldung: $ ./ array segmentation fault ./ array Was ist passiert? Es wurde auf einen Speicherbereich zugegrien, der nicht vorher alloziert wurde. Zeichenketten 109 L Zeichenketten (Strings) werden in C mit Hilfe von Feldern realisiert. L Der Datentyp eines Zeichens ist char (Ganzzahl-Datentyp). Zahl L Zeichen über ASCII-Tabelle. Ein C-String ist ein char-Feld und wird durch das Sonderzeichen \0 abgeschlossen. L Während char-Konstanten in Hochkommata geschrieben werden (z.B. 'a'), a wird eine String-Konstante in Anführungszeichen geschrieben (z.B. abc). Beachte: 'a' und a sind nicht gleich: 'a' ist gleich a, a ist gleich a\0. L Eine Zeichenkette der Länge n benötigt also ein char-Feld der Gröÿe n + 1. Der leere String benötigt ein Byte Speicherplatz. Regular ASCII Chart (character codes 0 127) 000d 001d 002d 003d 004d 005d 006d 007d 008d 009d 010d 011d 012d 013d 014d 015d 00h 01h 02h 03h 04h 05h 06h 07h 08h 09h 0Ah 0Bh 0Ch 0Dh 0Eh 0Fh 128d 129d 130d 131d 132d 133d 134d 135d 136d 137d 138d 139d 140d 141d 142d 143d 80h 81h 82h 83h 84h 85h 86h 87h 88h 89h 8Ah 8Bh 8Ch 8Dh 8Eh 8Fh ␀ ␁ ␂ ␃ ␄ ␅ ␆ ␇ ␈ ␊ ␋ ␍ ␎ ␏ (nul) (soh) (stx) (etx) (eot) (enq) (ack) (bel) (bs) (tab) (lf) (vt) (np) (cr) (so) (si) 016d 017d 018d 019d 020d 021d 022d 023d 024d 025d 026d 027d 028d 029d 030d 031d 10h 11h 12h 13h 14h 15h 16h 17h 18h 19h 1Ah 1Bh 1Ch 1Dh 1Eh 1Fh 144d 145d 146d 147d 148d 149d 150d 151d 152d 153d 154d 155d 156d 157d 158d 159d 90h 91h 92h 93h 94h 95h 96h 97h 98h 99h 9Ah 9Bh 9Ch 9Dh 9Eh 9Fh ␐ ␑ ␒ ␓ ␔ ␕ ␖ ␗ ␘ ␙ ␛ ␜ ␝ ␞ ␟ (dle) (dc1) (dc2) (dc3) (dc4) (nak) (syn) (etb) (can) (em) (eof) (esc) (fs) (gs) (rs) (us) 032d 033d 034d 035d 036d 037d 038d 039d 040d 041d 042d 043d 044d 045d 046d 047d 20h 21h 22h 23h 24h 25h 26h 27h 28h 29h 2Ah 2Bh 2Ch 2Dh 2Eh 2Fh ! " # $ % & ' ( ) * + ' . / 048d 049d 050d 051d 052d 053d 054d 055d 056d 057d 058d 059d 060d 061d 062d 063d 30h 31h 32h 33h 34h 35h 36h 37h 38h 39h 3Ah 3Bh 3Ch 3Dh 3Eh 3Fh 0 1 2 3 4 5 6 7 8 9 : ; < = > ? 064d 065d 066d 067d 068d 069d 070d 071d 072d 073d 074d 075d 076d 077d 078d 079d 40h 41h 42h 43h 44h 45h 46h 47h 48h 49h 4Ah 4Bh 4Ch 4Dh 4Eh 4Fh @ A B C D E F G H I J K L M N O 080d 081d 082d 083d 084d 085d 086d 087d 088d 089d 090d 091d 092d 093d 094d 095d 50h 51h 52h 53h 54h 55h 56h 57h 58h 59h 5Ah 5Bh 5Ch 5Dh 5Eh 5Fh P Q R S T U V W X Y Z [ \ ] _ 096d 097d 098d 099d 100d 101d 102d 103d 104d 105d 106d 107d 108d 109d 110d 111d 60h 61h 62h 63h 64h 65h 66h 67h 68h 69h 6Ah 6Bh 6Ch 6Dh 6Eh 6Fh ` a b c d e f g h i j k l m n o 112d 113d 114d 115d 116d 117d 118d 119d 120d 121d 122d 123d 124d 125d 126d 127d 70h 71h 72h 73h 74h 75h 76h 77h 78h 79h 7Ah 7Bh 7Ch 7Dh 7Eh 7Fh p q r s t u v w x y z { | } ␡ D0h D1h D2h D3h D4h D5h D6h D7h D8h D9h DAh DBh DCh DDh DEh DFh Ð Ñ Ò Ó Ô Õ Ö Ö Ø Ù Ú Û Ü Ý Þ ÿ 224d 225d 226d 227d 228d 229d 230d 231d 232d 233d 234d 235d 236d 237d 238d 239d E0h E1h E2h E3h E4h E5h E6h E7h E8h E9h EAh EBh ECh EDh EEh EFh à á â ã ä å æ ç è é ê ë ì í î ï 240d 241d 242d 243d 244d 245d 246d 247d 248d 249d 250d 251d 252d 253d 254d 255d F0h F1h F2h F3h F4h F5h F6h F7h F8h F9h FAh FBh FCh FDh FEh FFh ð ñ ò ó ô õ ö ö ø ù ú û ü ý þ ¸ Extended ASCII Chart (character codes 128 255) Latin1/CP1252 e f ... ^ % × Hexadecimal to Binary 0 1 2 3 0000 0001 0010 0011 4 5 6 7 0100 0101 0110 0111 8 9 A B 1000 1001 1010 1011 ` ' ~ ² ÷ º 160d 161d 162d 163d 164d 165d 166d 167d 168d 169d 170d 171d 172d 173d 174d 175d A0h A1h A2h A3h A4h A5h A6h A7h A8h A9h AAh ABh ACh ADh AEh AFh ½ ¢ ¿ ¤ ¥ ¦ ¨ © ª ¬ ® ¯ 176d 177d 178d 179d 180d 181d 182d 183d 184d 185d 186d 187d 188d 189d 190d 191d B0h B1h B2h B3h B4h B5h B6h B7h B8h B9h BAh BBh BCh BDh BEh BFh ° ± ² ³ ´ µ ¶ · ¹ º ¼ ½ ¾ ¾ 192d 193d 194d 195d 196d 197d 198d 199d 200d 201d 202d 203d 204d 205d 206d 207d C0h C1h C2h C3h C4h C5h C6h C7h C8h C9h CAh CBh CCh CDh CEh CFh À Á Â Ã Ä Å Æ Ç È É Ê Ë Ì Í Î Ï 208d 209d 210d 211d 212d 213d 214d 215d 216d 217d 218d 219d 220d 221d 222d 223d Groups of ASCII-Code in Binary C D E F 1100 1101 1110 1111 Bit 6 0 0 1 1 Bit 5 0 1 0 1 Group Control Characters Digits and Punctuation Upper Case and Special Lower Case and Special 2009 Michael Goerz This work is licensed under the Creative Commons Attribution-Noncommercial-Share Alike 3.0 License. To view a copy of this license, visit http://creativecommons.org/licenses/by-nc-sa/ Zeichenketten Beispiel char char char int for 111 a r r a y 1 [ 5 ] = { 'H ' , ' e ' , ' l ' , ' l ' , ' o ' } ; array2 [8]={ ' , ' , ' // k e i n String ' , 'w ' , ' o ' , ' r ' , ' l ' , ' d ' , ' \0 ' } ; string1 [50]; i ; ( i = 0 ; i < 5 ; i ++) { // k o p i e r e array1 nach string array2 nach string s t r i n g 1 [ i ]= a r r a y 1 [ i ] ; } for ( i = 0 ; i < 8 ; i ++) { // k o p i e r e s t r i n g 1 [ i +5]= a r r a y 2 [ i ] ; } p r i n t f ( "%s \ n " , s t r i n g 1 ) ; // d a s char gleiche : s t r i n g 2 []= " Hello , world " ; p r i n t f ( "%s \ n " , s t r i n g 2 ) ; printf ( "%c %d \ n " , 111 aus string1 [8] , string1 [8]) ; // gibt o und Funktionen für den Umgang mit Strings L 112 Das elementweise Arbeiten wie mit Feldern ist möglich, aber umständlich. L In der Standardbibliothek gibt es Funktionen für die wichtigsten String-Operationen. Diese sind in string.h deklariert. L Beispiele: Kopieren (strcpy, strncpy), Anfügen (strcat), Vergleichen (strcmp), Länge ermitteln (strlen). L Vorsicht: Strings sind char-Felder, d.h. beim Kopieren und Anhängen muss das Zielfeld groÿ genug sein! Siehe auch strncpy. Zeichenketten vergleichen strcmp L 113 strcmp() dient zum Vergleich zweier Strings. Beschreibung: int strcmp ( const char * string1 , const char * string2 ) L Die Funktion strcmp() vergleicht die beiden Zeichenketten byteweise. Sie liefert einen positiven Wert für einen negativen Wert für string1 < string2 string1 > string2, und 0, falls die Strings identisch sind. L Vorsicht: Ein Vergleich der Art if (string1==string2) prüft nicht alphabetisch auf Zeichengleichheit, es werden lediglich die Anfangsadressen verglichen. Zeichenketten Beispielprogramm / * stringsvergleich .c #include #include int char char int 114 */ < s t d i o . h> < s t r i n g . h> main ( ) { s 1 [ ] = " Pommes von Burger s 2 [ ] = " Pommes von McDonalds " ; King " ; x; p r i n t f ( " Welche Pommes sind b e s s e r ?\ n " ) ; x= s t r c m p ( s1 , s 2 ) ; if } ( x <0) { p r i n t f ( "%s ! \ n " , s 2 ) ; else i f else ( x >0) { p r i n t f ( "%s ! \ n " , s 1 ) ; } { p r i n t f ( " D i e %s } u n d %s sind gleich gut . \ n" , s1 , s2 ) ; Zeichenketten Beispielprogramm p r i n t f ( "\ nAber int int if else i f else welche Pommes sind 115 l a e n g e r ?\ n " ) ; l a e n g e 1= s t r l e n ( s1 ) ; l a e n g e 2= s t r l e n ( s2 ) ; ( laenge1 <laenge2 ) p r i n t f ( " D i e %s } sind { l a e n g e r !\ n" , s1 ) ; { p r i n t f ( " D i e %s s2 ) ; } l a e n g e r !\ n" , s2 ) ; ( laenge1 >laenge2 ) p r i n t f ( " D i e %s } { sind u n d %s sind gleich l a n g . \ n\n" , s1 , Zeichenketten Beispielprogramm char ungesund [ 1 0 0 ] ; s t r c p y ( ungesund , s t r c a t ( ungesund , s1 ) ; s t r c a t ( ungesund , " s t r c a t ( ungesund , s2 ) ; s t r c a t ( ungesund , " p r i n t f ( "%s \ n " , // Einfacher : char mit ( String ) als sowohl auch sind lang genug ? ") ; ") ; ungesund . " ) ; ungesund ) ; sprintf : ungesund2 [ 8 0 ] ; s p r i n t f ( ungesund2 , " Aber ungesund . " , s1 ) ; p r i n t f ( "%s \ n " , } // "\ nAber 116 return 0; s2 , s o w o h l %s ungesund2 ) ; als a u c h %s sind Call by value und Call by reference L In C ist für Funktionen ist nur ein Rückgabewert erlaubt. L Eine Möglichkeit diese Einschränkung zu umgehen, ist die 117 Verwendung globaler Variablen - schlechter Stil, unübersichtlich, fehleranfällig. L Eine weitere, bessere Möglichkeit ist die folgende: Man übergibt anstelle des Wertes einer Variablen (Call by value) die Adresse dieser Variablen (Call by reference). L Die Funktion kann dann den Wert an dieser Adresse verändern und er steht danach an bekannter Stelle zur Verfügung. L Beispiel: scanf: s c a n f ( "% i " , &k ) ; Call by value und Call by reference Beispiel / * 118 */ callref1 .c #include void float if return < s t d i o . h> betrag ( ( x <0.0) ; { x= x) x ; { // v e r a e n d e r t nichts ! } // o p t i o n a l } int main ( ) float x= { x , *z ; 1.5; betrag (x ) ; // w i r uebergeben value p r i n t f ( "%f \ n " , x ) ; z=&x ; betrag ( // d a s // e s gleiche * z ) ; // w i r wird wie uebergeben value p r i n t f ( "%f \ n " , x ) ; return 0; // e s wird den Wert 1.5 1.5 x , call by ausgegeben zuvor , den von x Wert wird von veraendert z , ausgegeben call by Call by value und Call by reference Beispiel / * 119 */ callref2 .c #include void float * if * * return < s t d i o . h> betrag ( ( x <0.0) ; { x) x= { * x ; } // o p t i o n a l } int main ( ) float x= { *z ; x , 1.5; b e t r a g (& x ) ; den // w i r Wert , p r i n t f ( "%f \ n " , x ) ; z=&x ; // d a s * z = 2; uebergeben call by // e s gleiche b e t r a g (& x ) ; p r i n t f ( "%f %f \ n " , x , ausgegeben return 0; die Adresse von x , nicht reference *z) ; wird wie 1.5 ausgegeben zuvor , // e s wird x wird 2.0 und veraendert : 2.0 Sinnvolles Beispielprogramm 120 Zeiger ermöglichen das Ändern von Funktionsargumenten: 1 /* 2 3 4 // 5 6 double *a *b 9 = der double swap ( tmp 8 < s t d i o . h> Vertauschen void 7 */ swap . c #include tmp ; Werte *a , von double a *b *a ; = *b ; = tmp ; 10 } 11 12 13 int main () double 14 x =2.0; 15 y =3.1; { x , y; 16 17 p r i n t f ( " x=% l f , 18 s w a p (& x ,& y ) ; 19 return 20 p r i n t f ( " x=% l f , 0; } y=% l f \ n " , x , y ) ; y=% l f \ n " , x , y ) ; und ) { b Vielen Dank... ... für Ihre Aufmerksamkeit und bis morgen... 121