C kümmert sich nicht um Strings. Nicht wirklich.
Es behandelt sie als Arrays von Zeichen. Nur Bytes im Speicher. Wer sie effektiv nutzen will, braucht Hinweise. Nicht, weil es Spaß macht. Aber weil Sie ohne sie zusätzliche Arbeit leisten.
Ein String in C ist einfach „char str[100]“. Das sieht nach Platz für 100 Zeichen aus. Das ist es nicht. Es bietet Platz für 99 Zeichen plus ein Abschlusszeichen. C verwendet nullterminierte Strings. Jede Zeichenfolge endet mit dem ASCII-Wert 0. Geschrieben als „\0“.
Das verändert alles.
Andere Sprachen behandeln Zeichenfolgen anders. Pascal verwendet ein Längenbyte. Es weiß genau, wie viele Zeichen gespeichert sind. Nach der Länge fragen? Es gibt dieses Byte zurück. Sofort.
C muss zählen. Es liest, bis es „\0“ erreicht. Dies macht C in einigen Fällen langsamer. In anderen schneller. Es hängt davon ab, was Sie tun.
In C gibt es keine integrierte String-Unterstützung. Sie sind auf Bibliotheken angewiesen. „
„c
char s[100];
strcpy(s, “Hallo”);
„
Das ist es. Sie kopieren Element für Element. Oder Sie verwenden „strcpy“. Die Bibliotheksfunktion übernimmt die schwere Arbeit.
„strcpy“ ist überall in C. Es initialisiert Strings. Es kopiert Daten.
„c
int main() {
char s1[100], s2[100];
strcpy(s1, “Hallo”);
strcpy(s2, s1);
0 zurückgeben;
}
„
Nachdem dies ausgeführt wurde, enthält „s1“ „Hallo“ und „s2“ „Hallo“. Das Array speichert ASCII-Werte. Ganze Zahlen. „h“ ist 104. „e“ ist 101. C denkt in Bytes. Sie denken im Text. Der Maschine ist es egal.
Der Vergleich verwendet „strcmp“. Es gibt eine Ganzzahl zurück.
Null bedeutet gleich. Negativ bedeutet, dass die erste Zeichenfolge kleiner ist. Positiv bedeutet, dass es größer ist.
„c
int main() {
char s1[100], s2[100];
bekommt(s1);
bekommt(s2);
if (strcmp(s1, s2) == 0)
printf(“gleich\n”);
sonst wenn (strcmp(s1, s2) < 0)
printf("s1 kleiner als s2\n");
sonst
printf("s1 größer als s2\n");
0 zurückgeben;
}
„
Es gibt weitere Funktionen. „strlen“ gibt die Länge zurück. „strcat“ verkettet. Lesen Sie die Manpage, wenn Sie mehr benötigen.
Doch wie funktionieren diese Funktionen eigentlich unter der Haube? Schauen wir uns „strlen“ an.
Ein naiver Ansatz sieht so aus:
„c
int strlen(char s[]) {
int x;
x = 0;
while (s[x] != ‘\0’)
x = x + 1;
Rückkehr (x);
}
„
Die meisten C-Programmierer hassen das. Es scheint ineffizient zu sein. Sie bevorzugen Hinweise.
„c
int strlen(char s) {
int x = 0;
while ( s != ‘\0’) {
x++;
s++;
}
Rückkehr (x);
}
„
Sie können es weiter komprimieren.
„c
int strlen(char s) {
int x = 0;
während ( s++)
x++;
Rückkehr (x);
}
„
Ein echter Experte könnte es wahrscheinlich kürzer machen.
Ich habe diese auf einem MicroVAX mit gcc kompiliert. Keine Optimierung. Wurde jeweils 20.000 Mal mit einer 120-stelligen Zeichenfolge ausgeführt.
Erste Version: 12,3 Sekunden.
Zweite Version: 12,3 Sekunden.
Dritte Version: 12,9 Sekunden.
Zeiger gewinnen nicht immer.
Schreiben Sie Code, den Sie verstehen. Die Lesbarkeit ist wichtiger als ein paar Mikrosekunden. Es sei denn, Sie befinden sich in einer schwierigen Situation. Dann vielleicht optimieren.
„strcpy“ folgt einer ähnlichen Entwicklung.
Beginnen Sie mit dem Offensichtlichen:
„c
strcpy(char s1[], char s2[]) {
int x;
für (x = 0; x <= strlen(s2); x++)
s1[x] = s2[x];
}
„
Beachten Sie das „<=“. Es kopiert das „\0“. Wenn Sie es überspringen, hat die Zeichenfolge kein Ende. Unbekannte Länge. Bugs später. Schwer zu finden.
Diese Version ist ineffizient. „strlen“ führt jede Iteration aus. Rufen Sie es einmal an.
„c
strcpy(char s1[], char s2[]) {
int x, len;
len = strlen(s2);
für (x = 0; x <= len; x++)
s1[x] = s2[x];
}
„
Nun Hinweise.
„c
strcpy(char s1, char s2) {
while (s2 != ‘\0’) {
s1 = *s2;
s1++;
s2++;
}
}
„
Komprimieren Sie es.
„c
strcpy(char s1, char s2) {
während (s2)
s1++ = *s2++;
}
„
Sauber. Schnell. Gefährlich, wenn Sie die Grenzen nicht überprüfen.
So funktionieren C-Saiten. Keine Magie. Nur Erinnerung und Hinweise. Und viel sorgfältiges Zählen.
Zeiger vs. Leistung in strcpy
Sie könnten technisch gesehen while (s1++ = s2++); schreiben, um das Kopieren von Zeichenfolgen zu handhaben. Der Leistungsunterschied zwischen naiven und optimierten Implementierungen ist atemberaubend.
Nehmen Sie strcpy. Die erste Version benötigt 415 Sekunden, um eine 120-stellige Zeichenfolge 10.000 Mal zu kopieren. Die zweite Version? 14,5 Sekunden. Die dritte sinkt auf 9,8 Sekunden. Der vierte Wert pendelt sich bei 10,3 Sekunden ein.
Das ist kein marginaler Unterschied. Es ist ein gewaltiger Schub. Zeiger sorgen hier für Geschwindigkeit, weil sie unnötigen Overhead vermeiden.
Rückgabetypen und String-Zeiger
Der Prototyp für strcpy in der String-Bibliothek verrät seine Absicht:
„c
char strcpy(char s1, char *s2)
„
Die meisten String-Funktionen geben einen Zeiger auf einen String zurück. strcpy gibt als Ergebnis den Wert von s1 zurück. Dies ermöglicht die Verkettung von Vorgängen oder die sofortige Verwendung der kopierten Zeichenfolge ohne eine zweite Suche.
Führende Leerzeichen entfernen, ohne Daten zu verschieben
Die Verwendung von Zeigern mit Zeichenfolgen führt häufig zu deutlichen Geschwindigkeitsverbesserungen. Sie können davon profitieren, wenn Sie ein wenig darüber nachdenken.
Angenommen, Sie möchten führende Leerzeichen aus einer Zeichenfolge entfernen. Der Instinkt besteht darin, Zeichen zu verschieben und die Leerstellen zu überschreiben. In C können Sie die Bewegung ganz vermeiden.
„c
int main() {
char s[100], p;
bekommt(s);
p = s;
while ( p == ‘ ‘) p++;
printf(“%s\n”, p);
0 zurückgeben;
}
„
Dies ist viel schneller als die Bewegungstechnik. Besonders für lange Saiten. Sie verschieben keine Bytes. Sie ändern lediglich den Startzeiger. Die Daten bleiben erhalten. Die Ausgabe ändert sich.
Tricks lernen
Im Laufe der Zeit werden Sie viele weitere Tricks mit Schnüren erlernen. Sie werden anderen Code lesen. Sie werden sehen, wie andere mit dem Gedächtnis umgehen.
Übung ist der Schlüssel. Es gibt keine Abkürzung zum Lesen von Code. Man muss sich nur ansehen, wie es gemacht wird und verstehen, warum es funktioniert. Die Leistungssteigerungen sind real. Die Lernkurve ist steil. Aber die Ergebnisse sprechen für sich.



























