C-Strings

  • Was ist ein C-String?
  • Wie definiert man einen C-String?
  • Länge des Strings
  • Einzelne Zeichen suchen und austauschen
  • Definition von langen Strings

Was ist ein C-String?

In der vorherigen Lektion haben wir uns über Arrays unterhalten und eins der wichtigsten Arrays ist das Array aus Buchstaben, denn ein Text ist nichts anderes als viele hintereinandergereihte Objekte vom Typ 'Buchstabe'. Entsprechend der ASCII-Tabelle ist jedem Zeichen (also Buchstaben, Satzzeichen oder Ziffer) ein Integerwert zugeordnet. Ein ASCII-Text ist also eine Ansammlung von Zahlenwerten zwischen Null und 127 (bzw. 255, wenn auch weitergehende Zeichen, wie z.B. Umlaute erlaubt sind). Der kleinste Datentyp, der 256 unterschiedliche Werte unterscheiden kann ist char. char ist die Kurzform für Character, zu deutsch: Buchstabe. Derart kleine Zahlen werden nämlich vorrangig zur Kodierung von Buchstaben verwendet - es spricht allerdings nichts dagegen, auch irgendwelche anderen Zahlenwerte in chars zu speichern. Ein Array von drei Chars eignet sich beispielsweise hervorragend, um eine Farbe mit ihren Rot/Grün/Blau-Werten zu speichern.

C-Strings sind also char-Arrays und genau so werden sie auf allen üblichen Betriebssystemen verwendet, um Texte zu speichern. Damit Du eine Vorstellung hast, dass dieser Kurs sich wirklich an der Realität entlang bewegt: Auch dieser Text, den Du gerade liest, liegt als Char-Array vor. Du lernst also jetzt zu verstehen, wie dieser Text im Computer verarbeitet wird, damit Du ihn lesen kannst.

Zwei Dinge müssen bei Char-Arrays bzw. C-Strings auseinander gehalten werden: die Länge des Textes und die Länge des Arrays. Das Ende des Textes muss mit besonderen Zeichen markiert werden, das ansonsten im Text nicht vorkommen darf. Es handelt sich um das Zeichen mit der Nummer 0, das sogenannte Nullbyte. Ein C-String, also ein Text ist so lang, bis ein Nullbyte gefunden wird, jeglicher Text dahinter wird ignoriert. Das char-Array ist im optimalen Fall also so lang wie der Text plus ein zusätzliches Char, das das Nullbyte aufnimmt. Das Nullbyte wird von Anfängern sehr gerne vergessen. Der Text kann also kürzer sein als das char-Array, aber er kann nicht so lang sein, wie das Char-Array (weil sonst der Platz für das Nullbyte fehlen würde) und der Text kann natürlich auch nicht länger sein als das Array.

Wie definiert man einen C-String?

Grundsätzlich wird ein C-String genauso wie jedes andere Array erstellt:

#include <stdio.h>
 
int main( void )
{
  char text[12] = { 112, 114, 111, 103, 103, 101, 110, 46, 111, 114, 103, 0 };
  int i;
 
  for( i = 0; text[i]; i = i + 1 )
    printf( "%c", text[i] );
 
  printf( "\n" );
 
  return 0;
}

Wenn man das Programm ausführt, bekommt man folgende Ausgabe:

proggen.org

Warum funktioniert das Programm?
Wir haben gelernt, dass die for-Schleife eine Expression auswertet und ihren Wahrheitswert überprüft. Die Expression ist hier text[i] und diese Expression ist solange wahr, solange sie nicht 0 ist. Da unser String mit einem Nullbyte am Ende markiert ist, wird die Expression text[i] am Ende des Strings falsch und die Schleife bricht ab. Man könnte auch text[i] != 0 schreiben, aber C-Programmierer sind da eher schreibfaul.

Strings mit printf ausgeben

Statt jeden Buchstaben einzeln auszugeben, kann man mit printf() auch gleich ganze C-Strings am Stück ausgeben lassen. Hierfür lässt sich im Formatstring das Zeichen %s verwenden, das printf() dazu veranlasst so lange Zeichen auszugeben, bis das Nullbyte gefunden wurde.

#include <stdio.h>
 
int main( void )
{
  char text[12] = { 112, 114, 111, 103, 103, 101, 110, 46, 111, 114, 103, 0 };
 
  printf( "%s\n", text );
 
  return 0;
}

ASCII-Zeichen

Die Zahlen im Array kannst Du in der ASCII-Tabelle nachschlagen. Aber seien wir ehrlich - wer will das schon? Den ASCII-Wert eines Zeichens erhält man in C ganz einfach, in dem man das Zeichen in einfache Hochkommas setzt. Und weil wir auch keine Lust haben, bei jedem Text die Buchstaben zu zählen, überlassen wir das Zählen auch dem Compiler in dem wir keine Größe des Arrays erzwingen, wie wir es in der vorherigen Lektion schon gelernt haben:

  char text[] = { 'p', 'r', 'o', 'g', 'g', 'e', 'n', '.', 'o', 'r', 'g', '\0' };

Auch das Nullbyte habe ich hier als Nullzeichen in Hochkommas gesetzt. Für den Compiler spielt es keine Rolle, ob Du 0 oder '\0' schreibst, in beiden Fällen wird ein char mit 0 beschrieben. Warum mache ich mir dann die Mühe, statt einer Ziffer umständlich '\0' zu schreiben? Es ändert das ausführbare Programm nicht, aber es ändert den Quelltext: Man kann so ganz klar sehen, dass es sich um ein Nullbyte handelt, das einen C-String beendet. Nicht verwechseln darfst Du es mit '0', denn das ist dann ja das Null-Zeichen und das Null-Zeichen hat den Wert 48. Sobald Du ein wenig Erfahrung mit C hast, wird Dir der Backslash, also das \-Zeichen vor der Null aber förmlich ins Auge springen.

Das ist nun schon deutlich übersichtlicher, allerdings geht einem so vermutlich bald die Taste für Hochkommas kaputt und das ging auch den Entwicklern der Sprache vermutlich schnell auf die Nerven. Deswegen geht die Sache noch einfacher:

  char text[] = "proggen.org";

„proggen.org“ ist ein C-String, das bedeutet, dass am Ende ein Nullbyte ist, dass bei der Initialisierung von text berücksichtigt wird. „proggen.org“ ist identisch mit { 'p', 'r', 'o', 'g', 'g', 'e', 'n', '.', 'o', 'r', 'g', '\0' } - nur einfacher zu schreiben.

Länge des Strings

Wir wissen ja bereits, wie wir Arrays lesen und beschreiben können. Versuchen wir die Länge des Strings herauszufinden. Dafür müssen wir das erste Auftauchen des Nullbytes suchen. Wir gehen also das Array Zeichen für Zeichen durch und schauen nach, an welcher Stelle wir das Nullbyte finden:

#include <stdio.h>
 
int main( void )
{
  char text[] = "proggen.org";
 
  printf( "%s\n", text );
 
  int length = 0;
  while( text[length] )
    length = length + 1;
 
  printf( "Der Text ist %d Zeichen lang.\n", length );
 
  return 0;
}

Wir erhalten die Ausgabe

proggen.org
Der Text ist 11 Zeichen lang.

Fällt es euch auf? Viele Dinge in der Computertechnik sind gut durchdacht, denn das Nullbyte am Ende des Strings ist das einzige Zeichen im String, das nicht true ist. Daher lässt sich die Bedingung der Schleife auch als Existenzabfrage formulieren: Am Ende des Strings existiert kein Zeichen mehr, daher ist der String zu Ende. Das möchte ich zum einen hervorheben, damit es euch auffällt, dass man so die Länge eines Strings bestimmen kann und zum anderen möchte ich darauf aufmerksam machen, dass wir hier an eine Stelle kommen, wo Wissen aus den ersten Lektionen der Grundlagen wieder auftaucht. Wir fangen also bereits an, Wissen aus diesem Tutorial wiederholt anzuwenden.

Einzelne Zeichen suchen und austauschen

Das Ganze lässt sich natürlich ganz schnell so abändern, dass man ein beliebiges Zeichen suchen kann. Stellen wir uns folgende Aufgabe: wir wollen nur den String vor dem Punkt ausgeben. Dafür müssen wir zunächst herausfinden, wo der Punkt ist und den C-String dort enden lassen.

#include <stdio.h>
 
int main( void )
{
  char text[] = "proggen.org";
 
  printf( "%s\n", text );
 
  int dot = 0;
  while( text[dot] != '.' )
    dot = dot + 1;
 
  text[dot] = '\0';
 
  printf( "Der Punkt wurde an Position %d gefunden.\n", dot );
  printf( "%s\n", text );
 
  text[dot] = '-';
 
  printf( "Der Punkt durch ein '-' ausgetauscht.\n" );
  printf( "%s\n", text );
 
  return 0;
}

Wir erhalten folgende Ausgabe:

proggen.org
Der Punkt wurde an Position 7 gefunden.
proggen
Der Punkt durch ein '-' ausgetauscht.
proggen-org

Nochmal zur Erinnerung: Der Positionsindex beginnt bei 0, das 0. Zeichen ist also das 'p'. Nachdem wir das Zeichen an der Position des Punktes gegen ein Nullbyte ausgetauscht haben, endet der String an dieser Stelle. Nachdem wir ein anderes Zeichen wieder eingefügt haben, ist das Nullbyte allerdings wieder überschrieben - der String endet also nicht mehr an der Stelle des ehemaligen Punktes und printf() gibt solange Text aus, bis das nächste Nullbyte gefunden wird.

Definition von langen Strings

Die meisten Strings sind vergleichsweise kurz, so dass sie einfach in eine Zeile passen:

char string[] = "Dies ist ein Text.";

Manchmal benötigt man auch längere Texte, die beispielsweise auch über mehrere Zeilen gehen. Mit dem Newline ('\n')-Zeichen wechselt man in die nächste Zeile:

char string[] = "Tolles Programm\n(c) by Programmierer\n\n";

Das lässt sich auch schöner schreiben, doch C verlangt, dass ein String am Ende der Zeile abgeschlossen wird. Allerdings werden Strings zusammengefügt, wenn sie aufeinander treffen. Der String „Dies ist ein Text.“ lässt sich in C auch so zusammenstellen:

char string[] = "Dies" " " "ist" " " "ein" " " "Text.";

Dies lässt sich für längere Texte nutzen, so dass sie weiterhin auch im Quelltext gut lesbar sind:

char string[] = "Tolles Programm\n"
                "(c) by Programmierer\n\n";

Ziel dieser Lektion

Wir haben uns das Character-Array genauer angesehen und gesehen, dass C-Strings kürzer sind als das Array in dem sie stehen und durch ein Nullbyte abgeschlossen werden. Wir haben die unterschiedliche Schreibweisen für das ASCII-Zeichen '0', das Nullbytes ('\0') und den Zahlenwert Null (0) kennengelernt.

Wir können Char-Arrays initialisieren und auf ihre Länge untersuchen oder besondere Zeichen suchen und haben uns angesehen, wie lange bzw. mehrzeilige Strings im Quelltext gut lesbar dargestellt werden können.

Im kommenden Kapitel werden uns um Zeiger kümmern.