5. Einfache Ein- und Ausgabe in C
  Ein Programm empfängt einen Strom (englisch: stream) von eingegebenen Daten,
  verarbeitet diese und gibt dann das Ergebnis als Strom von Daten wieder aus. Unter einem
  Datenstrom versteht man eine Folge von Zeichen. Für einen Datenstrom gibt es verschiedene
  Standardkanäle, die bereits definiert sind.
  
| Standardkanal | Datenstrom | 
| Standardeingabe (Tastatur) | stdin | 
| Standardausgabe (Bildschirm) | stdout | 
| Standardfehlerausgabe (Bildschirm) | stderr | 
| Standarddrucker (parallele Schnittstelle) | stdprn | 
| Standardzusatzgerät (serielle Schnittstelle) | stdaux | 
Diese Standardkanäle können mit Hilfe einiger Funktionen angesprochen werden. Um diese Funktionen sowie deren Verwendung für Standardein- und ausgaben soll es in diesem Kapitel gehen.
Die Standardeingabe geschieht in der Regel über die Tastatur, die Standardausgabe auf dem Bildschirm. Es gibt die Möglichkeit, Ein- und Ausgabe auf Dateien umzulenken, aber darauf wird hier nicht eingegangen.
Die Unterscheidung zwischen der Standardausgabe und der Standardfehlerausgabe dient dem Zweck, zwischen normalen Ausgaben und Fehlermeldungen unterscheiden zu können. Beispielsweise könnten so alle normalen Meldungen auf dem Bildschirm und die Fehlermeldungen in eine Protokolldatei ausgegeben werden.
5.1. Datenausgabe auf den Bildschirm
  Mit Hilfe des Bildschirms teilt ein Programm die Ergebnisse von Befehlen dem Benutzer mit.
  Dabei können konstante und variable Texte und Zahlen formatiert ausgegeben werden. Die
  Standardfunktion für eine Bildschirmausgabe ist die printf-Funktion.
  Dabei steht printf für "print formatted". Um die Funktion verwenden
  zu können, muss die Headerdatei stdio.h mittels
  #include <stdio.h> eingebunden werden.
  Die komplette Syntax der printf-Funktion lautet:
  int printf(const char *format [,argument_1 ... ,argument_n]);
  Dabei haben die einzelnen Wörter die folgenden Bedeutungen:
  
| int | Der Datentyp vor dem Funktionsnamen gibt an, was die Funktion als Ergebnis zurückgibt. In diesem Fall ist es eine ganze Zahl (int), die angibt, wieviele Zeichen insgesamt ausgegeben wurden. Im Falle eines Fehlers ist das Ergebnis gleich dem Wert EOF. | 
| printf | der eigentliche Funktionsname | 
| ( ... ) | Innerhalb dieser runden Klammern werden der Funktion die Parameter übergeben. | 
| const char *format | Der erste Parameter ist eine Zeichenkette, d.h. eine Folge von Zeichen, die in Anführungsstrichen stehen. In dieser Zeichenkette stehen die Formatierungen für die auszugebenden Daten. Über die Formatierungsangaben wird auch die Anzahl der auszugebenden Daten festgelegt. Die verschiedenen Formatierungsmöglichkeiten sind in den nächsten Tabellen aufgeführt. Mehr zu Zeichenketten finden Sie im Kapitel Strukturierte Datentypen. | 
| argument | Nach der Formatierungsangabe folgen die Variablennamen, deren Inhalte auf dem Bildschirm ausgegeben werden sollen, jeweils getrennt mit einem Komma. Die Anzahl der Argumente muss mit der Anzahl der Formatierungsanweisungen übereinstimmen. | 
  Die Formatierungszeichenkette beinhaltet zum einen "normale Zeichen", die direkt auf dem
  Bildschirm ausgegeben werden, und zum anderen die
  Formatierungsanweisungen. Eine Formatierungsanweisung hat folgenden Aufbau:
  %[Flags][Breite][.Präzision][F|N|hh|h|l|ll|L]Typ
  Jede Formatierungsanweisung beginnt mit einem Prozentzeichen. Auf dieses Zeichen folgen:
  
| [Flags] | Eine (optionale) Zeichenfolge, über die numerische Vorzeichen, Dezimalpunkte, führende und folgende Nullen, oktale und hexadezimale Präfixe sowie links- und rechtsbündige Ausgabe festgelegt werden. | 
| [Breite] | Eine (optionale) Angabe über die minimal auszugebende Zeichenzahl. Notfalls wird mit Leerzeichen oder Nullen aufgefüllt. | 
| [.Präzision] | Eine (optionale) Angabe, wieviele Zeichen maximal ausgegeben werden (Zeichenketten), die Minimalzahl von Ziffern (ganze Zahlen) bzw. die maximale Anzahl der Nachkommastellen (Fließkommazahlen). | 
| [F|N|hh|h|l|ll|L] | Eine (optionale) Angabe der Größe des Parameters. Genauere Angaben sind in der nächsten Tabelle enthalten. | 
| Typ | Die Angabe des Typs der auszugebenen Variable (siehe nächste Tabelle). Diese Angabe muss auf jeden Fall gemacht werden! | 
  Die folgende Tabelle gibt alle möglichen Typen an. Dabei wird erst einmal davon
  ausgegangen, dass außer der Größenangabe keine optionalen Angaben
  gemacht werden, d.h. keine Flags, Breite und keine Präzision.
  
| Typ | optionale | Datentyp des | Ausgabe | erlaubte | 
| d i1 | <keine> | int | dezimaler Integer | - + | 
| u | <keine> | unsigned int | dezimaler Integer | - + | 
| o | <keine> | unsigned int | oktaler Integer | - + # | 
| x X | <keine> | unsigned int | hexadezimaler Integer | - + # | 
| f F4 | <keine> | float, double | dezimale Fließkommazahl | - + # | 
| e E | <keine> | float, double | dezimale Fließkommazahl | - + # | 
| g G | <keine> | float, double | dezimale Fließkommazahl | - + # | 
| a3 A3 | <keine> | float, double | hexadezimale Fließkommazahl | - + # | 
| c | <keine> | int | Zeichen | - | 
| s | <keine> | char * | Zeichenkette (Array von char) bzw. Zeichenkette (Array von Multibytes) bis zu einem Nullzeichen oder dem Erreichen der durch .Präzision vorgegebene Zeichenzahl. | - | 
| p1 | <keine> | void * | Compilerabhängig; Far (F) und Near (N) -Zeiger sind nur in 16-Bit-Compilern enthalten. | Compiler- | 
| % | <keine> | - | Ausgabe des Zeichen %. | <keine> | 
  1 erst seit C89;   2 erst seit C95;   3 erst seit C99
  4 gehört nicht zum C-Standard, ist aber in vielen C-Compilern implementiert
  
  Beispiel:
   kap05_01.c
  kap05_01.c
  
  01 #include <stdio.h>
  02 
  03 int main()
  04 {
  05    int Zahl = 125;
  06    float Reel = 3033.1415f;
  07    char Zeichen = 'a';
  08 
  09    printf("Textausgabe ohne Variablen\n");
  10    printf("Die Variable Zahl hat den Wert %i\n", Zahl);
  11    printf("Variable Zahl in hex. Darstellung: %X\n", Zahl);
  12    printf("Die Variable Reel hat den Wert %f\n", Reel);
  13    printf("Variable Reel in Exponentendarstellung: %e\n", Reel);
  14    printf("Die Variable Zeichen hat %c als Inhalt.\n", Zeichen);
  15 
  16    return 0;
  17 }
  
  Dieses Beispielprogramm erzeugt folgende Bildschirmausgabe:
  
  Textausgabe ohne Variablen
  Die Variable Zahl hat den Wert 125
  Variable Zahl in hex. Darstellung: 7D
  Die Variable Reel hat den Wert 3033.141602
  Variable Reel in Exponentendarstellung: 3.033142e+03
  Die Variable Zeichen hat a als Inhalt.
  
  Mit der Typangabe alleine können bereits die meisten Bildschirmausgaben bewerkstelligt
  werden. Für die Feinheiten stehen die optionalen Angaben zur Verfügung:
  
| Flags | Ausgabe | 
| - | linksbündige Ausgabe (im Normalfall werden Zahlen rechtsbündig ausgegeben) | 
| + | numerische Ausgabe immer mit Vorzeichen (im Normalfall wird nur bei negativen Zahlen ein Vorzeichen ausgegeben) | 
| Leerzeichen | Positiven Zahlen wird ein Leerzeichen vorangestellt; wird dieses zusammen mit dem + verwendet, wird das Leerzeichen ignoriert! | 
| # | Alternative Darstellung | 
| 
 | 
 | 
| Breite | Ausgabe | 
| n | (n: Dezimalzahl) Es werden mind. n Zeichen ausgegeben und notfalls Leerzeichen vorangestellt. | 
| 0n | (0n: Dezimalzahl mit vorangestellter 0) Es werden mind. n
     Zeichen ausgegeben und notfalls Nullen vorangestellt. | 
| 
 | 
 | 
| .Präzision | Ausgabe | 
| .0 | Standardvorgabe für ganze Zahlen; | 
| .n | (n: Dezimalzahl) | 
  Beispiel:
  Nun wird das obige Beispielprogramm um diese optionalen Angaben erweitert:
   kap05_02.c
  kap05_02.c
  
  01 #include <stdio.h>
  02 
  03 int main()
  04 {
  05    int Zahl = 125;
  06    float Reel = 3033.1415f;
  07    char Zeichen = 'a';
  08 
  09    printf("Textausgabe ohne Variablen\n");
  10    printf("Die Variable Zahl hat den Wert %+05i\n", Zahl);
  11    printf("Variable Zahl in hex. Darstellung: %#X\n", Zahl);
  12    printf("Die Variable Reel hat den Wert %.10f\n", Reel);
  13    printf("Variable Reel in Exponentendarst.: %015.3e\n", Reel);
  14    printf("Zeichen hat %-3c als Inhalt.\n", Zeichen);
  15 
  16    return 0;
  17 }
  
  Diesmal wird folgende Bildschirmausgabe erzeugt:
  
  Textausgabe ohne Variablen
  Die Variable Zahl hat den Wert +0125
  Variable Zahl in hex. Darstellung: 0X7D
  Die Variable Reel hat den Wert 3033.1416015625
  Variable Reel in Exponentendarst.: 0000003.033e+03
  Zeichen hat a   als Inhalt.
  
  
5.2. Dateneingabe über die Tastatur
  Damit die "Kommunikation" zwischen Computer und Benutzer nicht einseitig aus
  Bildschirmausgaben besteht, ist es notwendig, dass der Benutzer Eingaben machen kann,
  die dem Programm (genauer: einer oder mehreren Variablen) übergeben werden. Zur
  Dateneingabe über die Tastatur wird in erster Linie der Befehl
  scanf verwendet. Die komplette Syntax lautet:
  int scanf(const char *format [,argument_1 ... ,argument_n]);
  Der Aufbau der Syntax sowie die einzelnen Parameter für den Befehl sind ganz
  ähnlich mit denen des printf-Befehls. Hier haben die einzelnen
  Wörter die folgenden Bedeutungen:
  
| int | Der Datentyp vor dem Befehl gibt an, was der Befehl als Ergebnis zurückgibt. In diesem Fall ist es eine ganze Zahl (int), die angibt, wieviele Werte insgesamt fehlerfrei eingelesen wurden. Im Falle eines Fehlers ist das Ergebnis gleich dem Wert EOF. | 
| scanf | der eigentliche Befehl | 
| ( ... ) | Innerhalb dieser runden Klammern werden dem Befehl die Parameter übergeben. | 
| const char *format | Der erste Parameter ist eine Zeichenkette, d.h. eine Folge von Zeichen, die in Anführungsstrichen stehen. In dieser Zeichenkette stehen die Formatierungen für die einzugebenden Daten. Über die Formatierungsangaben wird auch die Anzahl der einzulesenden Daten festgelegt. Die verschiedenen Formatierungsmöglichkeiten sind in der nächsten Tabelle aufgeführt. Mehr zu Zeichenketten finden Sie im Kapitel Strukturierte Datentypen. | 
| argument | Nach der Formatierungsangabe folgen die Variablennamen, jeweils getrennt mit einem Komma. Die Variablen müssen allerdings als Zeiger angegeben werden, d.h. es muss ein kaufmännisches Und (&) vor jeden Variablennamen gesetzt werden. Mehr zu Zeiger finden Sie im Kapitel Zeiger. | 
  Die Formatierungsanweisung ist ganz ähnlich wie bei dem
  printf-Befehl und ist wie folgt aufgebaut:
  %[*][Breite][F|N][hh|h|l|ll|L]Typ
  Auch hier beginnt jede Formatierungsanweisung mit einem Prozentzeichen. Auf dieses Zeichen
  folgen:
  
| [*] | Eine (optionale) Angabe, mit der die Zuweisung zum korrespondierenden Zeiger unterdrückt wird | 
| [Breite] | Eine (optionale) Angabe über die maximal zu lesende Zeichenzahl. Wird vor dem Erreichen der maximalen Zeichenanzahl ein sogenanntes "weißes" Leerzeichen (Trennzeichen wie Leerzeichen, Tabulator, Eingabetaste, ...) eingegeben, wird die Eingabe dieses Wertes beendet und zum nächsten einzugebenden Wert gesprungen. | 
| [F|N] | Eine (optionale) Angabe der Größe des Adress-Parameters (N = Near-Zeiger, F = Far-Zeiger. Diese Angabe ist nur notwendig, wenn die Größe des Parameters von der Standardgröße abweicht. | 
| [hh|h|l|ll|L] | Eine (optionale) Angabe der Größe des Parameters. Genauere Angaben sind in der nächsten Tabelle enthalten. | 
| Typ | Die Angabe des Typs des einzulesenden Wertes (siehe nächste Tabelle). Diese Angabe muss auf jeden Fall gemacht werden! | 
  Die folgende Tabelle gibt alle möglichen Typen an. Dabei wird erst einmal davon
  ausgegangen, dass keine optionalen Angaben gemacht werden, d.h. keine Breite
  usw.
  
| Typ | optionale | Datentyp des Parameters: | Eingabe | 
| d | <keine> | int | dezimaler Integer | 
| i1 | <keine> | int | dezimaler Integer; | 
| u | <keine> | unsigned int | dezimaler Integer (nur positive Zahl) | 
| o | <keine> | unsigned int | oktaler Integer (unabhängig von führender 0) | 
| x | <keine> | unsigned int | hexadezimaler Integer (unabhängig von führendem 0x bzw. 0X) | 
| c | <keine> | char | Zeichen (1 Byte) | 
| s | <keine> | char | Zeichenkette (Array von char) | 
| p1 | <keine> | Zeiger auf void | hexadezimaler Integer, der als Speicheradresse interpretiert wird | 
| f | <keine> | float | dezimale Fließkommazahl | 
| [ | <keine> | char | Zeichenkette (Array von char) | 
  1 erst seit C89;   2 erst seit C95;   3 erst seit C99
  4 gehört nicht zum C-Standard, ist aber in vielen C-Compilern implementiert
  Die folgenden Angaben gehören wohl nicht zum Standard-C, werden aber von einigen
  Compilern akzeptiert.
  
| Typ | entspricht Typ | Datentyp des Parameters: | Eingabe | 
| D | ld | long | dezimaler Integer | 
| I | li | long | dezimaler Integer | 
| U | lu | unsigned long | dezimaler Integer | 
| O | lo | unsigned long | oktaler Integer | 
| X | lx | unsigned long | hexadezimaler Integer | 
| E | e | float | dezimale Fließkommazahl | 
| G | lg | double | dezimale Fließkommazahl | 
  Beispiel:
   kap05_03.c
  kap05_03.c
  
  01 #include <stdio.h>
  02 
  03 int main()
  04 {
  05    int i;
  06    float f;
  07 
  08    printf("Bitte eine ganze Zahl & eine reele Zahl eingeben: ");
  09    scanf("%i %f", &i, &f);
  10    printf("Sie haben %i und %f eingegeben!\n", i, f);
  11 
  12    return 0;
  13 }
  
  Im Formatstring von scanf dürfen nur
  Platzhalter und Leerzeichen verwendet werden!
  Nun noch einige Besonderheiten beim Einlesen von Strings:
  Bei der Eingabe von Strings kann anstelle des Formats %s auch das
  Format %[Suchzeichen] verwendet werden. Suchzeichen ist
  eine Folge von Zeichen, aus denen die Eingabe bestehen muss.
  Beispiel: %[abcd] erwartet nur Eingaben, die aus
  den Zeichen a, b, c und
  d bestehen, bei jedem anderen Zeichen ist die Eingabe beendet.
  Wird als erstes Suchzeichen das Carret (^) verwendet, wird die Eingabe
  beendet, wenn eines der Suchzeichen eingegeben wird.
  Beispiel: %[^abcd] erwartet nur Eingaben, die
  nicht aus den Zeichen a, b, c
  und d bestehen. Die Eingabe wird in diesem Fall auch nicht von den
  sogenannten "weissen Leerzeichen" beendet, sondern nur durch die angegebenen
  Suchzeichen oder durch das Erreichen der mit Breite festgelegten Zeichenzahl.
  Anstelle von Zeichenaufzählungen können auch Bereiche angegeben werden.
  Beispiel: %[0123456789] ist äquivalent mit
  %[0-9].
  Bei manchen Compilern kann bzw. muss bei der Formatangabe das s
  angehangen werden (also %[Suchzeichen]s anstelle von
  %[Suchzeichen] ).
  
  Voriges Kapitel: 4. Datentypen in C
  
Nächstes Kapitel: 6. Kontrollstrukturen

