350 likes | 504 Views
Einführung in die Programmiersprache C 5.Tag Institut für Mathematische Optimierung - Technische Universität Braunschweig. Zeichenketten.
E N D
Einführung in die Programmiersprache C5.TagInstitut für Mathematische Optimierung -Technische Universität Braunschweig
Zeichenketten Zeichenketten (Strings) werden in C als Felder von Zeichen (char) realisiert. Das Ende wird durch das Zeichen 0 markiert. Die Zeichenkette „Wort" ist also fünf Zeichen lang: Die Länge einer Zeichenkette kann so bestimmt werden: intlen; char *str; ... len = 0; while (str[len]!=0) { len++; }
Ersetzen von Buchstaben Möchte man alle ’a’ durch ’b’ ersetzen, geht das so: char *str, *p; ... for (p=str; *p!=0; p++) { if (*p==’a’) *p==’b’; } Institut für Mathematische Optimierung – Technische Universität Braunschweig
Lexikographischer Vergleich Ein lexikographischer Vergleich ist so umsetzbar: char *str1, *str2; int i; ... for (i=0; ; i++) { if (str1[i]<str2[i]) /* "str1 < str2" */ if (str1[i]>str2[i]) /* "str1 > str2" */ if (str1[i]==0) /* "str1 == str2" */ } Institut für Mathematische Optimierung – Technische Universität Braunschweig
String.h Zur Bearbeitung von Zeichenketten stellt die Standardbibliothek string.h diverse Funktionen zur Verfügung. Beispiele: • intstrcmp(char *s1,char *s2) Vergleicht zwei Strings lexikographisch. Ergebnis : <0 (wenn s1 kleiner als s2), 0 (wenn s1=s2) und >0 (wenn s1 größer als s2). • intstrncmp(char *s1,char *s2, int n) Vergleicht zwei Strings lexikographisch, berücksichtigt höchstens die ersten n Stellen. Institut für Mathematische Optimierung – Technische Universität Braunschweig
String.h • intstrlen(char *s) Bestimmt die Länge eines Strings (ohne Zeichen '0'). • char* strcpy(char* ziel, char* quelle) Kopiert den String aus quelle nach ziel. • char* strncpy(char* ziel, char* quelle,int n) Kopiert den String aus quelle nach ziel, jedoch höchstens n Zeichen. • char* strcat(char* ziel, char* quelle) Kopiert den String aus quelle an das Ende von ziel (Zeichen '0' von ziel wird überschrieben). Institut für Mathematische Optimierung – Technische Universität Braunschweig
String.h • char *strchr(constchar *text, int a) Bestimmt Zeiger auf erstes Vorkommen des Zeichens a im String text oder auf NULL, falls a nicht in text enthalten. • char *strrchr(constchar *s, int a) Wie zuvor, nur letztes Vorkommen. • char *strstr(char *text, char *wort) Wie zuvor für Teilstring wort. Institut für Mathematische Optimierung – Technische Universität Braunschweig
sprintf und sscanf Analog zu printf(), scanf(), fprintf() und fscanf() gibt es auch sprintf() und sscanf(). Sie schreiben die Ausgabe in einen String bzw. lesen die Daten aus einem String. Institut für Mathematische Optimierung – Technische Universität Braunschweig
Beispiel mit sprintf charfname[64]; int i; FILE* f; ... for (i = 1; i <= 100; i++) { sprintf(fname,"datei%i.txt",i); f = fopen(fname,"w"); ... }
ctype.h Die Funktionen aus ctype.h dienen zum Kategorisieren von Zeichen. Auswahl der Funktionen (Rückgabewerte: 1 für wahr, 0 für falsch): • intisalnum(int c)alphanumer. Zeichen(a-z,A-Z,0-9)? • intisalpha(int c) Buchstabe (a-z, A-Z)? • intisblank(int c) Leerzeichen? • intiscntrl(int c) Steuerzeichen (\n, \t,…)? • intisdigit(int c) Dezimalziffer (0-9)? • intislower(int c) Kleinbuchstabe (a-z)? • intispunct(int c) druckbares Interpunktionszeichen? • intisspace(int c) Zwischenraumzeichen (Leerzeichen, \n, \t,…)? • intisupper(int c)Grossbuchstaben (A-Z)?
Beispiel (1. Teil) … charname[128], *p; intok; do { printf("Geben Sie Ihren Namen ein:"); scanf("%s",&name); ok = 1; Institut für Mathematische Optimierung – Technische Universität Braunschweig
Beispiel (2. Teil) for (p=name; *p != 0; p++) { if (!isalpha(*p)) { printf("unerlaubtes Zeichen ’%c’\n",*p); ok = 0; } } }while(!ok); … Institut für Mathematische Optimierung – Technische Universität Braunschweig
Konstante Variablen Das Schlüsselwort const vor einer Variablendeklaration verbietet ein Verändern dieser Variable. Beispiel: constint i; i = 17; erzeugt einen Kompilerfehler. Gleiches gilt für call-by-reference Parameter von Funktionen: voidfkt(constint *p) { *p = 17; }
Konstante Variablen Variablen dürfen als konstante Parameter übergeben werden: int i; ... fkt(&i); … voidfkt(constint *p) { printf("%i",*p); }
Konstante Variablen Konstante Variablen dürfen nicht als variable Parameter übergeben und dann verändert werden: constint i; ... fkt(&i); … voidfkt(int *p) { *p = 5; }
Aufzählungstypen In C können Aufzählungstypen, d.h. Datentypen mit endlich vielen Werten definiert werden. Beispiel: enumtag{montag, Dienstag, mittwoch}; definiert den Datentyp enum tag. Anwendung: enum tag t1, t2; ... t1=mittwoch; t2=t1; if (t2==montag) {...}
Union Eine union ähnelt dem bereits bekannten struct, es kann jedoch nur einesder definierten Elemente verwendet werden. Beispiel: unionstudent { intmatrikel; charname; floatnote; }; Die Elemente matrikel, name und note benutzen den gleichen Speicherbereich. Beim struct hätte jedes Element einen eigenen Speicherbereich. Institut für Mathematische Optimierung – Technische Universität Braunschweig
Union intmain(void) { unionstudent s1; s1.matrikel=5478; printf("matr.nr.: %d\n",s1.matrikel); s1.note=2.7; printf("matr.nr.:%d\nnote:%.2f\n",s1.matrikel,s1.note); return 0; } Führt zu einer zufälligen Ausgabe von s1.matrikel.
Deklaration mit inline Kurze Funktionen können als inline deklariert werden, um die Geschwindigkeit zu steigern. Dadurch wird keine echte Funktion erzeugt, sondern die Funktion wird an den nötigen Stellen eingefügt. Anwendung: inlineint max(inta,int b) { return (a<b) ? : a : b; } Bemerkung: Besser als Makros definieren (später). Institut für Mathematische Optimierung – Technische Universität Braunschweig
Der Präprozessor Das Kompilieren eines C-Programms erfolgt (logisch) in mehreren Schritten, der erste ist der Präprozessor. Die Präprozessor-Anweisungen beginnen mit #. Wir kennen bereits: #include <...> Um eine Datei aus dem aktuellen Verzeichnis einzubinden, verwendet man: #include "dateiname" Institut für Mathematische Optimierung – Technische Universität Braunschweig
Konstanten Über: #define PI 3.1315926 double kreisflaeche[radius]; wird eine Konstante PI definiert. Der Funktion kreisflaeche braucht nur noch die Variable radius übergeben werden. Die Namen der Konstanten bestehen üblicherweise aus Großbuchstaben. Dabei können auch kompliziertere Konstrukte verwendet werden: #define PI2 (3.1315926*3.1315926) Institut für Mathematische Optimierung – Technische Universität Braunschweig
Konstanten Achtung: Konstanten werden einfach an den verwendeten Stellen eingesetzt. Dies kann zu Fehlern führen: #define N 1+1 ... printf("%i\n",2*N); Gibt 3 aus, nicht 4. Das gewünschte Ergebnis erreicht man mit: #define N (1+1) Institut für Mathematische Optimierung – Technische Universität Braunschweig
Makros Bei diesen Definitionen können auch Parameter angegeben werden, dadurch entstehen Makros: #define MAX(a,b) ((a>b) ? a : b) ... int imax,i1,i2; float fmax,f1,f2; ... imax = MAX(i1,i2); fmax = MAX(f1,f2); Da die Ausdrücke einfach ersetzt werden, findet kein Funktionsaufruf statt und das Makro ist unabhängig vom verwendeten Datentyp. Institut für Mathematische Optimierung – Technische Universität Braunschweig
Beispiel #define MAX(a,b) ((a>b) ? a : b) double langsam(double); ... printf("%lf\n",MAX(langsam(1.3),langsam(2.2))); Hier wird die Funktion langsam() dreimal ausgeführt. Definiert man das Makro als inline-Funktion passiert dies nicht. Institut für Mathematische Optimierung – Technische Universität Braunschweig
Bedingte Kompilierung Quellcode, der hinter #if steht, wird nur übersetzt, falls die if-Bedingung erfüllt ist. Dieses muss beim Kompilieren überprüfbar sein. Außerdem muss jedes #if mit einem #endif abgeschlossen werden. Beispiel: #define K 1 ... intvar=0; … #if (K==1) var++; #endif
Bedingte Kompilierung Zudem darf die Bedingung von #if nur aus konstanten Integerausdrücken bestehen, also nicht wie folgt aussehen: #define K 1.1 ... intvar=0; … #if (K==1.1) var++; #endif
Bedingte Kompilierung Es gibt auch eine #else-Anweisung: #if (K==1) var++; #else var--; #endif Nützlich zur Fehlersuche: __LINE__ wird durch die Zeilenummer im Quelltext ersetzt. Mit: printf("%i\n",__LINE__); kann man überprüfen, ob das Programm die entsprechende Zeile erreicht und so Fehler lokalisieren. Institut für Mathematische Optimierung – Technische Universität Braunschweig
Aufteilen von Programmen Bei großen Programmen verteilt man die Funktionen auf verschiedene Dateien. Diese werden zuerst einzeln zu Objektdateien (*.o unter Linux) kompiliert und dann zum Programm verbunden (gelinkt). gcc -Wall -c main.c erzeugt die Objektdatei main.o (analog: ausgabe.c). Mit: gcc -Wall main.oausgabe.o -o programm werden zwei Objektdateien zu einem ausführbaren Programm gelinkt. Institut für Mathematische Optimierung – Technische Universität Braunschweig
Aufteilen von Programmen Vorteile: Es müssen nur die veränderten Dateien neu kompiliert werden (Zeitgewinn) und die Funktionen werden modularisiert. Damit Funktionen, Strukturen und Makros in anderen Dateien verwendet werden können, erzeugt man eine Headerdatei (*.h) in der die Prototypen und Definitionenenthalten sind. Diese wird dann mittels: #include "dateiname.h" in jede Datei einzeln eingebunden. Institut für Mathematische Optimierung – Technische Universität Braunschweig
Aufteilen von Programmen Funktionen und globale Variablen, die nur innerhalb einer Datei verwendet werden, sollten dort als statisch definiert werden: staticinthilfsfunktion(int x, float y) {...} staticintglobale_variable; Dies vermeidet Namenskonflikte. Institut für Mathematische Optimierung – Technische Universität Braunschweig
Aufteilen von Programmen Globale Variablen, die in mehreren Dateien benutzt werden, können neben der Datei, in der sie zum ersten Mal deklariert werden, in den anderen Dateien über den Zusatz extern deklariert werden. intvar=0; /*Deklaration und Initiali- sierung in erster Datei*/ extern intvar; /*Deklaration danach*/ Institut für Mathematische Optimierung – Technische Universität Braunschweig
Das Programmierwerkzeug Make Um das teilweise Neukompilieren zu automatisieren dient unter Linux/Unix das Programm make. Welche Dateien neu kompiliert und welche zusammen gelinkt werden, muss in einer Datei Makefile angegeben werden. Der logische Aufbau sieht dabei wie folgt aus: Ziel: Abhaengigkeiten Befehl Institut für Mathematische Optimierung – Technische Universität Braunschweig
Beispiel zu make Beispiel: programm: main.oausgabe.o gcc -Wall -o programmmain.oausgabe.o main.o: main.cinhalt.h gcc -Wall -c main.c ausgabe.o: ausgabe.cinhalt.h gcc -Wall –c ausgabe.c Institut für Mathematische Optimierung – Technische Universität Braunschweig
Das Programmierwerkzeug Make Achtung: Vor der Kompileranweisung muss ein Tabulatorzeichen stehen, nicht acht Leerzeichen. Die Anweisung: makeprogramm oder einfach: make erzeugt das ausführbare Programm. Dabei werden Abhängigkeiten und Änderungsdaten der Dateien geprüft. makemain.o würde nur die Objektdatei main.o neu erzeugen. Institut für Mathematische Optimierung – Technische Universität Braunschweig
Makros Um sich das Leben etwas zu vereinfachen, kann man auch durch Setzen von Makros die Schreibarbeit sparen: CC=gcc # Compiler CFLAGS=-Wall -ansi # Compiler-Schalter OBJFILES= main.oausgabe.o programm: $(OBJFILES) $(CC) -o programm $(OBJFILES) main.o: main.c $(CC) $(CFLAGS) -c main.c ausgabe.o: ausgabe.c $(CC) $(CFLAGS) –c ausgabe.c