Beispielprogramm P3-1.C
main() { printf ("Viel Spass mit C !\n"); }
Erläuterungen zu diesem Programm:
- C-Programme bestehen aus Funktionen, diese sind an den dem Funktionsnamen folgenden runden Klammern zu erkennen
- Funktion main() muß immer vorhanden sein
- sie wird meist am Anfang des Quellencodes plaziert
- die geschweiften Klammern umschließen den Funktionskörper wie z.B. BEGIN und END in PASCAL
- das Ende des Quellencodes muß nicht explizit angegeben werden
- in C gibt es nur Funktionen, keine CALLs
- printf ist eine Funktion zur formatierten Ausgabe auf den Bildschirm
- sie hat hier die Stringkonstante "Viel Spass mit C !\n" als Parameter
- die Zeichenkombination \n steht für das Zeilenendezeichen
- C kennt keine Zeilenstruktur (Ausnahme: innerhalb von Zeichenketten oder #define-Anweisungen)
- Anweisungen sind mit ; zu beenden
Beispielprogramm P3-2.C
main() { printf ("Viel"); printf (" Spass"); printf (" mit"); printf (" C !"); printf ("\n"); }
Erläuterungen zu diesem Programm:
gleiche Wirkung wie Programm P3-1.C aber anderes Programm
kein explizites Zeilenendezeichen, daher Verkettung der Ausgabe
das Zeichen \ wirkt als Fluchtsymbol, es dient zur Darstellung von Sonderzeichen:
\t = Tabulatorzeichen \b = Backspacezeichen \" = das Zeichen " \\ = das Zeichen \
Beispielprogramm P3-3.C
/* Beispiel 3 */ /* Umwandlung von Fahrenheit in Celsius fuer f = 0, 20, ..., 300 */ main() { int lower,upper,step; float fahr,celsius; lower = 0; /* untere Grenze der Temperaturtabelle */ upper = 300; /*obere Grenze */ step = 20; /*Schrittweite */ fahr = lower; while (fahr <= upper) { celsius = (5.0/9.0) * (fahr-32.0); printf ("%4.0f %6.1f\n",fahr,celsius); fahr = fahr + step; } }
Erläuterungen zu diesem Programm:
- alle Angaben zwischen /* und */ werden als Kommentar behandelt
- Kommentar kann überall im Quellencode stehen wo auch ein Leerzeichen, Tabulatorzeichen oder Zeilentrennzeichen stehen darf, sinnvollerweise schreibt man ihn aber an das Ende einer Zeile und/oder verwendet Kommentarzeilen
- in C müssen alle Variablen vor ihrer Verwendung vereinbart werden
- Vereinbarungen müssen am Anfang eines Blocks vor der ersten Anweisung stehen
- man unterscheidet Deklarationen und Definitionen
- C kennt folgende elementaren Datentypen
char := einzelnes Zeichen (Character)
int := Integerzahlen
float := Gleitkommazahlen
double := Gleitkommazahl mit doppelter Genauigkeit
- zur Qualifizierung dienen dann noch die Zusätze:
short := kleine Integerzahl
long := große Integerzahl
unsigned := ohne Vorzeichen
signed := mit Vorzeichen (Weglasswert)
- die Zeilen :
lower = 0;
upper = 300;
fahr = lower;
stellen Zuweisungen dar, dabei wird im 3.Fall eine Typwandlung von int nach float durchgeführt
- while (fahr <= lower) {
...
}
ist eine von mehreren in C realisierten Kontrollstrukturen, die Anweisungen in den geschweiften Klammern werden nur ausgeführt, wenn der Ausdruck in der Klammer nach while wahr ist
- hängt nur eine einzige Anweisung von der while Bedingung ab, so kann man die geschweiften Klammern auch weglassen:
while (i < j)
i = 2 * j;
- in C gilt generell die Konvention:
gleich 0 := FALSE (FALSCH)
ungleich 0 := TRUE (WAHR)
- die Formulierung 5.0/9.0 gegenüber 5/9 ist notwendig, da wegen der sonst verwendeten Ganzzahlarithmetik 5/9=0 gilt
- dagegen kann man die Zahl 32 als 32 oder 32.0 schreiben, weil C die Verwendung gemischter Typen in Ausdrücken erlaubt; zum Zwecke der besseren internen Dokumentation sollte man in unserem Falle aber 32.0 verwenden (Gleitkommazahlen)
- printf kann mehr als einen Parameter haben und gleichzeitig die Ausgabe formatieren:
printf("%4.0f %6.1f\n",fahr,celsius);
bedeutet:
gibt die Variable fahr im Gleitkommaformat mit insgesamt 4 Stellen ohne Nachkommastellen aus, füge ein Leerzeichen (Blank) ein, gib dann die Variable celsius im Gleitkommaformat mit insgesamt 6 Stellen und einer Nachkommastelle aus und schließe die Ausgabe mit einem Zeilenendezeichen ab
- printf kennt noch andere Umwandlungsformate:
%c := ein einzelnes Zeichen
%d = Integerzahl
%f := Gleitkommazahl
%o := Oktaldarstellung
%s := Zeichenkette
%x := Hexadezimaldarstellung
%% := das %-Zeichen selbst ausgeben
Beispielprogramm P3-4.C
/* Beispiel 4 */ /* wie Beispiel 3 aber mit for-Schleife */ main() { int fahr; for (fahr=0; fahr <= 300; fahr=fahr+20) printf ("%4.0d %6.1f\n",fahr,(5.0/9.0)*(fahr-32)); }
Erläuterungen zu diesem Programm:
- dieses Programm liefert das gleiche Ergebnis, wie das vorige Beispiel, aber es sieht ganz anders aus
- fahr ist jetzt eine Integerzahl, dies dient nur der Demonstration der %d Umwandlung
- printf akzeptiert auch Ausdrücke für die auszugebenden Parameter
- die for Schleife ist eine weitere in C mögliche Kontrollstruktur, sie hat die Form:
for (Initialisierung; Bedingung; Reinitialisierung)
Beispielprogramm P3-5.C
/* Beispiel 5 */ /* wie Beispiel 4 aber mit #define-Konstanten */ #define LOWER 0 /* untere Grenze der Tabelle */ #define UPPER 300 /* obere Grenze der Tabelle */ #define STEP 20 /* Schrittweite */ main() { int fahr; for (fahr=LOWER; fahr <=UPPER; fahr=fahr+STEP) printf ("%4.0d %6.1f\n",fahr,(5.0/9.0)*(fahr-32)); }
Erläuterungen zu diesem Programm:
- die Verwendung von symbolischen Konstanten garantiert eine einfache Änderungsmöglichkeit
- symbolische Konstanten werden üblicherweise zur einfacheren Identifizierung in Großbuchstaben geschrieben
- C unterscheidet zwischen Groß- und Kleinschreibung
- nach #define Zeilen steht kein Semikolon, da #define einen Textersatz (also auch mit evtl. Semikolon) bewirkt
- das # muß in der 1. Spalte stehen
- der C-Präprozessor verarbeitet diejenigen Anweisungen, bei denen ein # in der ersten Spalte steht (in unserem Falle hier ist diese Verarbeitung ein Textersatz)
Beispielprogramm P3-6.C
/* Beispiel 6 */ /* ein Kopierprogramm */ #include <stdio.h> /* enthaelt wichtige Konstantendefinitionen */ main() { int c; c = getchar(); while (c != EOF) { putchar(c); c=getchar(); } }
Erläuterungen zu diesem Programm:
- #include bewirkt das Einfügen von Quellencode aus einer anderen Datei
- die Hauptanwendung liegt im Einfügen von sogenannten Header-Dateien, die üblicherweise zu jedem C-Bibliothekssystem dazugehören
- eine solche Headerdatei hat die Dateinamenergänzung .h und enthält Symbole und Vereinbarungen, die bei bestimmten Anwendungen (z.B. Ein-/Ausgabe, Dateiverarbeitung) immer wieder gebraucht werden
- die spitzen Klammern um den Dateinamen bewirken, daß zunächst das "INCLUDE"-Verzeichnis (bei UNIX Systemen meist /usr/lib/include) und erst dann das Arbeitsverzeichnis nach der angegebenen Datei durchsucht wird
- auf verschiedenen Rechnern kann EOF 0 oder -1 sein, daher die Definition von EOF in einer Headerdatei
- c ist als int deklariert, um den Wert EOF abfragen zu können
- getchar ist eine Funktion aus der Funktionsbibliothek, die 1 Zeichen von der Konsole (stdin) einliest
- putchar gibt 1 Zeichen auf die Konsole (stdout) aus
- != bedeutet ungleich
- nach der while Bedingung sind 2 Anweisungen mittels geschweifter Klammern zu einem Block zusammengefaßt
- man hätte das Programm auch noch kompakter so formulieren können
while ((c=getchar()) != EOF) putchar(c);
die Klammerung ist sehr wichtig sonst wird c der Wert des Vergleiches von getchar() mit EOF und nicht das gelesene Zeichen zugewiesen
Beispielprogramm P3-7.C
/* Beispiel 7 */ /* Programm zum Zaehlen von Eingabezeichen */ #include <stdio.h> main() { long nc; nc = 0; while (getchar() != EOF) ++nc; printf ("%ld\n",nc); }
Erläuterungen zu diesem Programm:
- ++nc ist eine Inkrementoperation für die Variable nc, analog ist --nc eine Dekrementoperation
- ++nc und nc++ sind beide möglich, unterscheiden sich aber
- ++nc heißt erst inkrementieren, dann Wert von nc verwenden
- nc++ heißt erst Wert von nc verwenden, dann inkrementieren
- die Formatangabe %ld ist notwendig, da nc ein Long-Integerwert ist
Beispielprogramm P3-8.C
/* Beispiel 8 */ /* wie Beispiel 7, aber mit for-Schleife und anderer Datentyp fuer den Zaehler */ #include <stdio.h> main() { double nc; for (nc=0;getchar() != EOF; ++nc) ; printf ("%.0f\n",nc); }
Erläuterungen zu diesem Programm:
- die for-Schleife in diesem Fall hat keine abhängige Anweisung, daher das einzelne Semikolon in einer neuen Zeile (wichtig zur Dokumentation)
- die Formatangabe %.0f bewirkt die Ausgabe eine doppelt genauen Gleitpunktzahl ohne Nachkommastellen
Beispielprogramm P3-9.C
/* Beispiel 9 */ /* Programm zum Zaehlen der Eingabezeilen */ #include <stdio.h> main() { int c,nl; nl = 0; while ((c=getchar()) != EOF) /* Klammern sind wichtig */ if (c == '\n') ++nl; printf("%d\n",nl); }
Erläuterungen zu diesem Programm:
- hier sehen wir eine if Kontrollstruktur, wobei die Bedingung wie bei while in Klammern gesetzt wird
- die if Kontrollstruktur sieht so aus:
if (Bedingung)
Anweisung(en)
else
Anweisung(en)
der else Zweig ist optional
- == bedeutet identisch
- '\n' ist eine Zeichenkonstante, deswegen in Hochkommas eingeschlossen
Beispielprogramm P3-10.C
/* Beispiel 10 */ /* Eingabezeilen, -worte und -zeichen zaehlen */ #include <stdio.h> #define YES 1 #define NO 0 main() { int c, nl, nw, nc, inword; inword = NO; nl = nw = nc = 0; while ((c=getchar()) != EOF) { ++nc; if (c == '\n') ++nl; if (c==' ' || c=='\n' || c=='\t') inword = NO; else if (inword == NO) { inword = YES; ++nw; } } printf("%d %d %d\n",nl,nw,nc); }
Erläuterungen zu diesem Programm:
- verbundene Anweisungen wie nl=nw=nc=0; werden von rechts nach links abgearbeitet, sie sollten nach Möglichkeit vermieden werden
- || ist der (logische) ODER-Operator
- && ist der (logische) UND-Operator
- Ausdrücke mit logischen Operatoren werden von links nach rechts bewertet und dann abgebrochen, wenn das Ergebnis feststeht (also der erste Teilausdruck ungleich 0 (bei ODER) oder gleich 0 (bei UND) ist
Beispielprogramm P3-11.C
/* Beispiel 11 */ /* Ziffern, Zwischenraeume und andere Zeichen zaehlen */ #include <stdio.h> main() { int c,i,nwhite,nother; int ndigit[10]; nwhite=nother=0; for (i=0; i<10; ++i) ndigit[i]=0; while ((c=getchar()) != EOF) if (c>='0' && c<='9') ++ndigit[c-'0']; else if (c==' ' || c=='\n' || c=='\t') ++nwhite; else ++nother; printf("Zahlen ="); for (i=0; i<10; ++i) printf(" %d",ndigit[i]); printf("\n\"White Space\" = %d, andere = %d\n", nwhite,nother); }
Erläuterungen zu diesem Programm:
- Vektoren (Felder) werden durch Anhängen von eckigen Klammern an den Variablennamen definiert
- die Feldindizes laufen von 0 bis N-1, sie werden nicht abgeprüft
- das Beispielprogramm gilt nur für Zeichencodes mit lückenlosem Aufeinanderfolgen von Ziffern (sowohl in EBCDIC als auch in ASCII erfüllt)
- char wird intern in int gewandelt, deshalb ist der Ausdruck
c-'0'
so einfach möglich
- Verkettungen von if und else sollte man so schreiben:
if oder if else else if if else else
Beispielprogramm P3-12.C
/* Beispiel 12 */ /* die Funktion X hoch N */ main() { int i; for (i=0; i<10; ++i) printf("%d %d %d\n",i,power(2,i),power(-3,i)); } power(x,n) /* x hoch n, n>0 */ int x,n; { int i,p; p=1; for (i=1; i<=n; ++i) p = p * x; return(p); }
Erläuterungen zu diesem Programm:
- hier haben wir zum ersten Mal eine "richtige" Funktion
- eine Funktion hat immer die Form:
Name(Parameterliste,optional)
Parameterdeklarationen,optional
{
Vereinbarungen
Anweisungen
return Funktionswert,optional
}
- die Parameternamen sind nur lokal bekannt
- die Parameterwerte sind durch die Funktion nur lokal nicht aber mit Wirkung für die aufrufende Funktion veränderbar
- die return Anweisung bewirkt einen Rücksprung mit der Übergabe des Funktionswertes, die Klammern um den Funktionswert sind syntaktisch nicht notwendig, aber üblich
- fehlt return, dann erfolgt der Rücksprung nach der letzten schließenden geschweiften Klammer, der Funktionswert ist dann unbestimmt
Beispielprogramm P3-13.C
/* Beispiel 13 */ /* Wie Beispiel 3, aber mit Einlesen der Grenzen und der Schrittweite */ #include <stdio.h> main() { int i; int lower,upper,step; float fahr,celsius; i=0; while (i != 2) { printf("Bitte die Grenzen fuer die Berechnung in \ der Form \"untere - obere\" angeben\n"); i=scanf("%d - %d",&lower,&upper); if (i != 2 || upper<=lower) { printf("\n Falsche Eingabe \07\n"); i = 0; } } i=0; while (i != 1) { printf("Bitte die Schrittweite eingeben: "); i=scanf("%d",&step); if (i != 1 || step <= 0) { printf("\n Falsche Eingabe \07\n"); i = 0; } } fahr = lower; while (fahr <= upper) { celsius = (5.0/9.0) * (fahr-32.0); printf ("%4.0f %6.1f\n",fahr,celsius); fahr = fahr + step; } }
Erläuterungen zu diesem Programm:
- wir haben hier das gleiche Programm wie in Beispiel P3-3.C, allerdings werden hier einige Daten interaktiv eingelesen
- das Einlesen wird von der Funktion scanf bewerkstelligt
- sie hat die gleiche Formatsteuerung wie printf
- die Parameter müssen aber Adressen sein (Warum?)
- & ist der Adressoperator, Ergebnis ist die Adresse des Objekts
- Funktionswert von scanf ist die Anzahl erfolgreich eingelesener Parameter
- alle Angaben in den Anführungsstrichen von scanf, die nicht zu Formatangaben gehören, müssen genauso eingegeben werden
- Strings dürfen über das Zeilenende hinausgehen, wenn unmittelbar vor dem Zeilenende ein \ steht
- \" gibt " aus
- \07 gibt das ASCII-Zeichen mit dem Oktalcode 07 (=BELL) aus