25. Strings I

Strings (Zeichenketten) sind in C Arrays von chars, wobei das Ende des Strings durch eine Null (nicht ’0’ sondern 0) gekennzeichnet ist.

Das ist ein ungleich primitiverer String, als wir ihn aus Python kennen. Das Problem, dass Strings keine 0 enthalten dürfen, ist noch zu verschmerzen, schlimmer ist schon, dass C-Strings alle Beschränkungen von Arrays haben, also etwa eine zur Compilezeit festgelegte Maximallänge. JedeR C-ProgrammiererIn wird früher oder später über das Ende eines Strings rausschreiben und damit wirre Abstürze und Sicherheitslücken provozieren. Vorsicht gleich mal: Da die abschließende Null natürlich im Array steht, kann ein mit char str[80] deklarierter String maximal 79 Zeichen enthalten, und der Index des letzten möglichen Nutz-Zeichens ist 78.

Es gibt Bibliotheken, also Funktionssammlungen, die “bessere” Strings implementieren – nicht zuletzt die Bibliothek des Python-Interpreters. Insbesondere muss man sich bei diesen Strings keine Sorgen mehr darum machen, ob das Array groß genug ist für das, was man gerade vorhat. Wir bleiben hier zunächst bei dem, was uns die Standardbibliothek gibt.

#include <stdio.h>

void stringdemo(char str[])
{
  int i=0;

  printf("%s\n", str);
  while (str[i]) printf("%03d ", str[i++]);
  printf("\n");
}

int main(void)
{
  char str1[80]="Ein String";

  stringdemo(str1);
  stringdemo("01\n@gemein");
  return 0;
}

gibt (heute) aus:

Ein String
069 105 110 032 083 116 114 105 110 103
01
@gemein
048 049 010 064 103 101 109 101 105 110

Standard-Stringfunktionen

Die C-Bibliothek bietet einige Funktionen, um den Umgang mit Zeichenketten zu erleichtern. Deklariert werden sie in string.h. Übersicht über Stringfunktionen mit man 3 string, eine Auswahl:

  • strlen berechnet die Länge eines Strings ohne das Nullbyte (nicht den Platz im Array!).
  • strcmp vergleicht zwei Strings und gibt 0 zurück, wenn sie gleich sind.
  • strncpy kopiert eine Anzahl von Zeichen von einem String in einen anderen (strcpy kopiert den ganzen String und kann deshalb zu hässlichen buffer overflows führen).
  • strncat hängt eine Anzahl von Zeichen aus einem String in einen anderen an.
  • strchr findet ein Zeichen in einem string (braucht Pointer – später)
  • strstr findet einen string in einem anderen (ditto)

Ein Beispiel für die Verwendung dieser Funktionen:

#include <stdio.h>  /* Wie immer */
#include <string.h> /* Wir wollen Stringfunktionen verwenden */

#define MAX_LEN 80

int mangleStrings(char str1[], char str2[])
{
  char tmp[MAX_LEN*2];
  int res = strcmp(str1, str2);

  printf("len(str1)=%zu, len(str2)=%zu\n", strlen(str1), strlen(str2));
  if (res<0) { /* str1<str2 */
    strncpy(tmp, str1, 2*MAX_LEN); /* erstmal str1 nach tmp schreiben */
    strncat(tmp, str2, 2*MAX_LEN-strlen(tmp));
      /* dann str2 anhängen und dabei aufpassen, dass wir nicht
         überlaufen */
  } else if (res==0) { /* str1==str2 */
    printf("Die Strings sind ja gleich.  Wie langweilig.\n");
    return -1;
  } else { /* str1>str2 */
    /* The same procedure as above, nur kommt jetzt str2 zuerst rein */
    strncpy(tmp, str2, 2*MAX_LEN);
    strncat(tmp, str1, 2*MAX_LEN-strlen(tmp));
  }
  printf("Zusammen: '%s', %zu Zeichen lang\n", tmp, strlen(tmp));
    /* n.b.: strlen zählt die Null am Schluss nicht mit */
  if (strstr(tmp, "Rotz")) {
    /* das können wir auch ohne pointer: Wenn strstr "wahr" zurückgibt,
       ist das "Rotz" in tmp */
    printf("Pfui.  Gleich wäscht du dir den Mund aus.\n");
  }
  return 0;
}

int main(void)
{
  mangleStrings("Welt", "Hallo ");
  mangleStrings("rot", "rot");
  mangleStrings("rot ", "rot");
  mangleStrings("Sehr Rot", "zigtausend mal");
  return 0;
}

Das Programm gibt aus:

len(str1)=6, len(str2)=4
Zusammen: 'Hallo Welt', 10 Zeichen lang
len(str1)=3, len(str2)=3
Die Strings sind ja gleich.  Wie langweilig.
len(str1)=4, len(str2)=3
Zusammen: 'rotrot ', 7 Zeichen lang
len(str1)=8, len(str2)=14
Zusammen: 'Sehr Rotzigtausend mal', 22 Zeichen lang
Pfui.  Gleich wäscht du dir den Mund aus.

Merke: strcmp und Freunde wissen nichts vom Telefonbuch. Sie sortieren nach ASCII-Wert (was vor allem mit Umlauten richtig mistig ist).

Zum %zu-Formatcode, mit dem wir die Ergebnisse von strlen ausgeben, siehe unten bei size_t.


Markus Demleitner

Copyright Notice