Textdaten, die in Strings gespeichert werden, sind ein wichtiger Bestandteil vieler Programme. Sie wissen bereits, wie Sie in einem C-Programm Strings speichern und wie Sie Strings einlesen und ausgeben. Darüber hinaus gibt es aber noch eine Vielzahl von speziellen C-Funktionen, mit denen Sie weitere Stringmanipulationen vornehmen können. Heute lernen Sie:
Aus den vorangehenden Kapiteln sollten Sie wissen, dass Strings in C als eine Folge
von Zeichen definiert sind, auf deren Anfang ein Zeiger weist und deren Ende durch
das Nullzeichen \0
markiert ist. In bestimmten Situationen ist es jedoch erforderlich,
auch die Länge eines Strings zu kennen - das heißt die Anzahl der im String
enthaltenen Zeichen. Die Länge eines Strings lässt sich mit Hilfe der
Bibliotheksfunktion strlen()
ermitteln. Der Prototyp, der in string.h
deklariert ist,
lautet:
size_t strlen(char *str);
Vielleicht wundern Sie sich über den Rückgabetyp von size_t
. Dieser Typ ist auf den
meisten Systemen als unsigned int
definiert, kann aber auf Computern mit 64-Bit-
Prozessoren auch unsigned
long
sein. Der size_t
-Typ wird von vielen
Stringfunktionen verwendet. Sie sollten sich vor allem merken, dass der Typ nicht
vorzeichenbehaftet (unsigned
) ist.
Als Argument übergibt man strlen
einen Zeiger auf den String, dessen Länge
ermittelt werden soll. Als Ergebnis liefert die Funktion strlen()
die Anzahl der
Zeichen zwischen str
und dem nächsten Nullzeichen zurück (wobei das Nullzeichen
selbst nicht mitgezählt wird). In Listing 16.1 sehen Sie ein Beispiel zu strlen()
.
Listing 16.1: Mit der Funktion strlen() die Länge eines Strings ermitteln.
1: /* Einsatz der Funktion strlen(). */
2:
3: #include <stdio.h>
4: #include <string.h>
5:
6: int main(void)
7: {
8: size_t laenge;
9: char puffer[80];
10:
11: while (1)
12: {
13: puts("\nGeben Sie eine Textzeile ein, Beenden mit Leerzeile.");
14: fgets(puffer,80,stdin);
15:
16: laenge = strlen(puffer);
17:
18: if (laenge > 1)
19: printf("Die Zeile ist %u Zeichen lang.\n", laenge-1);
20: else
21: break;
22: }
23: return(0);
24: }
Geben Sie eine Textzeile ein, Beenden mit Leerzeile.
Nur keine Angst!
Die Zeile ist 16 Zeichen lang.
Geben Sie eine Textzeile ein, Beenden mit Leerzeile.
Dieses Programm dient lediglich dazu, den Einsatz von strlen()
zu demonstrieren.
Die Zeilen 13 und 14 geben eine Eingabeaufforderung aus und lesen einen Text in
den String puffer
ein. In Zeile 16 wird der Variablen laenge
mit Hilfe von strlen()
die Länge des Strings puffer
zugewiesen. In Zeile 18 wird sichergestellt, dass der
String nicht leer, sprich seine Länge größer als 1
ist. Denken Sie daran, dass fgets()
die über die Tastatur eingegebene Zeile mitsamt dem Neue-Zeile-Zeichen zurückgibt.
Deshalb enthalten selbst Leerzeilen ein Zeichen: das Neue-Zeile-Zeichen. Wenn der
String nicht leer ist, wird in Zeile 19 die Größe des Strings ausgegeben.
In der C-Bibliothek gibt es drei Funktionen zum Kopieren von Strings. Aufgrund der
Art und Weise, wie Strings in C gehandhabt werden, können Sie nicht einfach einen
String einem anderen zuweisen, wie das in einigen anderen Computersprachen
möglich ist, sondern müssen den Quellstring von seiner Position im Speicher in den
Speicherbereich des Zielstrings kopieren. Die Kopierfunktionen für Strings lauten
strcpy()
, strncpy()
und strdup()
. Wenn Sie eine dieser drei Funktionen verwenden
wollen, müssen Sie die Header-Datei string.h
einbinden.
Die Bibliotheksfunktion strcpy()
kopiert einen ganzen String an eine neue
Speicherstelle. Der Prototyp lautet:
char *strcpy( char *destination, char *source );
Die Funktion strcpy()
kopiert den String (einschließlich des abschließenden
Nullzeichens \0
), auf den source1
zeigt, an die Speicherstelle, auf die destination2
zeigt. Der Rückgabewert ist ein Zeiger auf den neuen String namens destination
.
Wenn Sie strcpy()
verwenden, müssen Sie zuerst Speicherplatz für den Zielstring
reservieren. Die Funktion hat keine Möglichkeit, herauszufinden, ob destination
auf
einen reservierten Speicherplatz zeigt. Wenn kein Speicher zugewiesen wurde, wird
die Funktion wahrscheinlich einen Segmentierungsfehler auslösen, da Ihr Programm
versucht, auf Speicher zuzugreifen, der ihm nicht gehört. Der Einsatz von strcpy()
wird in Listing 16.2 demonstriert.
Verantwortungsbewusste Programmierer geben Speicher, der wie in Listing 16.2 mit
malloc()
reserviert wurde, spätestens am Ende des Programms mit der Funktionfree()
frei. Mehr überfree()
erfahren Sie am Tag 18, »Vom Umgang mit dem Speicher«.
Listing 16.2: Vor dem Einsatz von strcpy() müssen Sie Speicher für den Zielstring reservieren.
1: /* Beispiel für strcpy(). */
2: #include <stdlib.h>
3: #include <stdio.h>
4: #include <string.h>
5:
6: char quelle[] = "Der Quellstring.";
7:
8: int main(void)
9: {
10: char ziel1[80];
11: char *ziel2, *ziel3;
12:
13: printf("Quelle: %s\n", quelle );
14:
15: /* Kopieren in ziel1 OK, da ziel1 auf 80 Bytes */
16: /* reservierten Speicher zeigt. */
17:
18: strcpy(ziel1, quelle);
19: printf("Ziel1: %s\n", ziel1);
20:
21: /* Um in ziel2 zu kopieren, müssen Sie Speicher reservieren. */
22:
23: ziel2 = (char *)malloc(strlen(quelle) +1);
24: strcpy(ziel2, quelle);
25: printf("Ziel2: %s\n", ziel2);
26:
27: /* Nicht kopieren, ohne Speicher für den Zielstring zu reservieren*/
28: /* Der folgende Code kann schwerwiegende Fehler verursachen. */
29:
30: /* strcpy(ziel3, quelle); */
31: return(0);
32: }
Quelle: Der Quellstring.
Ziel1: Der Quellstring.
Ziel2: Der Quellstring.
Dieses Programm zeigt, wie man Strings sowohl in Zeichenarrays (ziel1
, deklariert in
Zeile 10) als auch in Zeichenzeiger kopiert (ziel2
und ziel3
, deklariert in Zeile 11).
Zeile 13 gibt den ursprünglichen Quellstring aus. Dieser String wird dann mit Hilfe von
strcpy()
in ziel1
kopiert (Zeile 18). Zeile 24 kopiert quelle
in ziel2
. Sowohl ziel1
als auch ziel2
werden ausgegeben, um zu beweisen, dass die Funktionsaufrufe
erfolgreich waren. Beachten Sie den Aufruf von malloc()
in Zeile 23. Hier wird
Speicher für den Zeichenzeiger ziel2
reserviert, damit dieser die Kopie von source
aufnehmen kann. Wenn Sie einen String in einen Zeichenzeiger kopieren, für den
kein oder nur unzureichend Speicher reserviert wurde, kann dies unerwartete Folgen
haben.
Die Funktion strncpy()
entspricht weitgehend der Funktion strcpy()
. Im Unterschied
zu strcpy()
können Sie bei strncpy()
aber angeben, wie viele Zeichen Sie kopieren
wollen. Der Prototyp lautet:
char *strncpy(char *destination, char *source, size_t n);
Die Argumente destination
und source
sind Zeiger auf die Ziel- und Quellstrings. Die
Funktion kopiert maximal die ersten n
Zeichen von source
nach destination
. Wenn
source
kürzer als n
Zeichen ist, wird source
mit so vielen Nullzeichen aufgefüllt, dass
insgesamt n
Zeichen nach destination
kopiert werden können. Wenn source
länger
als n
Zeichen ist, wird an destination
kein abschließendes Nullzeichen angehängt.
Der Rückgabewert der Funktion ist der Zeiger destination
.
Listing 16.3 enthält ein Beispiel für die Verwendung von strncpy()
.
Listing 16.3: Die Funktion strncpy().
1: /* Die Funktion strncpy(). */
2:
3: #include <stdio.h>
4: #include <string.h>
5:
6: char ziel[] = "..........................";
7: char quelle[] = "abcdefghijklmnopqrstuvwxyz";
8:
9: int main(void)
10: {
11: size_t n;
12:
13: while (1)
14: {
15: puts("Anzahl der Zeichen, die kopiert werden sollen (1-26)");
16: scanf("%d", &n);
17:
18: if (n > 0 && n< 27)
19: break;
20: }
21:
22: printf("Ziel vor Aufruf von strncpy = %s\n", ziel);
23:
24: strncpy(ziel, quelle, n);
25:
26: printf("Ziel nach Aufruf von strncpy = %s\n", ziel);
27: return(0);
28: }
Anzahl der Zeichen, die kopiert werden sollen (1-26)
15
Ziel vor Aufruf von strncpy = ..........................
Ziel nach Aufruf von strncpy = abcdefghijklmno...........
Dieses Programm zeigt nicht nur, wie man strncpy()
verwendet, sondern auch wie
man sicherstellt, dass nur korrekte Daten vom Anwender eingelesen werden. Die
Zeilen 13 bis 20 enthalten eine while
-Schleife, die den Anwender auffordert, eine
Zahl zwischen 1 und 26 einzugeben. Die Schleife wird so lange durchlaufen, bis ein
gültiger Wert eingegeben wird - vorher wird das Programm nicht fortgeführt. Nach
Eingabe einer Zahl zwischen 1 und 26 gibt Zeile 22 den ursprünglichen Wert von ziel
aus, Zeile 24 kopiert die vom Anwender gewünschte Anzahl Zeichen von quelle
nach
ziel
und Zeile 26 gibt den fertigen Wert von ziel
aus.
Stellen Sie sicher, dass die Anzahl der kopierten Zeichen nicht die reservierte Größe des Zielstrings überschreitet, und denken Sie daran, dass für das Nullzeichen am Ende des Strings Platz gelassen werden muss.
Die Bibliotheksfunktion strdup()
entspricht weitgehend der Funktion strcpy()
. Die
Funktion strdup()
sorgt allerdings selbst dafür, dass für den Zielstring Speicher
reserviert wird, indem sie intern malloc()
aufruft. Dies entspricht unserer
Vorgehensweise in Listing 16.2, wo wir zuerst durch Aufruf von malloc()
Speicher
reserviert und dann strcpy()
aufgerufen haben. Der Prototyp für strdup()
lautet:
char *strdup( char *source );
Das Argument source
ist ein Zeiger auf den Quellstring. Die Funktion liefert einen
Zeiger auf den Zielstring zurück - das heißt den Speicherbereich, der von malloc()
reserviert wurde - oder NULL
, wenn der benötigte Speicherbereich nicht reserviert
werden kann. Listing 16.4 zeigt ein Beispiel für strdup()
. Beachten Sie, dass die
Funktion strdup()
nicht zum ANSI/ISO-Standard gehört. Sie ist aber auf Linux und
vielen anderen Betriebssystemen verfügbar.
Listing 16.4: strdup() kopiert einen String mit automatischer Speicherreservierung.
1: /* Die Funktion strdup(). */
2: #include <stdlib.h>
3: #include <stdio.h>
4: #include <string.h>
5:
6: char quelle[] = "Der Quellstring.";
7:
8: int main(void)
9: {
10: char *ziel;
11:
12: if ( (ziel = strdup(quelle)) == NULL)
13: {
14: fprintf(stderr, "Fehler bei der Speicherresevierung.\n");
15: exit(1);
16: }
17:
18: printf("Das Ziel = %s\n", ziel);
19: return(0);
20: }
Das Ziel = Der Quellstring.
In diesem Listing reserviert strdup()
den notwendigen Speicher für ziel
. Erst danach
wird der übergebene String source
kopiert. Zeile 18 gibt den kopierten String aus.
Wenn Sie den Begriff Konkatenierung nicht kennen, werden Sie sich sicherlich
fragen, was das ist und ob es überhaupt legal ist. Konkatenierung bedeutet einfach,
zwei Strings miteinander zu verbinden, indem man einen String an das Ende eines
anderen Strings anhängt - was fast überall auf der Welt erlaubt ist. Die C-
Standardbibliothek enthält zwei Funktionen zur Stringverkettung: strcat()
und
strncat()
. Beide Funktionen benötigen die Header-Datei string.h
.
Der Prototyp von strcat()
lautet:
char *strcat(char *str1, char *str2);
Die Funktion hängt eine Kopie von str2
an das Ende von str1
und verschiebt das
abschließende Nullzeichen an das Ende des neuen Strings. Sie müssen für str1
genügend Speicher reservieren, damit str1
den neuen String aufnehmen kann. Der
Rückgabewert von strcat()
ist ein Zeiger auf str1
. Ein Beispiel für strcat()
finden
Sie in Listing 16.5.
Listing 16.5: Mit strcat() Strings verketten.
1: /* Die Funktion strcat(). */
2:
3: #include <stdio.h>
4: #include <string.h>
5:
6: char str1[27] = "a";
7: char str2[2];
8:
9: int main(void)
10: {
11: int n;
12:
13: /* Schreibt ein Nullzeichen an das Ende von str2[]. */
14:
15: str2[1] = '\0';
16:
17: for (n = 98; n< 123; n++)
18: {
19: str2[0] = n;
20: strcat(str1, str2);
21: puts(str1);
22: }
23: return(0);
24: }
ab
abc
abcd
abcde
abcdef
abcdefg
abcdefgh
abcdefghi
abcdefghij
abcdefghijk
abcdefghijkl
abcdefghijklm
abcdefghijklmn
abcdefghijklmno
abcdefghijklmnop
abcdefghijklmnopq
abcdefghijklmnopqr
abcdefghijklmnopqrs
abcdefghijklmnopqrst
abcdefghijklmnopqrstu
abcdefghijklmnopqrstuv
abcdefghijklmnopqrstuvw
abcdefghijklmnopqrstuvwx
abcdefghijklmnopqrstuvwxy
abcdefghijklmnopqrstuvwxyz
Die Zahlen von 98 bis 122 entsprechen den ASCII-Codes für die Buchstaben b-z. Das
Programm verwendet diese ASCII-Codes, um die Arbeitsweise von strcat()
zu
verdeutlichen. Die for
-Schleife in den Zeilen 17 bis 22 weist diese ASCII-Codes der
Reihe nach str2[0]
zu. Da str2[1]
bereits das Nullzeichen zugewiesen wurde (Zeile
15), enthält str2
nacheinander die Strings »b
«, »c
« und so weiter. Jeder dieser Strings
wird danach mit str1
verkettet (Zeile 20), dessen Inhalt dann in Zeile 21 auf dem
Bildschirm ausgegeben wird.
Die Bibliotheksfunktion strncat()
führt ebenfalls eine Stringverkettung durch, erlaubt
Ihnen jedoch anzugeben, wie viele Zeichen des Quellstrings an das Ende des
Zielstrings angehängt werden sollen. Der Prototyp lautet:
char *strncat(char *str1, char *str2, size_t n);
Wenn str2
mehr als n
Zeichen enthält, werden die ersten n
Zeichen an das Ende von
str1
angehängt. Wenn str2
weniger als n
Zeichen enthält, wird str2
als Ganzes an
das Ende von str1
gehängt. In beiden Fällen wird ein abschließendes Nullzeichen an
das Ende des resultierenden Strings angehängt. Sie müssen für str1
genügend
Speicher reservieren, damit der Ergebnisstring aufgenommen werden kann. Die
Funktion liefert einen Zeiger auf str1
zurück. In Listing 16.6 nutzen wir strncat()
,
um die gleiche Ausgabe zu erzeugen wie in Listing 16.5.
Listing 16.6: Mit der Funktion strncat() Strings verketten.
1: /* Die Funktion strncat(). */
2:
3: #include <stdio.h>
4: #include <string.h>
5:
6: char str2[] = "abcdefghijklmnopqrstuvwxyz";
7:
8: int main(void)
9: {
10: char str1[27];
11: int n;
12:
13: for (n=1; n< 27; n++)
14: {
15: strcpy(str1, "");
16: strncat(str1, str2, n);
17: puts(str1);
18: }
19: return(0);
20: }
a
ab
abc
abcd
abcde
abcdef
abcdefg
abcdefgh
abcdefghi
abcdefghij
abcdefghijk
abcdefghijkl
abcdefghijklm
abcdefghijklmn
abcdefghijklmno
abcdefghijklmnop
abcdefghijklmnopq
abcdefghijklmnopqr
abcdefghijklmnopqrs
abcdefghijklmnopqrst
abcdefghijklmnopqrstu
abcdefghijklmnopqrstuv
abcdefghijklmnopqrstuvw
abcdefghijklmnopqrstuvwx
abcdefghijklmnopqrstuvwxy
abcdefghijklmnopqrstuvwxyz
Vielleicht fragen Sie sich, wozu die Zeile 15, strcpy(str1, "");
benötigt wird. Diese
Zeile kopiert einen leeren String, der nur aus einem einzigen Nullzeichen besteht,
nach str1
. Das Ergebnis ist, dass das erste Zeichen in str1
- str1[0]
- gleich 0
(dem
Nullzeichen) gesetzt wird. Das Gleiche hätten Sie auch mit der Anweisung str1[0] =
0;
oder str1[0] = '\0';
erreichen können.
Durch Stringvergleiche kann man festzustellen, ob zwei Strings gleich oder nicht
gleich sind. Sind sie nicht gleich, dann ist ein String größer oder kleiner als der
andere. Um zu entscheiden, ob ein String größer oder kleiner als ein anderer Strings
ist, werden die ASCII-Codes der Zeichen in den Strings herangezogen. Für
Buchstaben folgen die ASCII-Codes der Reihenfolge der Buchstaben im Alphabet, mit
der einen seltsam anmutenden Ausnahme, dass alle Großbuchstaben einen kleineren
Wert haben als die Kleinbuchstaben. Das liegt daran, dass Großbuchstaben die ASCII-
Codes 65-90 für A-Z haben, wohingegen die Kleinbuchstaben a-z durch die Werte
97-122 dargestellt werden. Demzufolge ist »ZEBRA
« kleiner als »heute
« - zumindest
wenn man die C-Funktionen verwendet.
Die ANSI/ISO-Bibliothek enthält Funktionen für zwei Arten von Stringvergleichen:
Vergleich zweier ganzer Strings und Vergleich der ersten n
Zeichen zweier Strings.
Die Funktion strcmp()
vergleicht zwei Strings, Zeichen für Zeichen. Der Prototyp lautet:
int strcmp(char *str1, char *str2);
Die Argumente str1
und str2
sind Zeiger auf die Strings, die verglichen werden
sollen. Die Rückgabewerte der Funktion finden Sie in Tabelle 16.1. Listing 16.7
enthält ein Beispiel für strcmp()
.
Listing 16.7: Mit strcmp() Strings vergleichen.
1: /* Die Funktion strcmp(). */
2:
3: #include <stdio.h>
4: #include <string.h>
5:
6: int main(void)
7: {
8: char str1[80], str2[80];
9: int x;
10:
11: while (1)
12: {
13: /* Zwei Strings einlesen. */
14:
15: printf("\n\nErster String (mit Eingabetaste beenden): ");
16: fgets(str1,80,stdin);
17: str1[strlen(str1)-1] = 0;
18:
19: if ( strlen(str1) < 2 )
20: break;
21:
22: printf("\nZweiter String: ");
23: fgets(str2,80,stdin);
24: str2[strlen(str2)-1] = 0;
25:
26: /* Strings vergleichen und Ergebnis ausgeben. */
27:
28: x = strcmp(str1, str2);
29:
30: printf("\nstrcmp(%s,%s) liefert %d zurück", str1, str2, x);
31: }
32: return(0);
33: }
Erster String (mit Eingabetaste beenden): Erster String
Zweiter String: Zweiter String
strcmp(Erster String,Zweiter String) liefert -21 zurück
Erster String (mit Eingabetaste beenden): Test-String
Zweiter String: Test-String
strcmp(test string,test string) liefert 0 zurück
Ersten String eingeben oder mit Eingabetaste beenden: zebra
Zweiten String eingeben: aardvark
strcmp(zebra,aardvark) liefert 25 zurück
Erster String (mit Eingabetaste beenden):
Auf manchen Systemen, wie zum Beispiel Windows, lauten die Rückgabewerte der Funktionen zum Vergleichen von Strings
-1
,0
oder1
anstatt der hier ausgegebenen Werte. Der Wert für ungleich lange Strings wird jedoch immer ungleich Null sein.
Dieses Programm möchte Ihnen die Funktionsweise von strcmp()
veranschaulichen
und fordert Sie deshalb auf, zwei Strings einzugeben (Zeilen 15 und 22). Zeile 30 gibt
das von strcmp()
zurückgegebene Ergebnis auf dem Bildschirm aus. Die Zeilen 17
und 24 entfernen die Neue-Zeile-Zeichen aus den Strings, die von der Funktion
fgets()
zurückgeliefert werden.
Spielen Sie ein wenig mit diesem Programm herum, um ein Gefühl dafür zu
bekommen, wie man mit strcmp()
Strings vergleichen kann. Geben Sie zwei Strings
ein, die bis auf die Groß- und Kleinschreibung identisch sind (zum Beispiel Morgen
und
morgen
). Sie werden feststellen, dass strcmp()
die Groß- und Kleinschreibung
berücksichtigt, das heißt, Groß- und Kleinbuchstaben haben jeweils unterschiedliche
Werte.
Die Bibliotheksfunktion strncmp()
vergleicht eine bestimmte Anzahl von Zeichen
eines Strings mit den Zeichen eines anderen Strings. Der Prototyp lautet:
int strncmp(char *str1, char *str2, size_t n);
Die Funktion strncmp()
vergleicht n
Zeichen von str2
mit str1
. Der Vergleich wird
abgeschlossen, wenn n
Zeichen verglichen oder das Ende von str1
erreicht ist.
Ansonsten entsprechen das Vergleichsverfahren und die Rückgabewerte denen von
strcmp()
. Der Vergleich berücksichtigt die Groß- und Kleinschreibung. Listing 16.8
demonstriert die Verwendung der Funktion strncmp()
.
Listing 16.8: Mit der Funktion strncmp() Teilstrings vergleichen.
1: /* Die Funktion strncmp(). */
2:
3: #include <stdio.h>
4: #include <string.h>
5:
6: char str1[] = "Der erste String.";
7: char str2[] = "Der zweite String.";
8:
9: int main(void)
10: {
11: size_t n, x;
12:
13: puts(str1);
14: puts(str2);
15:
16: while (1)
17: {
18: puts("Anzahl der zu vergleichenden Zeichen (0 für Ende):");
19: scanf("%d", &n);
20:
21: if (n <= 0)
22: break;
23:
24: x = strncmp(str1, str2, n);
25:
26: printf("Bei Vergleich von %d Zeichen liefert strncmp() %d.\n\n",
n, x);
27: }
28: return(0);
29: }
Der erste String.
Der zweite String.
Anzahl der zu vergleichenden Zeichen (0 für Ende):
3
Bei Vergleich von 3 Zeichen liefert strncmp() 0.
Anzahl der zu vergleichenden Zeichen (0 für Ende):
6
Bei Vergleich von 6 Zeichen liefert strncmp() -21.
Anzahl der zu vergleichenden Zeichen (0 für Ende):
0
Dieses Programm vergleicht die beiden Strings, die in den Zeilen 6 und 7 definiert
werden. Die Zeilen 13 und 14 geben die Strings auf dem Bildschirm aus, so dass der
Anwender sehen kann, was verglichen wird. Das Programm tritt in den Zeilen 16 bis
27 in eine while
-Schleife ein, die es erlaubt, mehrere Vergleiche nacheinander
durchzuführen. Wenn der Anwender in den Zeilen 18 und 19 angibt, dass null
Zeichen verglichen werden sollen, wird die Schleife in Zeile 22 beendet. Andernfalls
wird in Zeile 24 die Funktion strncmp()
ausgeführt und das Ergebnis in Zeile 26
ausgegeben.
Leider enthält die ANSI/ISO-C-Bibliothek keine Funktionen für Stringvergleiche, die
die Groß- und Kleinschreibung unberücksichtigt lassen. Linux stellt als Ersatz die
Funktion strcasecmp()
zur Verfügung, doch ist diese nicht unbedingt auf anderen
Unix-Systemen verfügbar. Vergleichsfunktionen, die nicht zwischen Groß- und
Kleinschreibung unterscheiden, betrachten Strings wie Schmidt
und SCHMIDT
als gleich.
Um sich selbst von der Arbeitsweise von strcasecmp()
zu überzeugen, ersetzen Sie
den strcmp()
-Aufruf in Zeile 28 von Listing 16.7 durch strcasecmp()
und starten das
Programm erneut.
Die C-Bibliothek enthält eine Reihe von Funktionen für das Durchsuchen von Strings.
Mit diesen Funktionen können Sie feststellen, ob und wo ein String innerhalb eines
anderen Strings enthalten ist. Sie haben die Wahl zwischen sechs verschiedenen
Suchfunktionen, die alle in der Header-Datei string.h
deklariert sind.
Die Funktion strchr()
sucht nach dem ersten Vorkommen eines angegebenen
Zeichens in einem String. Der Prototyp lautet:
char *strchr(char *str, int ch);
Die Funktion strchr()
durchsucht str
von links nach rechts, bis das Zeichen ch
oder
das abschließende Nullzeichen gefunden wird. Wird ein Vorkommen von ch
gefunden,
liefert die Funktion einen Zeiger darauf zurück. Ansonsten lautet der Rückgabewert
NULL
.
Wenn strchr()
das gesuchte Zeichen findet, liefert sie einen Zeiger auf das Zeichen
zurück. Da str
ein Zeiger auf das erste Vorkommen des Zeichens im String ist, ist es
nicht schwierig, die Position des gefundenen Zeichens zu ermitteln: Subtrahieren Sie
einfach str
von dem Zeigerwert, der von strchr()
zurückgegeben wird. Denken Sie
daran, dass sich das erste Zeichen in einem String an der Position 0
befindet. Wie die
meisten Stringfunktionen von C berücksichtigt auch strchr()
die Groß- und
Kleinschreibung (weshalb zum Beispiel das Zeichen F
in dem String Kaffee
nicht
gefunden wird).
Listing 16.9: Mit strchr() ein einfaches Zeichen in einem String suchen.
1: /* Mit strchr() nach einem einfachen Zeichen suchen. */
2:
3: #include <stdio.h>
4: #include <string.h>
5:
6: int main(void)
7: {
8: char *loc, puffer[80];
9: int ch;
10:
11: /* Den String und das Zeichen eingeben. */
12:
13: printf("Geben Sie den String ein, der durchsucht werden soll: ");
14: fgets(puffer,80,stdin);
15: printf("Geben Sie das Zeichen ein, nach dem gesucht werden soll: ");
16: ch = getchar();
17:
18: /* Suche durchführen. */
19:
20: loc = strchr(puffer, ch);
21:
22: if ( loc == NULL )
23: printf("Das Zeichen %c wurde nicht gefunden.\n", ch);
24: else
25: printf("Das Zeichen %c wurde an der Position %d gefunden.\n",
26: ch, (int)(loc-puffer));
27: return(0);
28: }
Geben Sie den String ein, der durchsucht werden soll: Alles klar auf der Andrea Doria?
Geben Sie das Zeichen ein, nach dem gesucht werden soll: D
Das Zeichen D wurde an der Position 26 gefunden.
Dieses Programm verwendet strchr()
in Zeile 20, um einen String nach einem
Zeichen zu durchsuchen. strchr()
liefert einen Zeiger auf die Position zurück, an der
das Zeichen das erste Mal gefunden wird, oder NULL
, wenn das gesuchte Zeichen nicht
gefunden wird. Zeile 22 prüft, ob der Wert von loc
NULL
ist, und gibt eine
entsprechende Nachricht aus. Wie bereits im Abschnitt »Die Funktion strchr()
«
beschrieben wurde, ermittelt man die Position des Zeichens im String, indem man den
Stringzeiger von dem Wert subtrahiert, der von der Funktion zurückgeliefert wird.
Die Bibliotheksfunktion strrchr()
entspricht strchr()
, sucht aber nach dem letzten
Vorkommen eines angegebenen Zeichens. Mit anderen Worten, die Suche beginnt
am Ende des Strings. Der Prototyp lautet:
char *strrchr(char *str, int ch);
Die Funktion strrchr()
liefert einen Zeiger auf das letzte Vorkommen von ch
in str
zurück oder NULL
, wenn keine Übereinstimmung gefunden wurde. Ändern Sie in
Listing 16.9 in der Zeile 20 den Aufruf von strchr()
in strrchr()
, um sich einen
Eindruck zu verschaffen, wie diese Funktion arbeitet.
Die Bibliotheksfunktion strcspn()
durchsucht einen String nach dem ersten
Vorkommen eines der Zeichen in einem zweiten String. Der Prototyp lautet:
size_t strcspn(char *str1, char *str2);
Die Funktion strcspn()
beginnt die Suche mit dem ersten Zeichen von str1
und sucht
nach allen Zeichen, die in str2
enthalten sind. Beachten Sie, dass die Funktion nicht
nach dem String str2
sucht, sondern nur nach den einzelnen Zeichen, die er enthält.
Wenn die Funktion eine Übereinstimmung feststellt, wird die Position des Zeichens in
str1
zurückgeliefert. Wird keine Übereinstimmung gefunden, liefert strcspn()
den
Wert von strlen(str1)
zurück. Damit wird angezeigt, dass die erste Übereinstimmung
das Nullzeichen war, das den String abgeschlossen hat. Listing 16.10 demonstriert,
wie Sie strcspn()
einsetzen können.
Listing 16.10: Mit strcspn() nach einem Satz von Zeichen suchen.
1: /* Mit strcspn() suchen. */
2:
3: #include <stdio.h>
4: #include <string.h>
5:
6: int main(void)
7: {
8: char puffer1[80], puffer2[80];
9: size_t loc;
10:
11: /* Strings eingeben. */
12:
13: printf("Geben Sie den String ein, der durchsucht werden soll: ");
14: fgets(puffer1,80,stdin);
15: printf("Geben Sie den String mit den zu suchenden Zeichen ein: ");
16: fgets(puffer2,80,stdin);
17: puffer2[strlen(puffer2)-1] = 0; /*Entfernt das Neue-Zeile-Zeichen*/
18:
19: /* Suche durchführen. */
20: loc = strcspn(puffer1, puffer2);
21:
22: if ( loc == strlen(puffer1) )
23: printf("Es wurde keine Übereinstimmung gefunden.\n");
24: else
25: printf("Erste Übereinstimmung an Position %d.\n", loc);
26: return(0);
27: }
Geben Sie den String ein, der durchsucht werden soll: Alles klar auf der Andrea Doria?
Geben Sie den String mit den zu suchenden Zeichen ein: Das
Erste Übereinstimmung an Position 4.
Dieses Listing ist dem Listing 16.10 sehr ähnlich. Anstatt nach dem ersten
Vorkommen eines einzigen Zeichens zu suchen, sucht es nach dem ersten
Vorkommen eines der Zeichen im zweiten String. Das Programm ruft strcspn()
in
Zeile 20 mit puffer1
und puffer2
auf. Wenn irgendwelche der Zeichen in puffer2
auch in puffer1
vorkommen, liefert strcspn()
die Position des ersten gefundenen
Vorkommens in str1
zurück. Zeile 22 prüft, ob der Rückgabewert gleich
strlen(puffer1)
ist. Ist der Wert strlen(puffer1)
, wurden keine Zeichen gefunden,
und eine entsprechende Nachricht wird in Zeile 23 ausgegeben. Wenn ein Wert
gefunden wurde, wird die Position des Zeichens im String ausgegeben.
Diese Funktion ist, wie Sie gleich sehen werden, eng mit der obigen Funktion,
strcspn()
, verbunden. Der Prototyp lautet:
size_t strspn(const char *str, char *accept);
Die Funktion strspn()
durchsucht str
und vergleicht den String Zeichen für Zeichen
mit den Zeichen in accept
. Als Ergebnis liefert die Funktion die Position des ersten
Zeichens in str
zurück, das nicht mit einem Zeichen in accept
übereinstimmt. Mit
anderen Worten, strspn()
liefert die Länge des ersten Abschnitts von str
zurück, der
gänzlich aus Zeichen besteht, die in accept
enthalten sind. Gibt es keine
Übereinstimmung, lautet der Rückgabewert 0
. Ein Beispiel für die Verwendung von
strspn()
finden Sie in Listing 16.11.
Listing 16.11: Mit strspn() nach dem ersten nicht übereinstimmenden Zeichen suchen.
1: /* Mit strspn() suchen. */
2:
3: #include <stdio.h>
4: #include <string.h>
5:
6: int main(void)
7: {
8: char puffer1[80], puffer2[80];
9: size_t loc;
10:
11: /* Strings eingeben. */
12:
13: printf("Geben Sie den String ein, der durchsucht werden soll: ");
14: fgets(puffer1,80,stdin);
15: printf("Geben Sie den String mit den zu suchenden Zeichen ein: ");
16: fgets(puffer2,80,stdin);
17: puffer2[strlen(puffer2)-1] = 0; /*Entfernt das Neue-Zeile-Zeichen*/
18:
19: /* Suche durchführen. */
20: loc = strspn(puffer1, puffer2);
21:
22: if ( loc == 0 )
23: printf("Es wurde keine Übereinstimmung gefunden.\n");
24: else
25: printf("Die Zeichen stimmen bis Position %d überein.\n", loc-1);
26: return 0;
27: }
Geben Sie den String ein, der durchsucht werden soll: Alles klar auf der Andrea Doria?
Geben Sie den String mit den zu suchenden Zeichen ein: Alles klar oder?
Die Zeichen stimmen bis Position 11 überein.
Dieses Programm entspricht unserem obigen Beispiel, außer das in Zeile 20 die
Funktion strspn()
statt strcspn()
aufgerufen wird und in Zeile 22 die Abfrage des
Rückgabewertes von strspn()
auf 0
geändert wurde. Die Funktion gibt die Position
des ersten Zeichens von puffer1
zurück, das nicht in puffer2
enthalten ist. Die Zeilen
22 bis 25 werten den Rückgabewert aus und geben eine entsprechende Nachricht
aus.
Die Bibliotheksfunktion strpbrk()
ist der Funktion strcspn()
sehr ähnlich. Sie
durchsucht einen String nach dem ersten Vorkommen eines der Zeichen eines
anderen Strings. Der Unterschied zu strcspn()
liegt darin, dass die abschließenden
Nullzeichen nicht in die Suche mit einbezogen werden. Der Prototyp der Funktion
lautet:
char *strpbrk(char *str, char *accept);
Die Funktion strpbrk()
liefert einen Zeiger auf das erste Zeichen in str
zurück, das
einem der Zeichen in accept
entspricht. Wird keine Übereinstimmung gefunden,
liefert die Funktion NULL
zurück. Wie schon bei der Funktion strchr()
erläutert,
berechnet man die Position der ersten Übereinstimmung in str
, indem man den
Zeiger str
von dem Zeiger, der von strpbrk()
zurückgeliefert wird, subtrahiert (was
natürlich nur geht, wenn der Wert ungleich NULL
ist). Ersetzen Sie doch einfach mal
die Funktion strcspn()
aus Zeile 20 des Listings 16.10 durch strpbrk()
.
Die letzte und vielleicht nützlichste C-Funktion zum Durchsuchen von Strings ist
strstr()
. Diese Funktion sucht nach dem ersten Vorkommen eines Strings in einem
anderen String, wobei nach dem ganzen String und nicht nur nach den einzelnen
Zeichen innerhalb des Strings gesucht wird. Der Prototyp lautet:
char *strstr(char *haystack, char *needle);
Die Funktion strstr()
liefert einen Zeiger auf das erste Vorkommen von needle3
in
haystack4
. Wird keine Übereinstimmung gefunden, liefert die Funktion NULL
zurück.
Wenn die Länge von needle
0
ist, liefert die Funktion haystack
zurück. Wenn strstr()
eine Übereinstimmung findet, können Sie die Position des ersten Vorkommens von
needle
berechnen, indem Sie die Zeiger, wie bereits für strchr()
erläutert,
voneinander subtrahieren. Die Funktion strstr()
berücksichtigt die Groß- und
Kleinschreibung. In Listing 16.12 sehen Sie ein Beispiel für strstr()
.
Listing 16.12: Mit strstr() nach einem String in einem String suchen.
1: /* Mit strstr() suchen. */
2:
3: #include <stdio.h>
4: #include <string.h>
5:
6: int main(void)
7: {
8: char *loc, puffer1[80], puffer2[80];
9:
10: /* Strings eingeben. */
11:
12: printf("Geben Sie den String ein, der durchsucht werden soll: ");
13: fgets(puffer1,80,stdin);
14: printf("Geben Sie den zu suchenden String ein: ");
15: fgets(puffer2,80,stdin);
16: puffer2[strlen(puffer2)-1] = 0; /*Entfernt das Neue-Zeile-Zeichen*/
17:
18: /* Suche durchführen. */
19: loc = strstr(puffer1, puffer2);
20:
21: if ( loc == NULL )
22: printf("Es wurde keine Übereinstimmung gefunden.\n");
23: else
24: printf("%s wurde an Position %d gefunden.\n",puffer2,loc-puffer1);
25: return(0);
26: }
Geben Sie den String ein, der durchsucht werden soll: Alles klar auf der Andrea Doria?
Geben Sie den zu suchenden String ein: auf
auf wurde an Position 11 gefunden.
Diese Funktion bietet eine weitere Möglichkeit, einen String zu durchsuchen. Diesmal
können Sie einen kompletten String innerhalb eines anderen Strings suchen. In den
Zeilen 12 bis 15 wird der Anwender aufgefordert, die zwei dafür benötigten Strings
einzugeben. Zeile 19 verwendet strstr()
, um in dem ersten String, puffer1
, nach
dem zweiten String, puffer2
, zu suchen. Es wird ein Zeiger auf das erste Vorkommen
zurückgeliefert oder NULL
, wenn der String nicht gefunden wurde. Die Zeilen 21 bis 24
werten den Rückgabewert loc
aus und geben eine entsprechende Nachricht aus.
Manchmal ist es erforderlich, die Stringdarstellung einer Zahl in eine tatsächliche
numerische Variable umzuwandeln - beispielsweise den String "123"
in eine Variable
vom Typ int
mit dem Wert 123
. Es gibt drei Funktionen, mit denen man einen String
in eine Zahl konvertieren kann. Sie werden in den folgenden Abschnitten erläutert,
ihre Prototypen stehen in der Header-Datei stdlib.h
.
Die Bibliotheksfunktion atoi()
konvertiert einen String in einen Integer. Der Prototyp
der Funktion lautet:
int atoi(char *ptr);
Die Funktion atoi()
wandelt den String, auf den ptr
zeigt, in einen Integer um.
Neben Ziffern kann der String auch führende Whitespace-Zeichen und ein Plus- oder
Minuszeichen enthalten. Die Umwandlung beginnt am Anfang des Strings und wird so
lange durchgeführt, bis ein unkonvertierbares Zeichen (zum Beispiel ein Buchstabe
oder ein Satzzeichen) auftritt. Der resultierende Integer wird an das aufrufende
Programm zurückgegeben. Werden keine konvertierbaren Zeichen gefunden, liefert
atoi() d
en Wert 0
zurück. Tabelle 16.2 enthält einige Beispiele.
Das erste Beispiel ist eindeutig und bedarf wohl keiner Erklärung. Im zweiten Beispiel
kann es Sie vielleicht etwas irritieren, dass ".6"
nicht umgewandelt wurde. Dann
möchte ich Sie noch einmal daran erinnern, dass wir hier Strings in Integer
umwandeln. Das dritte Beispiel ist ebenfalls eindeutig: Die Funktion interpretiert das
Pluszeichen als Teil der Zahl. Das vierte Beispiel lautet "elf"
. Die atoi()
-Funktion
sieht nur die einzelnen Zeichen, sie kann keine Wörter umwandeln, auch keine
Zahlwörter. Da der String nicht mit einer Zahl beginnt, liefert atoi() 0
zurück. Das
Gleiche gilt auch für das letzte Beispiel.
Die Bibliotheksfunktion atol()
entspricht im Großen und Ganzen der Funktion
atoi()
. Allerdings liefert Sie einen long
-Wert zurück. Der Prototyp der Funktion
lautet:
long atol(char *ptr);
Würde man die Strings aus Tabelle 16.2 mit atol()
umwandeln, erhielte man die
gleichen Werte wie für atoi()
, nur dass die Werte vom Typ long
und nicht vom Typ
int
wären.
Die Funktion atof()
konvertiert einen String in einen double
-Wert. Der Prototyp
lautet:
double atof(char *str);
Das Argument str
zeigt auf den zu konvertierenden String. Dieser String kann
führende Whitespace-Zeichen, ein Plus- oder ein Minuszeichen enthalten. Die Zahl
kann die Ziffern 0-9, den Dezimalpunkt und die Zeichen e
oder E
für den Exponenten
enthalten. Wenn es keine konvertierbaren Zeichen gibt, liefert atof()
0
zurück.
Tabelle 16.3 verdeutlicht anhand einiger Beispiele, wie atof()
arbeitet.
In Listing 16.13 können Sie selbst Strings eingeben, die konvertiert werden sollen.
Listing 16.13: Mit atof() Strings in numerische Variablen vom Typ double konvertieren.
1: /* Beispiel für die Verwendung von atof(). */
2:
3: #include <string.h>
4: #include <stdio.h>
5: #include <stdlib.h>
6:
7: int main(void)
8: {
9: char puffer[80];
10: double d;
11:
12: while (1)
13: {
14: printf("\nUmzuwandelnder String (Leerzeile für Ende): ");
15: fgets(puffer,80,stdin);
16:
17: if ( strlen(puffer) < 2 )
18: break;
19:
20: d = atof( puffer );
21:
22: printf("Der umgewandelte Wert lautet %f.\n", d);
23: }
24: return(0);
25:}
Umzuwandelnder String (Leerzeile für Ende): 1009.12
Der umgewandelte Wert lautet 1009.120000.
Umzuwandelnder String (Leerzeile für Ende): abc
Der umgewandelte Wert lautet 0.000000.
Umzuwandelnder String (Leerzeile für Ende): 3
Der umgewandelte Wert lautet 3.000000.
Umzuwandelnder String (Leerzeile für Ende):
Die while
-Schleife in den Zeilen 12 bis 23 führt das Programm so lange aus, bis Sie
eine leere Zeile eingeben. Die Zeilen 14 und 15 fordern Sie auf, einen Wert
einzugeben. Zeile 17 prüft, ob eine Leerzeile eingegeben wurde. Wenn ja, steigt das
Programm aus der while
-Schleife aus und wird beendet. Zeile 20 ruft atof()
auf und
konvertiert den eingegebenen Wert (puffer
) in einen Wert d
vom Typ double
. Zeile 22
gibt das Ergebnis der Umwandlung aus.
Die Header-Datei ctype.h
enthält Prototypen für eine Reihe von Funktionen zum
Prüfen von Zeichen, die wahr
oder falsch
zurückliefern - je nachdem ob das Zeichen
einer bestimmten Klasse von Zeichen angehört oder nicht. Sie können mit diesen
Funktionen zum Beispiel prüfen, ob es sich bei einem Zeichen um einen Buchstaben
oder um eine Zahl handelt? Die Funktionen is
xxxx
()
sind eigentlich Makros, die in
ctype.h
definiert sind. Näheres zu Makros erfahren Sie am Tag 20, »Compiler für
Fortgeschrittene«. Wenn Sie sich bis dort vorgekämpft haben, werden Sie
wahrscheinlich einen Blick auf die Definitionen in ctype.h
werfen wollen, um zu
sehen, wie alles funktioniert. Im Moment reicht es, wenn Sie wissen, wie die Makros
eingesetzt werden.
Die is
xxxx
()
-Makros haben alle den gleichen Prototyp:
int isxxxx(int ch);
In der obigen Zeile ist ch
das zu testende Zeichen. Der Rückgabewert ist wahr
(ungleich
Null), wenn das Zeichen der überprüften Klasse angehört, und falsch
(Null), wenn das
Zeichen nicht der Klasse angehört. In Tabelle 16.4 finden Sie die komplette Liste der
is
xxxx
()
-Makros.
Tabelle 16.4: Die isxxxx()-Makros.
Sie können viele interessante Dinge mit den Zeichen-Makros machen. Nehmen Sie
zum Beispiel die Funktion get_int()
aus Listing 16.14. Diese Funktion liest einen
Integer-Wert Zeichen für Zeichen aus stdin
ein und liefert ihn als Variable vom Typ
int
zurück. Die Funktion überspringt führende Whitespace-Zeichen und liefert 0
zurück, wenn das erste Nicht-Whitespace-Zeichen kein numerisches Zeichen ist.
Listing 16.14: Mit den Makros isxxxx() eine Funktion implementieren, die einen Integer einliest.
1: /* Mit den Zeichen-Makros einen Integer erzeugen */
2: /* erzeugen. */
3: #include <stdio.h>
4: #include <ctype.h>
5:
6: int get_int(void);
7:
8: int main(void)
9: {
10: int x;
11: printf("Geben Sie einen Integer ein: ") ;
12: x = get_int();
13: printf("Sie haben %d eingegeben.\n", x);
14: return 0;
15: }
16:
17: int get_int(void)
18: {
19: int ch, i, vorzeichen = 1;
20:
21: /* Überspringt alle führenden Whitespace-Zeichen. */
22:
23: while ( isspace(ch = getchar()) )
24: ;
25:
26: /* Wenn das erste Zeichen nicht nummerisch ist, stelle das */
27: /* Zeichen zurück und liefere 0 zurück. */
28:
29: if (ch != '-' && ch != '+' && !isdigit(ch) && ch != EOF)
30: {
31: ungetc(ch, stdin);
32: return 0;
33: }
34:
35: /* Wenn das erste Zeichen ein Minuszeichen ist, */
36: /* setze Vorzeichen entsprechend. */
37:
38: if (ch == '-')
39: vorzeichen = -1;
40:
41: /* Wenn das erste Zeichen ein Plus- oder Minuszeichen war, */
42: /* hole das nächste Zeichen. */
43:
44: if (ch == '+' || ch == '-')
45: ch = getchar();
46:
47: /* Lies die Zeichen, bis eine Nichtziffer eingegeben wird. */
48: /* Weise die Werte i zu. */
49:
50: for (i = 0; isdigit(ch); ch = getchar() )
51: i = 10 * i + (ch - '0');
52:
53: /* Mache Ergebnis negativ, wenn das Vorzeichen negativ ist. */
54:
55: i *= vorzeichen;
56:
57: /* Wenn kein EOF angetroffen wurde, muss eine Nichtziffer */
58: /* eingelesen worden sein. Also zurückstellen. */
59:
60: if (ch != EOF)
61: ungetc(ch, stdin);
62:
63: /* Den eingegebenen Wert zurückgeben. */
64:
65: return i;
66: }
Geben Sie einen Integer ein: -100
Sie haben -100 eingegeben.
Geben Sie einen Integer ein: abc3.145
Sie haben 0 eingegeben.
Geben Sie einen Integer ein: 9 9 9
Sie haben 9 eingegeben.
Geben Sie einen Integer ein: 2.5
Sie haben 2 eingegeben.
Dieses Programm verwendet in den Zeilen 31 und 61 die Bibliotheksfunktion
ungetc()
, die Sie bereits vom Tag 13, »Mit Bildschirm und Tastatur arbeiten«, kennen.
Denken Sie daran, dass diese Funktion ein Zeichen »zurückstellt«, d.h. an den
angegebenen Stream zurückgibt. Dieses zurückgegebene Zeichen ist das erste, das bei
der nächsten Leseoperation des Programms eingelesen wird. Dies ist wichtig, wenn
die Funktion get_int()
ein nichtnumerisches Zeichen aus stdin
ausliest, das
eigentlich nachfolgenden Leseoperationen zur Verfügung stehen sollte.
Die main()
-Funktion dieses Programms ist recht einfach. In Zeile 19 wird eine Integer-
Variable x
deklariert, der in Zeile 12 der Rückgabewert der get_int()
-Funktion
zugewiesen wird. Anschließend erfolgt die Ausgabe auf den Bildschirm (Zeile 13). Die
get_int()
-Funktion macht den ganzen Rest des Programms aus.
Die Funktion get_int()
ist nicht ganz so einfach aufgebaut. Um führende Whitespace-
Zeichen, die eventuell eingegeben wurden, zu entfernen, iteriert Zeile 23 durch eine
while
-Schleife. Das Makro isspace()
prüft, ob es sich bei dem übergebenen Zeichen -
in unserem Falle ch
, das mit der Funktion getchar()
eingelesen wird - um ein
Leerzeichen handelt. Wenn ja, wird ein weiteres Zeichen überprüft, und zwar so lange
bis ein Nicht-Whitespace eingelesen wird. Zeile 29 prüft, ob das Zeichen verwendbar
ist. Zeile 29 könnte man auch lesen als »Wenn das eingelesene Zeichen kein
Vorzeichen, keine Ziffer und kein Dateiende-Zeichen ist«. Ist diese Bedingung wahr,
wird in Zeile 31 ungetc()
verwendet, um das Zeichen zurückzustellen und zu main()
zurückzukehren. Ist das Zeichen dagegen verwendbar, wird die Funktion weiter
ausgeführt.
Die Zeilen 38 bis 45 behandeln das Vorzeichen der Zahl. Zeile 38 prüft, ob das
eingegebene Zeichen ein negatives Vorzeichen ist. Wenn ja, wird die Variable
vorzeichen
auf -1
gesetzt. vorzeichen
wird dazu benutzt, um die endgültige Zahl
später positiv oder negativ zu machen (Zeile 55). Da die Zahlen standardmäßig positiv
sind, reicht es, das negative Vorzeichen zu berücksichtigen. Wurde ein Vorzeichen
eingegeben, muss allerdings noch ein weiteres Zeichen eingelesen werden. Das
übernehmen die Zeilen 44 und 45.
Das Herz der Funktion ist die for
-Schleife in den Zeilen 50 und 51, die so lange
Zeichen einliest, wie es sich bei den Zeichen um Ziffern handelt. Zeile 51 mag auf den
ersten Blick etwas verwirrend erscheinen. Diese Zeile übernimmt die einzelnen
eingegebenen Zeichen und wandelt sie in eine Zahl um. Durch die Subtraktion des
Zeichens '0'
von der eingegebenen Ziffer wird der ASCII-Code der Ziffer in eine
echte Zahl umgewandelt. Dieser Wert wird zu dem letzten Wert, multipliziert mit 10,
addiert. (Die Multiplikation des bisherigen Wertes mit 10 wird erforderlich, weil die
höchsten Ziffern der Zahl zuerst eingelesen werden.) Die for
-Schleife wird so lange
durchlaufen, bis eine Nichtziffer eingegeben wird. Am Schluss wird der Wert in Zeile
55 noch mit dem Vorzeichen multipliziert, und die Umwandlung der Zeicheneingabe
in eine Zahl ist komplett.
Bevor das Programm zurückkehrt, müssen noch einige Aufräumarbeiten erledigt
werden. Wenn das letzte Zeichen nicht EOF war, muss es zurückgegeben werden (für
den Fall, dass es anderswo benötigt wird). Dieser Schritt erfolgt in Zeile 61. Mit Zeile
65 kehrt die Programmausführung aus get_int()
zurück.
Die Header-Datei ctype.h
enthält noch zwei weitere nützliche Funktionen, mit denen
man Groß- in Kleinbuchstaben umwandeln kann und umgekehrt. Diese Funktionen
sind wie folgt definiert:
int toupper (int c);
int tolower (int c);
Jede dieser Funktionen übernimmt ein int
-Argument und gibt einen int
-Wert zurück.
Wenn die Schreibweise bereits korrekt ist oder es sich um ein nichtalphabetisches
Zeichen handelt, geben die Funktionen die Buchstaben beziehungsweise das Zeichen
unverändert zurück. In Listing 16.15 sehen Sie ein Beispiel für die Verwendung dieser
Funktionen.
Listing 16.15: Mit der Funktion tolower() einen String in Kleinbuchstaben umwandeln.
1: /* Beispiel für die Funktion tolower() */
2: #include <stdio.h>
3: #include <ctype.h>
4:
5: char* kleinschreibung(char *str);
6:
7: int main(void)
8: {
9: char puffer[80];
10:
11: printf("Geben Sie den umzuwandelnden String ein: ");
12: fgets(puffer,80,stdin);
13:
14: kleinschreibung(puffer);
15:
16: printf(puffer);
17:
18: return 0;
19: }
20:
21: char* kleinschreibung(char *str)
22: {
23: int k ;
24:
25: for (k = 0 ; str [k] ; k++)
26: str[k] = tolower(str[k]);
27:
28: return str ;
29: }
Geben Sie den umzuwandelnden String ein: GeMischTe SchreibWEISE
gemischte schreibweise
In diesem Beispiel ist nur sehr wenig neu. Die Zeilen 11 und 12 fordern Sie auf, eine
Textzeile einzugeben, die dann in das Zeichenarray puffer
eingelesen wird. Dieses
Zeichenarray wird der Funktion kleinschreibung()
übergeben und in Zeile 16 auf
dem Bildschirm ausgegeben. Die Funktion kleinschreibung()
wird in den Zeilen 21
bis 29 definiert. Sie übernimmt einen Zeiger auf ein Zeichenarray als Argument und
liefert am Ende einen Zeiger auf das gleiche Array zurück. Die Hauptarbeit der
Funktion steckt in den Zeilen 25 und 26. Zeile 25 ist eine for
-Schleife, die endet,
wenn das Zeichen an der Position k
im Array str
das Nullzeichen \0
ist. Für jeden
Wert von k
, der nicht den Testbedingungen der for
-Schleife entspricht, wandelt die
Anweisung in Zeile 26 das Zeichen in einen Kleinbuchstaben um. Beachten Sie, dass
keine Prüfung benötigt wird, um sicherzustellen, dass das umzuwandelnde Zeichen ein
Buchstabe des Alphabets ist.
Die heutige Lektion hat Ihnen verschiedene Möglichkeiten gezeigt, wie Sie in C Strings manipulieren können. Mit den Funktionen der C-Standardbibliothek können Sie Strings kopieren, verketten, vergleichen und durchsuchen. Diese Aufgaben sind unverzichtbarer Bestandteil der meisten Programmierprojekte. Außerdem enthält die Standardbibliothek Funktionen für die Umwandlung in Groß- beziehungsweise Kleinschreibung und für das Konvertieren von Strings in Zahlen. Schließlich gibt es in C eine Reihe von Zeichentestfunktionen oder vielmehr Makros, mit denen man prüfen kann, ob ein Zeichen einer bestimmten Zeichenklasse angehört. Mit Hilfe dieser Makros können Sie Ihre eigenen Eingabefunktionen erzeugen.
Frage:
Woher weiß ich, ob eine Funktion ANSI/ISO-kompatibel ist?
Antwort:
Wenn Sie im Handbuch oder der Manpage für die Funktion nachsehen,
werden Sie dort einen Abschnitt »CONFORMING TO« finden. Dieser
Abschnitt teilt Ihnen mit, welchem Standard die Funktion entspricht. Die
Übereinstimmung mit dem ANSI/ISO-Standard wird nur angegeben, wenn Sie
eine ältere Version der Manpages haben. Denken Sie daran, dass der ISO-
Standard auf ANSI aufbaut (siehe Tag 1, »Einführung in Linux und die
Programmiersprache C«). Auf anderen Plattformen müssen Sie die
entsprechenden Referenzhandbücher zu Rate ziehen.
Frage:
Wurden heute alle verfügbaren Stringfunktionen angesprochen?
Antwort:
Nein. Die heute vorgestellten Stringfunktionen sollten aber ausreichen, um so
ziemlich alle Ihre Bedürfnisse zu befriedigen. Informationen zu den anderen
Funktionen finden Sie in den Manpages.
Frage:
Ignoriert strcat()
nachfolgende Leerzeichen?
Antwort:
Nein. strcat()
behandelt Leerzeichen wie jedes andere Zeichen.
Frage:
Kann ich Zahlen in Strings konvertieren?
Antwort:
Ja. Sie können eine Funktion schreiben, die der in Listing 16.16 ähnlich ist,
oder in Ihrer Bibliothekreferenz nachschauen, ob es in der Bibliothek eine
passende Funktion gibt. Zu den üblicherweise verfügbaren Funktionen
gehören itoa()
, ltoa()
und ultoa()
. Sie können aber auch sprintf()
verwenden.
Der Workshop enthält Quizfragen, die Ihnen helfen sollen, Ihr Wissen zu festigen, sowie Übungen, die Sie anregen sollen, das Gelernte umzusetzen und eigene Erfahrungen zu sammeln. Die Lösungen zu den Fragen und den Übungen finden Sie in Anhang C.
strcmp()
und strncmp()
?
strcmp()
und strcasecmp()
?
isascii()
?
var
wahr
zurückgeben?
int var = 1;
x
wahr
zurückgeben?
char x = 65;
atoi()
zurückliefern, wenn ihr die folgenden Werte
übergeben würden?
"65"
"81.23"
"-34.2"
"zehn"
"+12hundert"
"negativ100"
atof()
zurückliefern, wenn ihr die folgenden Werte
übergeben würden?
"65"
"81.23"
"-34.2"
"zehn"
"+12hundert
"1e+3"
char *string1, string2;
string1 = "Hallo Welt";
strcpy( string2, string1);
printf( "%s %s", string1, string2 );
Aufgrund der vielen möglichen Antworten gibt es zu den folgenden Übungen keine Lösungen.
Bradley
, Lee
und Jones
lautet,
speichern Sie diese Eingabe als B. L. Jones
. Geben Sie den neuen Namen auf
den Bildschirm aus.
strstr()
findet das erste Vorkommen eines Strings in einem
anderen und berücksichtigt dabei die Groß- und Kleinschreibung. Schreiben Sie
eine Funktion, die die gleiche Aufgabe ausführt, ohne jedoch die Groß- und
Kleinschreibung zu berücksichtigen.
printf
« durchsuchen lassen, sollte das Programm alle Zeilen
auflisten, in der die Funktion printf()
aufgerufen wird.
stdin
einliest. Schreiben Sie eine Funktion get_float()
, die einen Fließkommawert von
stdin
einliest.