C-Programmierung: Zeichenkettenfunktionen
Inhaltsverzeichnis |
Zeichenkettenfunktionen [Bearbeiten]
Für die Bearbeitung von Strings stellt C eine Reihe von Bibliotheksfunktionen zu Verfügung:
strcpy [Bearbeiten]
char* strcpy(char* Ziel, const char* Quelle)
Kopiert einen String in einen anderen (Quelle nach Ziel) und liefert Zeiger auf Ziel als Funktionswert. Bitte beachten Sie, dass eine Anweisung text2 = text1 für ein Array nicht möglich ist. Für eine Kopie eines Strings in einen anderen ist immer die Anweisung strcpy nötig, da eine Zeichenkette immer zeichenweise kopiert werden muss.
Beispiel:
-
#include <stdio.h> -
#include <string.h> -
-
int main(void)
-
{ -
char text[20];
-
-
strcpy(text, "Hallo!");
-
printf("%s\n", text);
-
strcpy(text, "Ja Du!");
-
printf("%s\n", text);
-
return 0;
-
}
Nach dem Übersetzen und Ausführen erhält man die folgende Ausgabe:
Hallo! Ja Du!
strncpy [Bearbeiten]
char* strncpy(char* Ziel, const char* Quelle, size_t num)
Kopiert num-Zeichen von Quelle zu Ziel. Wenn das Ende des Ziel C-String (welches ein null-Character ('\0') signalisiert) gefunden wird, bevor num-Zeichen kopiert sind, wird Ziel mit '\0'-Zeichen aufgefüllt bis die komplette Anzahl von num-Zeichen in Quelle geschrieben ist.
Wichtig: strncpy() fügt selbst keinen null-Character ('\0') an das Ende von Ziel. Soll heißen: Ziel wird nur null-Terminiert wenn die Länge des C-Strings Quelle kleiner ist als num.
Beispiel:
-
/* strncpy beispiel*/ -
#include <stdio.h> -
#include <string.h> -
-
int main ()
-
{ -
char strA[] = "Hallo!"; -
char strB[6]; -
-
strncpy(strB, strA, 5); -
-
/* Nimm die Anzahl von Bytes in strB (6), ziehe 1 ab (= 5) um auf den letzten index zu kommen, -
dann füge dort ein null-Terminierer ein. */ -
strB[sizeof(strB)-1] = '\0'; -
-
puts(strB); -
-
return 0; -
}
Vorsicht: Benutzen Sie sizeof() in diesem Zusammenhang nur bei Character Arrays. sizeof() gibt die Anzahl der reservierten Bytes zurück. In diesem Fall: 6 (Größe von strB) * 1 Byte (Character) = 6.
Nach dem Übersetzen und Ausführen erhält man die folgende Ausgabe:
Hallo
strcat [Bearbeiten]
char* strcat(char* s1, const char* s2)
Verbindet zwei Zeichenketten miteinander. Natürlich wird das Stringende-Zeichen \0 von s1 überschrieben. Voraussetzung ist, dass s2 in s1 Platz hat.
Beispiel:
-
#include <stdio.h> -
#include <string.h> -
-
int main(void)
-
{ -
char text[20];
-
strcpy(text, "Hallo!");
-
printf("%s\n", text);
-
strcat(text, "Ja du!");
-
printf("%s\n", text);
-
return 0;
-
}
Nach dem Übersetzen und Ausführen erhält man die folgende Ausgabe:
Hallo! Hallo!Ja du!
Wie Sie sehen wird der String in Zeile 9 diesmal nicht überschrieben, sondern am Ende angehängt.
strncat [Bearbeiten]
Eine sichere Variante ist strncat:
char* strncat(char* s1, const char* s2,size_t n)
Es werden nur n Elemente angehängt. Damit wird sichergestellt, dass nicht in einen undefinierten Speicherbereich geschrieben wird.
In jedem Fall wird jedoch ein '\0' - Zeichen an das Ende der Resultat-Zeichenfolge angehängt.
Soweit nicht anders angegeben, ist das Ergebnis für überlappende Bereiche nicht definiert.
Anmerkung: n ist so zu wählen, das die Länge der Resultat-Zeichenkette s1 nicht überschritten wird.
strtok [Bearbeiten]
char *strtok( char *s1, const char *s2 )
Die Funktion strtok zerlegt einen String(s1) in einzelne Teilstrings anhand von sogenannten Token. Der String wird dabei durch ein Trennzeichen(s2) getrennt.
"s2" kann mehrere Trennzeichen enthalten, z.B. s2=" ,\n." (d.h. Trennung bei Space, Komma, New-Line, Punkt).
Der Code zu diesem Beispiel würde folgendermaßen aussehen:
-
#include <stdio.h> -
#include <string.h> -
-
int main(void) {
-
char text[] = "Das ist ein Beispiel!"; -
char trennzeichen[] = " "; -
char *wort; -
int i=1; -
wort = strtok(text, trennzeichen); -
-
while(wort != NULL) { -
printf("Token %d: %s\n", i++, wort); -
wort = strtok(NULL, trennzeichen); -
-
//Jeder Aufruf gibt das Token zurück. Das Trennzeichen wird mit '\0' überschrieben. -
//Die Schleife läuft durch bis strtok() den NULL-Zeiger zurückliefert. -
} -
return 0; -
}
Token1: Das Token2: ist Token3: ein Token4: Beispiel!
strcspn [Bearbeiten]
int strcspn (const *s1, const *s2)
strcspn() ist eine Funktion der Standardbibliothek string.h die, je nach Compiler, in jedes C-Programm implementiert werden kann. strcspn() dient dazu, die Stelle eines Zeichens zu ermitteln, an der es zuerst in einem String vorkommt.
Sobald ein Zeichen aus s2 in s1 gefunden wird, wird der Wert der Position an der es gefunden wurde, zurückgegeben.
Achtung: es wird der Index im Char-Array ermittelt.
Beispiel:
-
/*Beispiel zu strcspn()*/ -
-
#include <stdio.h> -
#include <string.h> -
-
int main(void){
-
char s1[] = "Das ist ein Text"; -
char s2[] = "tbc"; // gesucht werden soll das Zeichen t, b oder c -
int position = 0; -
-
position = strcspn(s1,s2); -
printf("Das erste Zeichen von %s tritt an der Stelle %i auf.\n", s2, position+1); -
// Da der Positionszähler der Zeichenkette bei 0 (wie bei Arrays) beginnt, -
// muss zur gefundenen Position 1 zuaddiert werden um eine korrekte -
// Darstellung zu erhalten. -
-
return 0; -
}
Das erste Zeichen von tbc tritt an der Stelle 7 auf.
strpbrk [Bearbeiten]
char *strpbrk( const char *string1, const char *string2);
Gibt einen Zeiger auf das erste Zeichen in string1 zurück, das auch in string2 enthalten ist. Es wird also nicht nach einer Zeichenkette gesucht, sondern nach einem einzelnen Zeichen aus einer Zeichenmenge. War die Suche erfolglos, wird NULL zurückgegeben.
Ein Beispiel:
-
#include <stdio.h> -
#include <string.h> -
-
int main()
-
{ -
char str1[]="Schwein gehabt!";
-
char str2[]="aeiou";
-
printf("%s\n", strpbrk(str1, str2));
-
return 0;
-
}
Ausgabe:
ein gehabt!
strrchr [Bearbeiten]
char *strrchr(const char *s, int ch)
strrchr() ist eine Stringfunktion, die das letzte Auftreten eines Zeichens in einer Zeichenkette sucht. Als Ergebnis wird der Zeiger auf dieses Zeichen geliefert bzw. der NULL-Zeiger, falls dieses Zeichen nicht gefunden wurde.
Im folgenden Beispiel wird eine Zeichenkette mit fgets eingelesen. fgets hängt am Ende ein New-Line-Zeichen an (\n). Wir suchen mit einem Zeiger nach diesem Zeichen und ersetzen es durch ein '\0'-Zeichen.
-
#include <stdio.h> -
#include <string.h> -
-
int main()
-
{ -
char string[20];
-
char *ptr;
-
-
printf("Eingabe machen:\n");
-
fgets(string, 20 , stdin);
-
/* man setzt den zeiger auf das New-Line-Zeichen */ -
ptr = strrchr(string, '\n');
-
/* \n-Zeichen mit \0 überschreiben */ -
*ptr = '\0';
-
printf("%s\n",string);
-
return 0;
-
}
Ein weiteres Beispiel:
-
#include <stdio.h> -
#include <string.h> -
-
int main()
-
{ -
char string[]="Dies ist wichtig. Dies ist nicht wichtig";
-
char *ptr;
-
// suche Trennzeichen "." vom Ende der Zeichenkette aus. -
ptr = strrchr (string, '.');
-
// wenn Trennzeichen im Text nicht vorhanden, -
// dann ist der Pointer NULL. D.h. NULL muss abgefangen werden. -
if (ptr != NULL) {
-
*ptr = '\0'; -
} -
printf ("%s", string);
-
}
Ausgegeben wird:
Dies ist wichtig
Der Pointer ptr zeigt nach strrchr genau auf die Speicherstelle des Strings in der das erste Trennzeichen von hinten steht. Wenn man nun an diese Speicherstelle das Zeichenketteendezeichen \0 schreibt, dann ist der String für alle Stringfunktionen an dieser Stelle beendet. printf gibt den String string nur bis zum Zeichenketteendezeichen aus.
strcmp [Bearbeiten]
int strcmp(char* s1, char* s2);
Diese Stringfunktion ist für den Vergleich von zwei Strings zu verwenden. Die Strings werden Zeichen für Zeichen durchgegangen und ihre ASCII-Codes verglichen. Wenn die beiden Zeichenketten identisch sind, gibt die Funktion den Wert 0 zurück. Sind die Strings unterschiedlich, gibt die Funktion entweder einen Rückgabewert größer oder kleiner als 0 zurück: Ein Rückgabewert >0 (<0) bedeutet, der erste ungleiche Buchstabe in s1 hat einen größeren (kleineren) ASCII-Code als der in s2.
Beispiel:
-
#include <stdio.h> -
#include <string.h> -
-
int main()
-
{ -
const char string1[] = "Hello";
-
const char string2[] = "World";
-
const char string3[] = "Hello";
-
-
if (strcmp(string1,string2) == 0)
-
{ -
printf("Die beiden Zeichenketten %s und %s sind identisch.\n",string1,string2); -
} -
else -
{ -
printf("Die beiden Zeichenketten %s und %s sind unterschiedlich.\n",string1,string2); -
} -
-
if (strcmp(string1,string3) == 0)
-
{ -
printf("Die beiden Zeichenketten %s und %s sind identisch.\n",string1,string3); -
} -
else -
{ -
printf("Die beiden Zeichenketten %s und %s sind unterschiedlich.\n",string1,string3); -
} -
-
return 0;
-
}
Nach dem Ausführen erhält man folgende Ausgabe:
Die beiden Zeichenketten Hello und World sind unterschiedlich. Die beiden Zeichenketten Hello und Hello sind identisch.
strncmp [Bearbeiten]
int strncmp(const char *x, const char *y, size_t n);
Diese Funktion arbeitet ähnlich wie die Funktion strcmp(), mit einem Unterschied, dass n Zeichen miteinander verglichen werden. Es werden die ersten n Zeichen von x und die ersten n Zeichen von y miteinander verglichen. Der Rückgabewert ist dabei derselbe wie schon bei strcmp().
Ein Beispiel:
-
#include <stdio.h> -
#include <string.h> -
-
int main()
-
{ -
const char x[] = "aaaa";
-
const char y[] = "aabb";
-
int i;
-
-
for(i = strlen(x); i > 0; --i)
-
{ -
if(strncmp( x, y, i) != 0) -
printf("Die ersten %d Zeichen der beiden Strings "\ -
"sind nicht gleich\n", i); -
else -
{ -
printf("Die ersten %d Zeichen der beiden Strings "\ -
"sind gleich\n", i); -
break; -
} -
} -
return 0;
-
}
Die ersten 4 Zeichen der beiden Strings sind nicht gleich Die ersten 3 Zeichen der beiden Strings sind nicht gleich Die ersten 2 Zeichen der beiden Strings sind gleich
strspn [Bearbeiten]
Die Funktion strspn() gibt die Position des ersten Vorkommens eines Zeichens an, das nicht vorkommt. Die Syntax lautet:
int strspn(const char *s1, const char *s2);
Folgendes Beispiel gibt Ihnen die Position des Zeichens zurück, welches keine Ziffer ist:
-
#include <stdio.h> -
#include <string.h> -
-
int main()
-
{ -
const char string[] = "7501234-123";
-
int pos = strspn(string, "0123456789");
-
printf("Die Position, an der keine Ziffer steht:");
-
printf(" %d\n",++pos);
-
// pos wird um 1 erhöht, da die Positionierung mit 0 anstatt 1 beginnt -
return 0;
-
}
Die Position, an der keine Ziffer steht: 8
strchr [Bearbeiten]
char* strchr(char * string, int zeichen)
Die Funktion strchr (string char) sucht das erste Vorkommen eines Zeichens in einem String. Sie liefert entweder die Adresse des Zeichens zurück oder NULL, falls das Zeichen nicht im String enthalten ist.
Beispiel:
-
#include <stdio.h> -
#include <string.h> -
-
int main()
-
{ -
char string[] = "Ein Teststring mit Worten";
-
printf("%s\n",strchr(string, (int)'W'));
-
printf("%s\n",strchr(string, (int)'T'));
-
return 0;
-
}
Hier die Ausgabe des Programms:
Worten Teststring mit Worten
Noch ein Beispiel:
-
#include <stdio.h> -
#include <string.h> -
-
int main()
-
{ -
char string[]="Dies ist wichtig. Dies nicht.";
-
char *stelle;
-
-
stelle=strchr(string, (int)'.');
-
*(stelle+1)='\0';/*Durch *(stelle+1) wird nicht der Punkt,
-
sondern das Leerzeichen (das Zeichen danach) -
durch das Determinierungszeichen ersetzt*/ -
printf("%s", string);
-
-
return 0;
-
}
Hier die Ausgabe des Programms:
Dies ist wichtig.
Achtung: Achten Sie auf die richtige Rechtschreibung, da aus strchr leicht strrchr werden kann. Ansonsten wird statt des ersten, das letzte Zeichen im String ausgelesen.
strlen [Bearbeiten]
Zum Ermitteln der Länge eines String, kann man die Funktion strlen() verwenden. Die Syntax lautet wie folgt:
size_t strlen(const char *string1)
Mit dieser Syntax wird die Länge des adressierten Strings string1 ohne das Determinierungszeichen zurückgegeben.
Nun ein Beispiel zu strlen():
-
#include <stdio.h> -
#include <string.h> -
-
int main()
-
{ -
char string1[] = "Das ist ein Test";
-
size_t length;
-
-
length = strlen(string1);
-
printf("Der String \"%s\" hat %d Zeichen\n", string1, length);
-
-
return 0;
-
}
Der String "Das ist ein Test" hat 16 Zeichen
strstr [Bearbeiten]
char *strstr(const char *s1, const char *s2);
Sucht das erste Vorkommen der Zeichenfolge s2 (ausschließlich des abschließenden '\0' - Zeichens) in der Zeichenfolge s1. Als Ergebnis wird ein Zeiger auf die gefundene Zeichenfolge (innerhalb s1) geliefert bzw. der NULL-Zeiger, falls die Suche erfolglos war. Ist die Länge der Zeichenfolge s2 0, so wird der Zeiger auf s1 geliefert.
-
#include <stdio.h> -
#include <string.h> -
-
int main ()
-
{ -
char str[] = "Dies ist ein simpler string";
-
char *ptr;
-
// setzt den Pointer ptr an die Textstelle "simpler" -
ptr = strstr (str, "simpler");
-
// ersetzt den Text an der Stelle des Pointers mit "Beispiel" -
strncpy (ptr, "Beispiel", 8);
-
puts (str);
-
return 0;
-
}
Dies ist ein Beispielstring
Gefahren [Bearbeiten]
Bei der Verarbeitung von Strings muss man sehr vorsichtig sein, um nicht über das Ende eines Speicherbereiches hinauszuschreiben oder zu -lesen. Generell sind Funktionen wie strcpy() und sprintf() zu vermeiden und stattdessen strncpy() und snprintf() zu verwenden, weil dort die Größe des Speicherbereiches angegeben werden kann.
-
#include <string.h> // fuer Zeichenketten-Manipulation -
#include <stdio.h> // fuer printf() -
-
int main(void)
-
{ -
char text[20];
-
-
strcpy(text, "Dies ist kein feiner Programmtest"); //Absturzgefahr, da Zeichenkette zu lang
-
-
strncpy(text, "Dies ist ein feiner Programmtest", sizeof(text));
-
printf("Die Laenge ist %u\n", strlen(text)); //Absturzgefahr, da Zeichenkette 'text' nicht terminiert
-
-
// also vorsichtshalber mit \0 abschliessen. -
text[sizeof(text)-1] = '\0';
-
printf("Die Laenge von '%s' ist %u \n", text, strlen(text));
-
-
return 0;
-
}
Die beiden Zeilen 8 und 11 bringen das Programm möglicherweise zum Absturz:
- Zeile 8: strcpy() versucht mehr Zeichen zu schreiben, als in der Variable vorhanden sind, was möglicherweise zu einem Speicherzugriffsfehler führt.
- Zeile 11: Falls das Programm in Zeile 8 noch nicht abstürzt, geschieht das evtl. jetzt. In Zeile 10 werden genau 20 Zeichen kopiert, was prinzipiell in Ordnung ist. Weil aber der Platz nicht ausreicht, wird die abschließende \0 ausgespart, was bedeutet, dass die Zeichenkette nicht terminiert ist. Die Funktion strlen() benötigt aber genau diese '\0', um die Länge zu bestimmen. Tritt dieses Zeichen nicht auf, kann es zu einem Speicherzugriffsfehler kommen.
Entfernt man die beiden Zeilen 8 und 11 ergibt sich folgende Ausgabe:
Die Laenge von 'Dies ist ein feiner' ist 19
Es ist klar, dass sich hier als Länge 19 ergibt, denn ein Zeichen wird eben für die 0 verbraucht. Man muss also immer daran denken, ein zusätzliches Byte dafür einzurechnen.
Iterieren durch eine Zeichenkette (Ersetzen eines bestimmten Zeichens durch ein anderes in einem String) [Bearbeiten]
-
#include <string.h> // fuer Zeichenketten-Manipulation -
#include <stdio.h> // fuer printf() -
-
/* Diese Funktion ersetzt in einer Zeichenkette ein Zeichen -
* durch ein anderes. Der Rückgabewert ist die Anzahl der -
* Ersetzungen */ -
unsigned replace_character(char* string, char from, char to)
-
{ -
unsigned result = 0;
-
-
if (!string) return 0;
-
-
while (*string != '\0')
-
{ -
if (*string == from) -
{ -
*string = to; -
result++; -
} -
string++; -
} -
return result;
-
} -
-
int main(void)
-
{ -
char text[50] = "Dies ist ein feiner Programmtest";
-
unsigned result;
-
-
result = replace_character(text, 'e', ' ');
-
printf("%u Ersetzungen: %s\n", result, text);
-
-
result = replace_character(text, ' ', '#');
-
printf("%u Ersetzungen: %s\n", result, text);
-
-
return 0;
-
}
Die Ausgabe lautet:
5 Ersetzungen: Di s ist in f in r Programmt st 9 Ersetzungen: Di#s#ist##in#f#in#r#Programmt#st
Zuerst wird die Funktion replace_character deklariert, mit der ein gewisses Zeichen in einem String durch ein anderes ersetzt wird. Grundsätzlich wird die Funktion solange wiederholt, bis sie das Determinierungszeichen \0 findet. Dabei vergleicht sie das erste Zeichen (dessen Adresse bei der Parameterrückgabe mit dem Namen zurückgegeben wird, da der Name auch immer die Adresse des ersten Zeichens ist) mit dem From-Zeichen. Falls beide Zeichen identisch sind, wird die Stelle im String, auf dem der Handle gerade zeigt, durch das to-Zeichen ersetzt. Außerdem wird die Variablen result um eins vergrößert und dann am Schluss zurückgegeben.
Die Bibliothek ctype.h [Bearbeiten]
Wie wir bereits im Kapitel Variablen und Konstanten gesehen haben, sagt der Standard nichts über den verwendeten Zeichensatz aus. Nehmen wir beispielsweise an, wir wollen testen, ob in der Variable c ein Buchstabe gespeichert ist. Dazu verwenden wir die Anweisung
if ('A' <= c && c <= 'Z' || 'a' <= c && c <= 'z')
Wenn in c ein Zeichen, das zwischen den Buchstaben A und Z liegt, bzw. den Buchstaben a und z, dann ...
Unglücklicherweise funktioniert das Beispiel zwar auf dem ASCII-Zeichensatz, nicht aber mit dem EBCDIC-Zeichensatz. Der Grund hierfür ist, dass die Buchstaben beim EBCDIC-Zeichensatz nicht hintereinander stehen.
Wer eine plattformunabhängige Lösung sucht, kann deshalb auf Funktionen der Standardbibliothek zurückgreifen. Ihre Prototypen sind alle in der Headerdatei <ctype.h> definiert. Für den Test auf Buchstabe können wir die Funktion int isalpha(int c) benutzen. Alle Funktionen, die in der Headerdatei ctype.h deklariert sind, liefern einen Wert ungleich 0 zurück wenn die entsprechende Bedingung erfüllt ist, andernfalls liefern sie 0 zurück.
Weitere Funktionen von ctype.h sind:
int isalnum(int c)testet auf alphanumerisches Zeichen (a-z, A-Z, 0-9)int isalpha(int c)testet auf Buchstabe (a-z, A-Z)int iscntrl(int c)testet auf Steuerzeichen (\f, \n, \t ...)int isdigit(int c)testet auf Dezimalziffer (0-9)int isgraph(int c)testet auf druckbare Zeichenint islower(int c)testet auf Kleinbuchstaben (a-z)int isprint(int c)testet auf druckbare Zeichen ohne Leerzeichenint ispunct(int c)testet auf druckbare Interpunktionszeichenint isspace(int c)testet auf Zwischenraumzeichen (Leerzeichen, \f, \n, \t ...)int isupper(int c)testet auf Großbuchstaben (A-Z)int isxdigit(int c)testet auf hexadezimale Ziffern (0-9, a-f, A-F)int isblank(int c)testet auf Leerzeichen
Zusätzlich sind noch zwei Funktionen für die Umwandlung in Groß- bzw. Kleinbuchstaben definiert:
int tolower(int c)wandelt Groß- in Kleinbuchstaben umint toupper(int c)wandelt Klein- in Großbuchstaben um