Kapitel 3

Formatierte Ein-/Ausgabe

C Programming: A Modern Approach — K. N. King

Wahlpflichtfach Informatik

Übersicht

  • printf — Formatierte Ausgabe
  • Umwandlungsspezifikationen & Escape-Sequenzen
  • scanf — Formatierte Eingabe
  • Gewöhnliche Zeichen im Formatstring
  • Häufige Fehler & Fallen
  • Programm: Brüche addieren

Die printf-Funktion

Gibt den Inhalt eines Formatstrings aus, wobei Werte an markierten Stellen eingefügt werden.

printf(formatstring, ausdruck1, ausdruck2, ...);
  • Keine Begrenzung der Anzahl an Werten
  • Der Compiler prüft nicht, ob Spezifikation und Typ zusammenpassen
Achtung: Falscher Typ → sinnlose Ausgabe, kein Fehler vom Compiler!

Umwandlungsspezifikationen

Allgemeine Form

%m.pX     oder     %-m.pX
  • m = Minimale Feldbreite (optional)
  • p = Genauigkeit (optional)
  • X = Umwandlungsspezifizierer (d, f, e, g)
  • - = Linksbündige Ausgabe

Feldbreite (m)

AufrufAusgabeErklärung
printf("%4d", 123) ·123 Rechtsbündig, 1 Leerzeichen
printf("%4d", 12345) 12345 Feld wird automatisch erweitert
printf("%-4d", 123) 123· Linksbündig
· steht hier für ein Leerzeichen.

Spezifizierer

SpecBeschreibungBeispiel
%d Ganzzahl (Dezimal) printf("%4d", 42)··42
%f Float (Dezimalform) printf("%.2f", 3.14)3.14
%e Float (Exponentialform) printf("%e", 3.14)3.140000e+00
%g Float (%e oder %f, kürzer) printf("%g", 0.0001)0.0001

Genauigkeit (p)

SpezifiziererBedeutung von p
%dMindestanzahl Ziffern (Standard: 1)
%f, %eNachkommastellen (Standard: 6)
%gSignifikante Stellen (Standard: 6)
printf("%10.3f", 3.14159);   /*    ·····3.142  */
printf("%.2f", 83.162);     /*    83.16        */
printf("%.4g", 123456.0);   /*    1.235e+05    */

Escape-Sequenzen

SequenzWirkung
\nZeilenumbruch
\tTabulator
\\Einzelnes Backslash-Zeichen
\"Anführungszeichen im String
\aAkustisches Signal
%%Einzelnes Prozentzeichen
printf("Item\tUnit\tPurchase\n\tPrice\tDate\n");
printf("Gewinn: %d%%\n", 10);  /* Gewinn: 10%  */
printf("\"Hallo!\"");           /* "Hallo!"     */

Escape-Sequenzen — Ausgabe

printf("Item\tUnit\tPurchase\n\tPrice\tDate\n");

Erzeugt:

Item Unit Purchase Price Date
Tabstopps sind in C nicht definiert — typisch 8 Zeichen, aber vom Betriebssystem abhängig.

Die scanf-Funktion

Liest Eingaben gemäß einem Formatstring und speichert sie in Variablen.

int i, j;
float x, y;
scanf("%d%d%f%f", &i, &j, &x, &y);
& vor dem Variablennamen ist Pflicht! Fehlt es → Absturz oder undefiniertes Verhalten.

Wie scanf funktioniert

  • Liest die Eingabe als durchgehenden Zeichenstrom
  • Überspringt Whitespace automatisch beim Suchen nach Zahlen
  • Eingabe kann auf einer oder mehreren Zeilen stehen
scanf("%d%d%f%f", &i, &j, &x, &y);

/* Eingabe (3 Zeilen):
     1
   -20   .3
     -4.0e3
   → i=1, j=-20, x=0.3, y=-4000.0  */

Erkennungsregeln

%d — Ganzzahl

  • Sucht: Ziffer, +, oder -
  • Liest Ziffern bis Nicht-Ziffer
  • Nicht passende Zeichen → zurückgelegt

%f / %e / %g — Float

  • Optionales Vorzeichen
  • Ziffern (evtl. Dezimalpunkt)
  • Optionaler Exponent (e/E)
  • Alle drei sind austauschbar

Zurücklegen von Zeichen

scanf("%d%d%f%f", &i, &j, &x, &y);
/* Eingabe: 1-20.3-4.0e3 */
  • %d → liest 1, stoppt bei - (zurückgelegt)
  • %d → liest -20, stoppt bei . (zurückgelegt)
  • %f → liest .3, stoppt bei - (zurückgelegt)
  • %f → liest -4.0e3
Eingaben landen in einem versteckten Puffer — scanf kann Zeichen dorthin zurücklegen.

Gewöhnliche Zeichen im Formatstring

  • Leerzeichen → überspringt beliebig viele Whitespace-Zeichen
  • Andere Zeichen → müssen exakt in der Eingabe vorkommen
/* Erwartet z.B. "2/17" */
scanf("%d/%d", &monat, &tag);

/* Erwartet z.B. "4,28" */
scanf("%d,%d", &i, &j);
Eingabe 4 28 bei "%d,%d" → scanf bricht ab! Komma fehlt.

Häufige Fehler

1. & in printf

printf("%d %d\n", &i, &j);   /* FALSCH! */
printf("%d %d\n",  i,  j);   /* Richtig */

Gibt seltsame Zahlen (Speicheradressen) statt Werte aus.

Häufige Fehler

2. \n am Ende von scanf

scanf("%d\n", &i);   /* FALSCH! */
scanf("%d",   &i);   /* Richtig */

\n wirkt in scanf wie ein Leerzeichen — Programm hängt, bis der Benutzer ein nicht-leeres Zeichen eingibt.

Häufige Fehler

3. Unnötige Zeichen im scanf-Format

scanf("%d, %d", &i, &j);    /* Erwartet Komma! */

Wenn der Benutzer 4 28 eingibt (ohne Komma), wird j nicht gelesen.

Faustregel: scanf-Formatstrings so einfach wie möglich halten. Nur Umwandlungsspezifikationen verwenden, wenn möglich.

Programm: Brüche addieren

#include <stdio.h>

int main(void)
{
    int num1, denom1, num2, denom2,
        result_num, result_denom;

    printf("Ersten Bruch eingeben: ");
    scanf("%d/%d", &num1, &denom1);

    printf("Zweiten Bruch eingeben: ");
    scanf("%d/%d", &num2, &denom2);

    result_num = num1 * denom2 + num2 * denom1;
    result_denom = denom1 * denom2;

    printf("Die Summe ist %d/%d\n",
           result_num, result_denom);

    return 0;
}

addfrac.c — Ausgabe

Ersten Bruch eingeben: 5/6 Zweiten Bruch eingeben: 3/4 Die Summe ist 38/24
  • scanf("%d/%d", ...) nutzt / als Trennzeichen
  • Das Ergebnis wird nicht gekürzt
  • Formel: a/b + c/d = (a·d + c·b) / (b·d)

Fragen & Antworten

%i vs. %d

printf Kein Unterschied

scanf Großer Unterschied!

  • %d → nur Dezimalzahlen
  • %i → erkennt auch Oktal (056) und Hex (0x56)
Falle: Führende 0 bei %i wird als Oktalzahl interpretiert!
Empfehlung: Bei %d bleiben.

Fragen & Antworten

Ungültige Eingabe bei scanf

printf("Zahl eingeben: ");
scanf("%d", &i);
  • Eingabe 23fooi = 23, foo bleibt im Puffer
  • Eingabe fooi undefiniert, foo bleibt im Puffer
Prüfung: Rückgabewert von scanf auswerten (Details in Kapitel 22).

Fragen & Antworten

Satzzeichen zwischen Zahlen

scanf("%d%d", &i, &j);
/* Eingabe: 4,28  →  i=4, j wird NICHT gelesen */

Lösung: Komma im Formatstring:

scanf("%d,%d", &i, &j);
/* Eingabe: 4,28  →  i=4, j=28  ✓ */

Übung — printf-Ausgaben

Welche Ausgabe erzeugen diese Aufrufe?

AufrufAusgabe
printf("%6d,%4d", 86, 1040) ····86,1040
printf("%12.5e", 30.253) ·3.02530e+01
printf("%.4f", 83.162) 83.1620
printf("%-6.2g", .0000009979) 1e-06·

Übung — scanf-Falle ★

scanf("%d%f%d", &i, &x, &j);
/* Eingabe: 10.3 5 6 */
VariableWertErklärung
i10Stoppt am Punkt
x0.3Liest .3 als Float
j5Nächste Ganzzahl

6 bleibt im Eingabepuffer.

Übung — scanf-Falle ★

scanf("%f%d%f", &x, &i, &y);
/* Eingabe: 12.3 45.6 789 */
VariableWertErklärung
x12.3Vollständiger Float
i45Stoppt am Punkt
y0.6Liest .6 als Float

789 bleibt im Eingabepuffer.

Übung — scanf-Formatstrings

Sind diese Paare gleichwertig?

PaarGleichwertig?
"%d" vs. " %d" Ja%d überspringt Whitespace
"%d-%d-%d" vs. "%d -%d -%d" Nein — Leerzeichen überspringt extra Whitespace
"%f" vs. "%f " Nein — nachstehendes Leerzeichen → hängt
"%f,%f" vs. "%f, %f" Ja — Leerzeichen vor %f ist redundant

Programmierprojekte

Projekt 1: Datumsformatierung

Datum im Format mm/dd/yyyy einlesen, als yyyymmdd ausgeben.

Datum eingeben (mm/dd/yyyy): 2/17/2011 Eingegebenes Datum: 20110217
Hinweis: scanf("%d/%d/%d", &m, &d, &y) für die Eingabe verwenden.

Programmierprojekte

Projekt 2: Produktinformationen

Artikelnummer eingeben: 583 Stückpreis eingeben: 13.5 Kaufdatum eingeben (mm/dd/yyyy): 10/24/2010 Item Unit Purchase Price Date 583 $ 13.50 10/24/2010

Hinweis: Tabs (\t) für Spaltenausrichtung verwenden.

Programmierprojekte

Projekt 3: ISBN zerlegen

ISBN eingeben: 978-0-393-97950-3 GS1-Präfix: 978 Gruppenkennung: 0 Verlagscode: 393 Titelnummer: 97950 Prüfziffer: 3
Hinweis: scanf mit - als Trennzeichen. Gruppengrößen variieren!

Programmierprojekte

Projekt 4: Telefonnummer

Telefonnummer eingeben [(xxx) xxx-xxxx]: (404) 817-6900 Eingegeben: 404.817.6900

Projekt 5: Magisches Quadrat

16 Zahlen einlesen, als 4×4-Feld anzeigen, Zeilen-/Spalten-/Diagonalsummen berechnen.

Programmierprojekte

Projekt 6: addfrac erweitern

Beide Brüche auf einmal eingeben, getrennt durch +:

Zwei Brüche mit + eingeben: 5/6+3/4 Die Summe ist 38/24
Hinweis: scanf("%d/%d+%d/%d", &n1, &d1, &n2, &d2)

Zusammenfassung

ThemaKernpunkte
printf %m.pX für Feldbreite, Genauigkeit, Typ
Escape-Sequenzen \n, \t, \\, \", %%
scanf & nicht vergessen! Whitespace wird übersprungen
Formatstrings Zeichen im Format müssen in der Eingabe vorkommen
Typische Fallen Kein \n in scanf, & nicht in printf

Ende Kapitel 3

Fragen?