5.1. Eingabe und Ausgabe einzelner Zeichen

Die einfachsten Funktionen, um ein einzelnes Zeichen einzulesen oder auszugeben, sind getchar() (steht für "get character") und putchar() ("put character"). Zwar ist es möglich, diese Aufgabe mit den weiter unten besprochenen Funktionen scanf() und printf() zu erledigen, diese sind aber wegen ihres Funktionsumfangs wesentlich aufwendiger und führen zu einem unnötigen "Overhead"; getchar() und putchar() sind also vorzuziehen. Erstere Funktion wartet, bis eine Taste betätigt wird, und gibt das entsprechende Zeichen zurück. Der Rückgabewert der Funktion getchar() ist allerdings nicht, wie man erwarten könnte, char, sondern integer. Das eingelesene Zeichen befindet sich im unteren Byte dieses integer-Werts. Die Funktion getchar() stellt das eingegebene Zeichen auf dem Bildschirm dar: In der Fachsprache wird dieses Phänomen als "Bildschirm-Echo" bezeichnet.

Die Funktion putchar() gibt ein Zeichen an der Cursorposition aus. Auch hier entspricht der Datentyp des Arguments nicht ganz den Erwartungen: putchar() erwartet nämlich einen integer-Wert, wovon es allerdings nur das geringerwertige Byte ausgibt. Wenn putchar() ohne Fehler ausgeführt wird, dann gibt es das geschriebene Zeichen zurück; andernfalls liefert es den Wert EOF. EOF steht für "End of File" und wird als Konstante in der Datei stdio.h definiert.

Das folgende Progrämmchen wartet auf einen Tastendruck und gibt das eingegebene Zeichen wieder auf dem Bildschirm aus.


/*******************************************************
 *                                                     *
 * Beispiel für die Verwendung von putchar()           *
 * und getchar()                                       *
 *                                                     *
 *******************************************************/

#include <stdio.h>


/* notwendig, wenn I/O - Funktionen verwendet werden */

int main(void){

	char cKeyPressed; 
	/* Variable, die eingelesenes Zeichen aufnimmt */

	 printf("Geben Sie ein Zeichen ein!\n");
	 cKeyPressed = getchar();
	/*---------> automatische Typumwandlung!! <---------*/
	 printf("Sie habe folgendes Zeichen eingegeben:\n");
	 putchar(cKeyPressed);

return 0;
}

Beachtenswert ist die automatische Typumwandlung, die bei der Zuweisung des eingelesenen Zeichens zur Variable cKeyPressed erfolgt; getchar() liefert, wie erwähnt, einen integer-Wert zurück; die Variable cKeyPressed ist allerdings nur vom Typ char und umfaßt nur ein Byte, während der Typ int je nach System 2 oder 4 Byte groß ist. Das eingelesene Zeichen befindet sich aber im unteren Byte des Rückgabewerts. Bei der Konvertierung gehen nur die höherwertigen Byte verloren, was in diesem Fall nicht weiter schlimm ist, da die benötigte Information im untersten Byte erhalten bleibt.

Bei der Ausführung des Beispielprogramms fällt außerdem auf, daß die Funktion getchar() neben dem Bildschirmecho über eine weitere Eigenheit verfügt: Die Eingabe erfolgt gepuffert, d.h., sie muß durch Drücken von (␍) abgeschlossen werden. Wenn die Eingabe ohnehin nur ein Zeichen erwartet, dann erscheint es oft wünschenswert, daß eine weitere Bestätigung durch (␍) entfällt. Zu allem Überfluß beläßt getchar() auf diese Art ein Zeichen - nämlich den Zeilenvorschub - im Tastaturpuffer, da die Funktion ja nur ein Zeichen, und zwar das erste, einliest. Ein weiteres, darauffolgendes getchar würde daher den verbliebenen Zeilenvorschub aus dem Tastaturpuffer lesen, anstatt die Benutzereingabe entgegenzunehmen - mit der Folge, daß sich das zweite getchar() so verhält, als wäre bloß die (␍)-Taste gedrückt worden. Abhilfe verschafft hier der Aufruf eines "leeren" getchar(), das ausschließlich dazu dient, den (␍) wieder aus dem Tastaturpuffer zu entfernen.


.
.
	printf("Geben Sie ein Zeichen ein!\n");
	cKeyPressed = (char) getchar();
	/*---------> explizite Typumwandlung zu char!! <---------*/
	getchar(); /* ein dummy-Aufruf, um den Zeilenvorschub
	              aus dem Tastaturpuffer auszulesen */
	 printf("Sie habe folgendes Zeichen eingegeben:\n");
.
.

Alternativen zu getchar()

Obwohl die ANSI-Spezifikation zuläßt, daß die Funktion getchar() auch ohne abschließendes (␍) funktioniert, ist sie trotzdem fast überall in der oben besprochenen Weise realisiert. Das ANSI-Komitee definierte allerdings keine weitere Funktion, die dem Bedürfnis nach einer komfortablen, zeichenweisen Eingabe in interaktiven Umgebungen entgegenkommt. Die meisten Compiler verfügen aber zusätzlich über zumindest zwei weitere Funktionen, die nicht den Nachteil von getchar aufweisen: getch() und getche() ; getch liest ein Zeichen ungepuffert von der Tastatur ohne Bildschirmecho ein; getche() hingegen (das abschließende "e" steht für "Echo") gibt das eingegebene Zeichen auf dem Bildschirm wieder.

Hat der Hersteller Ihres Compilers getchar() in der üblichen Weise implementiert, dann sollten Sie überprüfen, ob getch() bzw. getche() als bessere Alternativen zur Verfügung stehen. Es ist dabei jedoch zu beachten, daß die Prototypen dieser Funktionen im allgemeinen nicht in stdio.h definiert werden. Sie müssen dann der Dokumentation des Compilers entnehmen, welche Header-Datei mit einer #include-Anweisung eingefügt werden muß (meist ist es conio.h).

Die Funktion getch() eignet sich bei den meisten PC-Compilern dafür, den erweiterten Scancode von Funktionstasten oder Cursortasten abzufragen. Dazu muß getch() zweimal hintereinander aufgerufen werden; beim Drücken einer Funktionstaste liefert der erste Aufruf null, der zweite gibt den Scancode der gedrückten Taste zurück. Das Drücken von (F1) würde im folgenden Beispiel der Variablen cChar den Wert null zuweisen, iExtended enthielte dann den Wert 59.


/**************************************************
 *                  extended.c                    *
 * erweiterten Scancode von Sondertasten abfragen *
 **************************************************/
#include <stdio.h>
 /* wg. printf() */
#include <conio.h>
/* wg. getch() */

int main(void){

int iExtended;
char cChar;

	printf("Bitte eine Funktionstaste "
		"(F1-F10) drücken...\n");
	cChar = getch();
	/* cChar erhält beim Drücken einer
	 * Funktionstaste den Wert 0
	 * erst zweiter Aufruf ergibt Scancode
	 */
	iExtended = getch();

	printf("Funktionstaste F%d wurde gedrückt!\n",
		iExtended - 58);
	/* Funktionstaste F1 hat den Scancode 59. Um die
	 * Nummer der Funktionstaste zu ermitteln, muß nur
	 * noch 58 vom Scancode abgezogen werden.
	 */

return 0;
}

Es sei noch einmal darauf hingewiesen, daß dieses Verfahren nicht auf ANSI C beruht und daher nicht auf allen Plattformen mit allen Compilern funktioniert. So definieren C-Compiler auf PC-UNIX-Systemen wie Linux im allgemeinen keine conio.h, getch() kann zumeist nach Einbinden von curses.h genutzt werden. Die ungepufferte Eingabe ist im CBREAK-Modus möglich, der sich mittels cbreak() und nocbreak() ein- bzw. ausschalten läßt.