16.6 Zeichenweise lesen und schreiben – »getchar()« und »putchar()« 

Um zeichenweise aus dem Stream stdin (Standardeingabe) zu lesen und zeichenweise auf stdout (Standardausgabe) zu schreiben, können Sie folgende Funktionen verwenden:
#include <stdio.h> // Lesen (zeichenweise) von stdin int getchar(); // Schreiben (zeichenweise) auf stdout int putchar(int c);
getchar() dient zum Einlesen einzelner Zeichen von der Standardeingabe; normalerweise ist dies die Tastatur. Ein wenig verwirrend dürfte der Rückgabewert der Funktion getchar() sein, da dieser vom Datentyp int ist. Das liegt daran, dass ein char vor der Verwendung eines Ausdrucks in ein int konvertiert wird.
Etwas genauer: Das Problem der Verwendung von int liegt in der Konstante EOF (End of File), die das Ende einer Eingabe anzeigt. EOF ist eine define-Konstante, die in der Headerdatei <stdio.h> mit dem Wert –1 deklariert ist, damit sie nicht mit den normalen ASCII-Zeichen kollidiert. Früher, als noch 127 Zeichen verwendet wurden, war das kein Problem. Heute sind die Werte der Zeichen größer als 127, um zum Beispiel Umlaute wie ä, ö, ü und ß ausgeben zu können. Ist char dabei mit unsigned deklariert, könnten Zeichen zwischen 0 ... 255 Platz darin finden. Es ist dann aber kein Platz mehr für EOF (-1). Daher wurde einfach der Rückgabewert von getchar() als int deklariert, und damit können sowohl die 255 Zeichen als auch das EOF übermittelt werden – das Problem war gelöst.
Hierzu ein Listing:
/* echo_char.c */ #include <stdio.h> #include <stdlib.h> int main(void) { int c; while( (c = getchar()) !='.') putchar(c); return EXIT_SUCCESS; }
Wenn hierbei mehrere Zeichen eingegeben werden und gedrückt wird, wird der Text Zeichen für Zeichen auf dem Bildschirm ausgegeben. Dies geschieht so lange, bis ein einzelnes Zeichen dem eines Punktes entspricht. Dann ist die while-Bedingung unwahr. Sie können als Abbruchbedingung auch EOF angeben:
while((c = getchar()) != EOF);
Hiermit werden so lange Zeichen eingelesen, bis die Tastenkombination +
(unter MS-Systemen) oder
+
(unter Linux) gedrückt wird, die EOF nachbildet.
Hinweis für Programmierneulinge |
Auch wenn es bei der Funktion getchar() den Anschein hat, dass hier mit ganzen Strings gearbeitet wird, ist dem nicht so. Diese Funktion liest Zeichen für Zeichen aus einem Puffer. Dies geschieht aber erst, wenn die Taste |
Neben den byte-orientierten Funktionen getchar() und putchar() gibt es natürlich auch dieselben Funktionen für breite Zeichen. Hier sehen Sie die Syntax dazu:
#include <wchar.h> // breite Zeichen von stdin (zeichenweise) einlesen wint_t getwchar(); // breite Zeichen auf stdout (zeichenweise) ausgeben wint_t putwchar(wint_t wc);
Der primitive Datentyp wint_t ist ein ganzzahliger Typ, der mindestens den Wertebereich des Typs wchar_t speichern kann. Zusätzlich kann wint_t auch den Wert WEOF speichern. WEOF ist ein Makro (ebenfalls vom Typ win_t) und ist ein Wert, der nicht mit einem erweiterten breiten Zeichensatz übereinstimmt. WEOF ist also das breite Gegenstück zu EOF, mit dem Unterschied, dass der Wert von WEOF nicht negativ sein muss.
Hinweis |
Tritt bei der Konvertierung eines Multibyte-Zeichens in ein Breitzeichen ein Fehler auf, wird die Fehlervariable errno (siehe Abschnitt 16.22, »Fehlerbehandlung«) auf den Wert EILSEQ gesetzt. |
Hier sehen Sie das breite Gegenbeispiel zum Listing echo_char.c mit wide-orientierten Streams:
/* echo_wchar.c */ #include <stdlib.h> #include <wchar.h> int main(void) { wint_t c; while( (c = getwchar()) != L'.') putwchar(c); return EXIT_SUCCESS; }
Zur Funktion getchar() noch ein Listing:
/* count_char.c */ #include <stdio.h> #include <stdlib.h> int main (void) { int c,counter=0; printf("Bitte Eingabe machen:"); /* Eingabe machen, bis mit Return beendet wird */ while((c=getchar()) != '\n') { /* Leerzeichen und Tabulatorzeichen nicht mitzählen */ if( (c != ' ') && (c != '\t') ) counter++; /* counter erhöhen */ } /* Gibt die Anzahl eingegeb. Zeichen von 0 bis counter-1 aus. * Mit counter-1 wird das Zeichen '\0' nicht mitgezählt. */ printf("Anzahl der Zeichen beträgt %d Zeichen\n", counter-1); return EXIT_SUCCESS; }
Mit diesem Listing werden alle darstellbaren Zeichen gezählt, die Sie über die Tastatur eingeben. Leerzeichen und Tabulatoren werden jedoch nicht mitgezählt.
16.6.1 Ein etwas portableres »getch()« 

Die folgende Frage wurde mir bereits unzählige Male gestellt: Wie kann ich den Programmablauf anhalten, bis eine bestimmte Taste gedrückt wird? Dafür gibt es leider keinen standardisierten Weg. Aber um Sie jetzt nicht im Regen stehen zu lassen, folgt hierfür ein etwas portableres getch(), das sowohl unter Linux/UNIX als auch unter MS-Windows funktioniert. Ihnen diese Funktion speziell unter Linux/UNIX näher zu erklären, würde ein wenig zu weit führen. Bei MS-Windows gibt es dabei nicht viel zu sagen, nur dass die Headerdatei <conio.h> mit eingebunden werden muss, da sich darin diese Funktion befindet. Hier der Quellcode:
/* portable_getch.c */ #include <stdio.h> #include <stdlib.h> /* ... übersetzt unter Linux/UNIX? */ #ifdef __unix__ #include <termios.h> #include <unistd.h> static struct termios new_io; static struct termios old_io; /* Funktion schaltet das Terminal in den cbreak-Modus: */ /* Kontrollflag ECHO und ICANON auf 0 setzen */ /* Steuerzeichen: Leseoperation liefert 1 Byte VMIN=1 VTIME=1 */ int cbreak(int fd) { /*Sichern unseres Terminals*/ if((tcgetattr(fd, &old_io)) == -1) return -1; new_io = old_io; /* Wir verändern jetzt die Flags für den cbreak-Modus. */ new_io.c_lflag = new_io.c_lflag & ~(ECHO|ICANON); new_io.c_cc[VMIN] = 1; new_io.c_cc[VTIME]= 0; /*Jetzt setzen wir den cbreak-Modus*/ if((tcsetattr(fd, TCSAFLUSH, &new_io)) == -1) return -1; return 1; } int getch(void) { int c; if(cbreak(STDIN_FILENO) == -1) { printf("Fehler bei der Funktion cbreak ... \n"); exit(EXIT_FAILURE); } c = getchar(); /* alten Terminal-Modus wiederherstellen */ tcsetattr(STDIN_FILENO, TCSANOW, &old_io); return c; } /* ... oder wird das Programm unter MS-Windows übersetzt? */ #elif __WIN32__ || _MSC_VER || __MS_DOS__ #include <conio.h> #endif int main(void) { int zeichen; printf("Bitte 'q' drücken, um das Programm zu beenden!\n"); /* Wartet auf das Zeichen q. */ while(( zeichen=getch() ) != 'q'); return EXIT_SUCCESS; }
Ihre Meinung
Wie hat Ihnen das Openbook gefallen? Wir freuen uns immer über Ihre Rückmeldung. Schreiben Sie uns gerne Ihr Feedback als E-Mail an kommunikation@rheinwerk-verlag.de.