C_C++ [Kompatibilitätsmodus]

Werbung
Informatik
Heinrich Krämer
Hochschule für Technik, Wirtschaft und Kultur Leipzig (FH)
Fachbereich Informatik, Mathematik und Naturwissenschaften
Folie 2
1 Einführung
Einsatz von Rechnern im Automobilbau
– Entwurf
• Festigkeitsanalysen
• Simulierte Crashtest
– Produktion
• Personalverwaltung
• Robotik
• Ein-, Verkauf, Lagerhaltung
– Betrieb
• Motorsteuerung (Einspritzanlage)
• Traktionskontrolle, ABS
• Navigationssystem
Wesentliche Merkmale lassen sich nicht oder nur mit immensem Aufwand ohne
Rechnereinsatz realisieren. In anderen Brachen ergibt sich ein ähnliches Bild.
Grundlagen der Informatik
Folie 3
1.1 Algorithmus
Ein Algorithmus ist die Beschreibung eines Verfahrens, wie aus gegeben
Eingabedaten die gewünschten Ausgabedaten berechnet werden können.
Ausgangspunkt bei der Entwicklung eines Algorithmus ist eine exakte Spezifikation
Diese besteht aus
– Eingabe
Genaue Angabe der zulässigen Eingabewerte
– Ausgabe
Angabe der Wertebereiche des Ausgabedaten.
Mögliche Fehlermeldung
– Funktionaler Zusammenhang
Grundlagen der Informatik
Folie 4
1.1 Algorithmus
Entwicklung eines Algorithmus nach der Top-Down-Methode
Problemanalyse
Welche mögliche Eingabedaten können auftreten?
Welche Eingabedaten sollen unzulässig sein?
Welche Ausgabedaten sollen berechnet werden?
Wie soll auf unzulässige Eingaben reagiert werden?
Welcher funktionale Zusammenhang besteht zwischen diesen?
Spezifikation
Zergliedern in Teilprobleme
Häufig: Eingabe, Verarbeitung, Ausgabe
Welche Teilergebnisse müssen berechnet werden?
Bestimmung der Reihenfolge
abstrakter Algorithmus
Codierung
Formulierung des Algorithmus in einer Programmiersprache
Grundlagen der Informatik
Folie 5
1.1 Algorithmus
Beispiel
Berechnung GGT (Größter gemeinsamer Teiler)
Eingabe: Zwei natürliche Zahlen a, b
Ausgabe: natürliche Zahl g
Funktionaler Zusammenhang:
a und b sind durch g ohne Rest teilbar
g ist größte Zahl mit dieser Eigenschaft
Algorithmus
1. Eingabe(a);
2. Eingabe(b);
3. solange a b
3.3 falls a < b : b := b – a
3.3 sonst a := a – b
4 Gebe a aus
Grundlagen der Informatik
Adressbus
Datenbus
Steuerbus
Central Processing Unit
Leitwerk
Zustand
Operandenholen
Befehlholen
Dekodieren
Ausführen
Programmzähler
Nr
0
1
2
3
4
5
6
7
Register
Inhalt
15
Adresse
0
1
2
3
4
5
6
7
8
9
10
Inhalt
100
101
102
103
104
105
106
107
108
109
110
111
112
113
Lade R0 <- [5]
Lade R1 <- [6]
Falls R0 R1 gehe 110
Falls R0 > R1 gehe 107
R2 <- R1 - R0
Speichere [5] <- R2
gehe 100
R2 <- R0 - R1
Speichere [6] <- R2
gehe 100
Ende
Peripherie
15
10
100
ALU
Arithmetic
Logic
Unit
Folie 7
1.2 Programmablaufpläne / Flußdiagramme
Startknoten
Start
Zusammenführung
Endeknoten
Ende
Anweisung
true
?
false
Grundlagen der Informatik
Anweisungsknoten
Verzeigungsknoten
Ein- / Ausgabeknoten
Unterprogramm
Unterprogrammaufruf
Folie 8
Beispiel: GGT (größter gemeinsamer Teiler)
Start
a, b
false
true
a
b?
true
b = b -a
Ende
Grundlagen der Informatik
a < b?
false
a=a-b
C-Notation
int main()
{
int a,b;
scanf(`` %d %d´´,&a,&b)
while (a != b) {
if (a < b) {
b = b - a;
} else {
a = a - b;
}
}
}
Folie 9
2 Darstellung von Information
Programme und Daten werden im Speicher als Bytes (Achtergruppen von 0/1 den
Bits) gespeichert. Die Bedeutung der Information ist hierbei von der Interpretation
abhängig
Mögliche Interpretationen bei einem Intel-Proz.
Adresse
+0
+1
+2
+3
Inhalt
1111 0111
1100 0010
0100 0001
0110 0010
Befehl: test dx, 0110001001000001b
Ganzzahl
1648476919
Gleitkommazahl
1,513762354851 269
Zeichen
TAb
Die Interpretation der Daten wird bei einer Hochsprache durch den Datentyp
festgelegt
Grundlagen der Informatik
Folie 10
2.1 Skalaren Datentypen in C/C++
Der Datentyp int
int dient zur Modellierung von ganzzahligen Werten. Es ist in C üblich, diesen
Datentyp auf die Maschinenwortbreite abzubilden.
Beispiele für Maschinenwortbreiten
Zahlenbereich
i286
16-Bit
-215...215-1
-32768... 32767
i386
32-Bit
-231...231-1
-2147483648... 2147483647
Pentium
32-Bit
-231...231-1
-2147483648... 2147483647
Sparc
64-Bit
-263...263-1 -9,223372036855e+18... 9,223372036854e+18
Modifizierer
signed
Es werden positive und negative Werte betrachtet (Standard)
unsigned Es werden nur positive Werte betrachtet
long
Es gilt immer, dass jeder int Wert in long darstellbar ist
short
Es gilt, dass jeder short Wert in int darstellbar ist
Grundlagen der Informatik
Folie 11
2.2 Skalaren Datentypen in C/C++
Der Datentyp float (Gleitkommazahlen)
Float dient zur Modellierung von reellen Zahlen. Hierbei ist jedoch zu beachten,
dass diese nur mit endlicher Genauigkeit dargestellt werden können. Die
Darstellung ist in der IEEE-Norm 754 festgelegt. Die rechnerinterne Darstellung
erfolgt analog dem „wissenschaftlichen Format“ bei einem Taschenrechner als
Vorzeichen Mantisse 2Exponent
Hierbei haben Mantisse und Exponent eine feste Länge, welche die
Genauigkeit der Darstellung bestimmt
float
Einfache Genauigkeit
double
Doppelte Genauigkeit
Konstante bei Gleitkommazahlen
1.0
(Gleitkomma Eins)
0.31417e+1 (Gleitkomma 3,1417)
Grundlagen der Informatik
Folie 12
2.2 Skalaren Datentypen in C/C++
Der Datentyp char
Dient der Darstellung von Zeichen. Eigentlich handelt es sich hierbei um ein
8-Bit Ganzzahlformat. Daher gibt es auch für char die Modifizierer signed
(Standard!) und unsigned. Die Zeichen werden üblicherweise im ASCIIFormat (American Standard Code for Information Interchange) dargestellt.
Eine Zeichenkonstante wird in Einfachhochkommas eingeschlossen.
'c'
Das Zeichen c
Zusätzlich gibt es noch einige spezielle Zeichen
\t
Tabulator
\n
neue Zeile (newline)
\“
Doppelhochkomma
\‘
Einfachhochkomma
\\
back slash
\<Oktalcode> zur Notation von nicht druckbare Zeichen
Grundlagen der Informatik
Folie 13
2.2 Skalaren Datentypen in C/C++
Der Datentyp bool
dient der Modellierung von Wahrheitswerten. Es gibt nur die beiden Konstanten:
false
falsch
true
wahr
Es gilt false < true.
In C/C++ wird jeder Wert ungleich 0 als true und jeder Wert gleich 0 als false
angesehen.
Besonderheiten
0
false
17
true
0.0
false
-0.0 true
Grundlagen der Informatik
Folie 14
Notation
Backus-Nauer-Form (BNF)
Produktion
<linke Seite> ::= { <Nichtterminale> | <Terminale> }
Methazeichen
[ ] optionales Vorkommen
{ } beliebig oft
... | ... Auswahl
Beispiel <Bezeichner>: jedes Objekt muss einen eindeutigen Namen erhalten
<Bezeichner> ::= <Buchstabe> { <Buchstabe> | <Ziffer> }
<Buchstabe> ::= a|b|...|z|A|B|...|Z|_|$
(Großkleinschreibung ist relevant)
<Ziffer> ::= 0|1|...|9
Legale Bezeichner
x11, Beta, beta
Ein_Sehr_Langer_Bezeichner
__system, $syscall
Grundlagen der Informatik
Illegale Bezeichner
1_Fehler, faulty-name
Folie 15
2.3 Ausdrücke
Typumwandlung
(typ) Ausdruck
Inkrement/Dekrement
++ Inkrement (+1)
-- Dekrement (-1)
Unitäre Operatoren
+ Positiv
- Negativ
! Logisches Nicht
~ Bitweises Komplement
Multiplikationsoperatoren
* Multiplikation
/ Division
% Modulo
Additionsoperator
+ Addition
- Subtraktion
Grundlagen der Informatik
Schiebeoperatoren
<< Schieben nach links
>> Schieben nach rechts
Vergleichsoperatoren
> Größer
< Kleiner
>= Größergleich
<= Kleinergleich
Gleichheitsoperatoren
== Gleichheit
!= Ungleichheit
Bitoperatoren
& Bitweises UND
^ Bitweise Antivalenz
| Bitweises ODER
Logische Operatoren
&& UND
|| ODER
Folie 16
2.3 Ausdrücke
Bedingte Ausdrücke
<Ausdruck1> ? <Ausdruck2> : <Ausdruck3>
Der Ausdruck1 wird bewertet ergibt dieser wahr, so ist der Wert des Ausdrucks
durch Ausdruck2 gegeben sonst durch Ausdruck3
Zuweisungsausdrücke
<lwert> = <Ausdruck>
Ein <lwert> ist ein Datenobjekt das modifiziert werden
darf. Die Auswertung erfolgt von rechts nach links.
Verkürzte Zuweisungen
*=
/=
Eine verkürzte Zuweisung der Form
%=
+=
<lwert> <op>= <Ausdruck>
-=
>>=
hat die Bedeutung
<<=
<lwert> = <lwert> <op> <Ausdruck>
&=
^=
|=
Grundlagen der Informatik
Folie 17
Programmentwicklung
#include <Standarbiliothek.h>
#include "Header.h"
int main () {
<Anweisungen>
return 0
}
C-Prog.
<name>.cpp
Präprozessor
Compiler
Binder
<name>.exe
Grundlagen der Informatik
Folie 18
C-Anweisungen
Ausdrucksanweisung
<Ausdruck>;
Ein Ausdruck gefolgt von einem Semikolon
Der Ausdruck kann leer sein
Blockanweisung
{ <Anweisung>... }
Ein Liste von Anweisungen in geschweiften
Klammern
Variablendeklaration
<typ> <Varname> [ = <Ausdruck>]{ , <Varname> [ = <Ausdruck>]};
Jede Variable muß vor ihrer ersten Verwendung deklariert sein.
Die Deklaration beginnt mit der Deklaration und endet mit dem Block, in dem
sie deklariert wurde.
Grundlagen der Informatik
Folie 19
if-Anweisung
<if-Anweisung> ::=if (<Ausdruck>)
<Anweisung(1)>
[else
<Anweisung(2)> ]
Bem.: Falls kein else-Teil vorhanden ist und
der Ausdruck sich zu falsch auswertet, so
wird keine Aktion durchgeführt. Beispiele:
Ausdruck
Anweisung(1)
Grundlagen der Informatik
Anweisung(2)
if (x < 0)
x = -x
* a;
else
x = x *
a;
if (x < 0) {
d =
1/x;
a = a +
d;
}
Folie 20
switch-Anweisung
<switch-Anweisung> ::=
switch (<Ausdruck>) {
case <Konstante> : { <Anweisung> }
{ case <Konstante> : { <Anweisung> }}
[ default : <Anweisung> { <Anweisung> }]
}
Zunächst wird der Ausdruck bewertet. Anschließend wird zu dem Fall verzweigt,
dessen Konstante gleich dem Wert des Ausdrucks ist.
Anschließend werden alle nachfolgenden Anweisungen ausgeführt.
Die Ausführung kann durch die Anweisung
break;
unterbrochen werden.
Ist keine Konstante gleich dem Wert des Ausdrucks wird zu default verzweigt.
Falls dieser nicht vorhanden ist, wird keine Anweisung ausgeführt.
Grundlagen der Informatik
Folie 21
k1
switch-Anweisung
Beispiel: Menü-Auswahl
char c;
printf_s("Bitte Aktion auswählen:");
printf_s("\t(1)\tSpeichern\n");
printf_s("\t(2)\tBeenden\n");
scanf_s("%c",&c);
switch ( c ) {
case '1' :
store();
break;
case '2' :
exitprog();
break;
default:
printf_s("Fehler: kein gültiger Menü-Punkt\");
}
Grundlagen der Informatik
Folie 21
k1
kraemer; 09.02.2016
Folie 22
while/do-Schleife
<while-Schleife> ::=
while (<Ausdruck>)
<Anweisung>
<do-Schleife> ::=
do {
<Anweisung>
} while (<Ausdruck>);
false
Ausdruck
Anweisung
true
Anweisung
Ausdruck
true
false
Grundlagen der Informatik
Folie 23
while/do-Schleife
Grundlagen der Informatik
Folie 24
for-Schleife
<for-Schleife> ::=
for ( <Init-Anweisung> <Ausdruck1> ; <Ausdruck2> )
<Anweisung>
hat die Bedeutung
<Init-Anweisung>
while (<Ausdruck1>) {
<Anweisung>
<Ausdruck2>;
}
Alle Schleifen können folgende Anweisungen enthalten
break;
die Schleife wird abgebrochen
continue;
die Iteration wird am Beginn der Schleife fortgesetzt
Grundlagen der Informatik
Folie 25
for-Schleife
Grundlagen der Informatik
Folie 26
Benutzerdefinierte Datentypen
Der Felddatentyp und Zeichenketten
Der Felddatentyp dient der Zusammenfassung gleicher Elemente
Die Deklaration einer Feldvariablen erfolgt durch
<typ> <Varname>[<ganzzahlige Konstante>][[<ganzzahlige Konstante>]];
Die Anzahl der eckigen Klammern ist die Dimension des Feldes (Array)
Felder mit einer variablen Anzahl von Elementen sind in ANSI-C nicht
zulässig.
Grundlagen der Informatik
Folie 27
Zeichenketten (strings)
Zeichenketten sind eindimensionale Felder des Typs char
Hierbei wird das Ende der Zeichenkette durch das Zeichen mit dem Wert 0
dargestellt ('\0'). Die Zeichenkette muß also um eins größer sein, als die
Anzahl der Buchstaben.
Beispiel
char Hello[13];
Hello = "Hello World\n";
Darstellung im Speicher
Hello
H e l l o
W o r l d \n \0
0 1 2 3 4 5 6 7 8 9 10 11 12
Grundlagen der Informatik
Folie 28
Allgemeine Felder
Felder lassen sich zu jedem Datentyp deklarieren
Beispiel
float Vector[10];
float Matrix[3][3];
Gleitkommawerten.
Ein Feld mit zehn Gleitkommawerten (0..9)
Ein zweidimensionales Feld mit 3 3
Darstellung im Speicher
Matrix
[0][0] [0][1] [0][2]
[1][0] [1][1] [1][2]
[2][0] [2][1] [2][2]
Grundlagen der Informatik
Folie 29
Allgemeine Felder
Zugriff auf Feldelemente
<Fname>[<ganzzahliger Ausdruck>]{[<ganzzahliger Ausdruck>]}
Hierbei dürfen höchstens so viele Indices angegeben werden, wie das Feld
Dimensionen hat (weniger sind zulässig)
Bsp.
float x, vector[10], matrix[10][10];
int i;
x = vector[5];
x = matrix[3][4];
vector = matrix[2]
matrix[i+7][i-2] = x;
In C/C++ ist der Programmier dafür verantwortlich, dass der Index-Wert im
zulässigen Bereich bleibt. Ein zu großer oder kleiner Wert führt zu einer sog.
Feldgrenzenüberschreitung. Das Ergebnis ist undefiniert.
Grundlagen der Informatik
Folie 30
Verbunddatentypen (struct, class)
Der Verbunddatentyp dient der Zusammenfassung verschiedener Datentypen
Deklaration eines Verbunddatentyps
struct <SBezeichner> {
{ <Element-Deklaration>; }
} [ <Verbund-Variable>];
<Element-Deklaration> ::=
<typ> <element> { , <element> } |
<Element-Funktion>
Zugriffsteuerung
public:
Die Elemente sind überall sichtbar und zugreifbar
private: Die Elemente sind nur in Elementfunktionen zugreifbar
protected:
Die Elemente sind abgeleiteten Klassen
sichtbar
Grundlagen der Informatik
Folie 31
Verbunddatentyp
Deklaration eines Verbunddatentyps
class <CBezeichner> {
{ <Element-Deklaration>; }
} [ <Verbund-Variable>];
Unterschiede
struct Adresse {
// standard public:
char NachName[20];
char VorName[20];
int PLZ;
char Ort[20];
char Strasse[30];
};
Grundlagen der Informatik
class Adresse {
public:
// standard private:
char NachName[20];
char VorName[20];
int PLZ;
char Ort[20];
char Strasse[30];
};
Folie 32
Verbunddatentyp
Der Zugriff auf ein Element eines Verbunddatentyps erfolgt durch den
Selektor-Operator .
Bsp. Einzelne Adresse
Adresse adr; // Deklaration
adr.NachName = "Krämer";
adr.VorName = "Heinrich";
Bsp. Adreßliste mit 10 Elementen
Adresse al[10];
al[2].VorName = "Fritz";
al[2].Nachname = "Kaiser";
Grundlagen der Informatik
Folie 33
Typdeklaration
Zwischen einer Struktur-(struct) bzw. Klassendeklaration(class) und einem
Feld besteht ein grundlegender Unterschied:
float vector[10];
struct verbund{float x1, float x2};
// Hierdurch wird eine Variable
// mit 10 Elementen angelegt
// hier wird nur ein Datentyp deklariert
// Eine Variable (Speicherbereich) muss
// gesondert deklariert werden durch
verbund v;
Manchmal kann es sinnvoll sein, auch Felder als wiederverwendbaren Datentyp zu
deklarieren hierzu dient das
typedef <typdeklaration>;
Bsp
typedef float matrix[10][10]; // Deklaration des Datentyps matrix
matrix A; // Variablendeklaration
Grundlagen der Informatik
Folie 34
Zeigertypen
Durch Zeiger kann dynamisch Speicher angelegt werden
Deklaration einer Zeigervariablen
<typ> *<Varname>;
Durch die Operatoren
new
wird neuer Speicher angelegt
delete wird angelegter Speicher gelöscht
Beachte: Dynamisch angelegter
Bsp.: Anlegen eines Strings
char *str;
str = new char[256];
Speicher bleibt erhalten
Löschen des Speichers
delete [] str;
// Beachte: Wird im Speicher ein Feld
// angelegt so ist mit [] zu löschen
Anlegen eines dynamischen Feldes
float *f;
f = new float[n] // n kann eine Variable sein
Grundlagen der Informatik
Folie 35
Zeigertypen
In C/ C++ werden eindimensionale Felder als Zeiger interpretiert
Der Inkrement / Dekrement-Operator dient zum Weiterschalten um ein Element
Folgenden Programme sind äqivalent
char ergstr[256], qstr[] = "Das ist eine StringInitialisierung";
for (int i = 0; ergstr[i] = qstr[i]; i++);
// Alternativ
for (char *p = ergstr, *q = qstr; *p++ = *q++;);
// Das folgende Programm ist FALSCH
for (;*ergstr++ = *qstr++;);
// Hierbei werden die Zeiger auf die Strings verändert
Grundlagen der Informatik
Folie 36
Sichtbarkeit von Deklarationen
• Jeder Bezeichner darf erst dann verwendet werden, wenn er vorher deklariert
wurde.
• In einer Umgebung darf ein Bezeichner nur einmal deklariert werden.
(Ausnahmen später)
• Eine Block-Anweisung (öffnende und schließende geschweifte Klammer) definiert
eine neue Umgebung
Sichtbarkeitsregeln
• Alle Deklarationen vor dem Hauptprogramm sind überall sichtbar.
(globale Deklarationen)
• Deklarationen sind nur in der Umgebung und den jeweiligen Unterumgebungen
sichtbar (lokale Deklarationen)
• Eine Neudeklaration des gleichen Bezeichners in einer untergeordneten
Umgebung ist zulässig. Diese überschreibt die Deklaration der äußeren
Umgebung. Damit wird die äußere Deklaration unsichtbar
Grundlagen der Informatik
Folie 37
Sichtbarkeit von Deklarationen
const int n;
typedef float[n] feld;
int main(…..) {
feld f;
int feld[5];
float z, x = 0.0;
{
float y, x = 1.0;
y = 5.0 * x;
}
z = x + 10.0;
}
Grundlagen der Informatik
Folie 38
Sichtbarkeit von Deklarationen
Konventionen
• Variablen sollten so lokal wie möglich deklariert werden
• Die Verwendung von globalen Variablen muss vermieden weden
Besonderheiten
int main(….) {
for (int i = 0; i < n; i++) {
// In C erfolgt die Deklaration in der umschließenden
// Umgebung in C++ innerhalb der for-Schleife
}
for (int i = 0; i < n; i++) {
// illegal in C
// notwendig in C++
}
}
Grundlagen der Informatik
Folie 39
Unterprogramme
Unterprogramme dienen
– zur Zusammenfassung von häufig benutzten Anweisungsfolgen
– zur Strukturierung von Programmen
Faustregel: Eine fortlaufende Programmsequenz sollte nicht länger als ein bis
zwei Bildschirmseiten lang sein (kein Spaghetticode) .
Grundlagen der Informatik
Folie 40
Unterprogramme
Definition von Funktionen
Eine Funktionsdefinition besteht aus einem Funktionskopf und einem
Funktionsrumpf
<Rückgabetyp> <FName>(<Parameterliste>)
//Kopf
{
//Rumpf
<Anweisungen>
}
Funktionen dürfen nur global d.h. vor der Funktion main definiert werden.
Die Parameterliste besteht aus beliebig vielen (auch keinem) Parametern.
Diese hat den Aufbau:
[<Datentyp> <Pname> { , <Datentyp> <Pname>} ]
Die Parameter bei der Definition werden als formale Parameter bezeichnet.
Grundlagen der Informatik
Folie 41
Unterprogramme
Bsp.
float Average(int x1, int x2, int x3)
{
float mean;
mean = (x1 + x2 + x3) / 3.0;
return mean;
}
Der Aufruf einer Funktion erfolgt durch die Angabe des Funktionsnamens und
gefolgt durch die aktuellen Parameter.
Hierbei muß beim Aufruf für jeden formalen Parameter ein entsprechender
aktueller Parameter mit einem entsprechenden Typ eingesetzt werden.
Bsp.:
int a = 1, b = 2;
float x = Average(a,3,b);
Grundlagen der Informatik
Folie 42
Unterprogramme
Teilweise ist es unnötig, daß eine Funktion einen Wert zurückliefert. (Prozedur)
Hierfür dient der "Datentyp" void, dieser bezeichnet keinen Rückgabewert
Die Anweisung return dient zum Verlassen der Funktion. Diese gibt es in zwei
Versionen:
return <Ausdruck>;
Diese Form ist bei Funktionen mit Rückgabewert anzugeben. Der Ausdruck
muß sich zu einem entsprechenden Datentyp auswerten. Hier muß bei jedem
Ausführungspfad mindestens eine return-Anweisung erreicht werden.
return;
Diese Form wird bei Funktionen ohne Rückgabewert (Prozeduren) benutzt.
Hier kann die return-Anweisung entfallen. Es wird automatisch am Ende des
Rumpfes zurückgesprungen
Grundlagen der Informatik
Folie 43
Parameterersetzungen
Wertparameter
Diese Parameter behalten den Wert nach dem Aufruf der Funktion bei, den
sie vor dem Aufruf hatten. Änderungen innerhalb der Funktion haben nach
außen also keine Wirkung. Standardmäßig sind alle Parameter in C
Wertparameter.
Referenzparameter
Bei diesen Parametern wird nur ein Zeiger auf die entsprechende
Speicherstelle übergeben. Änderungen innerhalb der Funktion wirken sich
auf die Parameter aus. In C++ können Referenzparameter durch den
Referenzoperator & deklariert werden.
Bsp.:
float RefParBsp(int &a)
{
a = 10 * a;
return a/5.0;
}
Grundlagen der Informatik
Folie 44
Sichtbarkeit und Parameterersetzungen
int fctA(int a) {
int n
}
int fctB(int a) {
int n;
n = fctA(n)
}
int main(int argv, char *argc[]) {
int m,
int n;
n = fctA(m);
m = fctB(n);
n = fctA(100)
}
Grundlagen der Informatik
fctA
global
a
Param. (lokal)
n
lokal
fctB
global
a
Param. (lokal)
n
lokal
main
global
argv
Param. (lokal)
argc
Param. (lokal)
n
lokal
m
lokal
Folie 45
Sichtbarkeit und Parameterersetzungen
int fctARef(int &a) {
int n
}
int fctBRef(int &a) {
int n;
n = fctA(n)
}
int main(char *argv[], int argc) {
int m,
int n;
n = fctARef(m);
m = fctBRef(n);
n = fctARef(100); // illegal
}
Grundlagen der Informatik
fctARef
global
a
Param. (lokal)
n
lokal
fctBRef
global
a
Param. (lokal)
n
lokal
main
global
argv
Param. (lokal)
argc
Param. (lokal)
n
lokal
m
lokal
Folie 46
Überladen von Funktionen
In C++ ist es zulässig mehreren Funktionen den gleichen Namen zu geben.
Allerdings müssen sich zwei gleichnamige Funktionen in mindestes einem Datentyp in
der Parameterliste oder der Anzahl unterscheiden.
Diese Eigenschaft wird als überladen von Funktionen bezeichnet
Es ist nicht zulässig, dass sich zwei Funktionen nur im Rückgabewert unterscheiden
Bsp.:
float max(float A[], int n);
int Summe(float A[]);
float max(float a, float b);
float Summe(float A[]); // falsch
Operatoren wie +, -, * werden wie Funktionen behandelt z. B.
long operator+(const long a, const long b);// entspricht der ganzzahligen
Addition
Alle Standardoperatoren können überladen werden (nur C++)
Grundlagen der Informatik
Folie 47
Überladen von Operatoren
Beispiel: Multiplikation Skalar mit Vektor
struct vector {
float elems[n];
}
vector operator*(float a, const &vector x) {
vector h;
for(int i = 0; i < n; i++) {
h.elems[i] = a * x.elems[i];
}
return h;
}
vector a, b;
float c;
b = c * a; // Es wird obiger Operator eingesetzt
b = a * c; // illegal
Grundlagen der Informatik
Folie 48
Rekursive Programme
Funktionen können andere Funktionen die bereits deklariert sind aufrufen.
Insbesondere können Funktionen auch sich selbst aufrufen. Diese wird als
rekursiver Aufruf bezeichnet.
Bsp: Berechnung der Fakultät n! = 1 2 .... n (Beachte 0! := 1)
int Fakult(int n)
{
if (n < 0) return -1; // Fehler;
if (n == 0) return 1;
return Fakult(n-1)*n;
}
Grundlagen der Informatik
Folie 49
Funktionsdeklaration und Module
Da sich Funktionen gegenseitig aufrufen können, muß es möglich sein, diese
Bekannt zu machen ohne ihren Rumpf anzugeben. Man sprich von einer
Funktionsdeklaration. Diese hat die Form:
<Rückgabetyp> <FName>(<Parameterliste>);
Bsp.
void A()
{
B(); //illegal
}
void B()
{
A();//illegal
}
void B();
void A()
{
B();
}
void B()
{
A();
}
void A()
{
B();
}
void B()
{
A();
}
Grundlagen der Informatik
Folie 50
Funktionsdeklaration und Module
Große Programme werden meist in sogenannte Module zerlegt. Jedes Modul
realisiert eine bestimmte Teilaufgabe Hierbei werden von einem Modul
bestimmte benutzerdefinierte Datentypen und Funktionen bereitgestellt.
Alle Datentypen und Funktionen des Moduls werden zunächst in einer Art
Schnittstelle deklariert. Diese Datei erhält den Namen <Modul>.h (Header-File)
Die Definition der Funktionen und eventuell zusätzliche Hilfsfunktionen erfolgt in
der Datei <Modul>.cpp (Implementierung)
Hierdurch ist es möglich, jedes einzelne Modul getrennt zu übersetzen. Vom
Compiler wird hierdurch eine Objektdatei <Modul>.obj erzeugt.
Alle Module müssen dann zu einem Gesamtprogramm gebunden werden
(Linker)
Grundlagen der Informatik
Folie 51
Funktionsdeklaration und Module
Verhindert ein
matrix.h #ifndef MATRIX_H
mehrfaches
#define MATRIX_H
Einkopieren
const int n;
typedef float Matrix[n][n];
Einkopieren
Hauptprogramm (.cpp)
void ReadM(Matrix X);
void PrintM(Matrix X);
#include "matrix.h"
Matrix MultM(X, Y);
int main (int argc,
#endif
char **argv)
matrix.cpp #include "matrix.h"
{
Matrix A,B,C;
void ReadM(Matrix X)
{
ReadM(A);
// Code zum Einlesen
}
ReadM(B)
void PrintM(Matrix X)
{
C = MultM(A,B)
// Code zun Ausgeben
}
PrintM(C);
Matrix MultM(Matrix X, Matrix Y)
return 0;
{
// Code zur Multiplikation
}
}
Bsp.
Grundlagen der Informatik
Folie 52
Arbeiten mit Dateien
Das FILE-Konzept (benötigte Header-Datei stdio.h)
Der vordefinierte Datentyp: FILE * ist ein Zeiger auf eine Dateistruktur.
Dateivariable
FILE* f
Verbindung zwischen Dateivariable und Betriebssystem-Datei
Absoluter Pfad
f = fopen("C:\\MeinOrdner\\MeineDatei.dat","r+")
Relativer Pfad
f = fopen("MeineDatei.dat","r+")
C:
MeinOrdner
Modus
r
w
a
+
MeineDatei.dat
zum Lesen; die Datei muß vorhanden sein
zum Schreiben, der Inhalt wird gelöscht
Datei wird zum Schreiben geöffnet; neue Daten werden angehängt
Datei wird zum Lesen und Schreiben geöffnet
Grundlagen der Informatik
Folie 53
Arbeiten mit Dateien
Vordefinierte Dateivariablen
stdin Standardeinegabe (z. B. Tastatur)
stdout Standardausgabe (z. B. Bildschirm)
stderr Standardausgabe für Fehlermeldungen (z. B Bildschirm)
Operationen auf Dateien
Lesen
int fscanf(FILE *f, char *Format-String, <Argumente>)
Es wird die Anzahl der umgewandelten Felder zurückgegeben. Am Dateiende
wird EOF zurückgegegben
int getc(FILE *f)
Liest von der Datei ein Zeichen ein. Der Code
des Zeichens wird zurückgegeben.
fseek(FILE *f, long offset, int origin)
Positionieren des
Dateizeigers
origin: seek_cur, seek_set, seek_end
Grundlagen der Informatik
Folie 54
Arbeiten mit Dateien
Schreiben
int fprintf(FILE * f, char* Format-String,<Argumente>)
Schreibt den Format-String in die Ausgabedatei f
für jede Format-Anweisung wird eine Argument benötigt
int putc(int c, FILE * f)
Es wird eine Zeichen in die Datei f geschrieben
Prinzip:
Dateizeiger
l l
o
1 2 . 3 4
EOF
H a
Zur Leistungssteigerung wird nicht auf den Dateien direkt sondern über
sogenannte Puffer gearbeitet. Puffer sind Bereiche im Hauptspeicher, die eine
bestimme Menge von Bytes aufnehmen können. Zur Leerung der Puffer dient
die Funktion:
int fflush(FILE *f)
Grundlagen der Informatik
Folie 55
Arbeiten mit Dateien
Das Stream-Konzept
Benötigte Header-Datei
<iostream.h> stream-Klassen
<iomanip.h> Formatierung
Streams sind Ströme von Bytes. Die Daten können zwischen Programmen oder
Peripherie-Geräten ausgetauscht werden. Je nach Anwendungsfall wird eine
geeignete Klasse verwendet.
Vordefinierte streams
cin
Standardeingabe (entspricht stdin)
cout
Standardausgabe (entspricht stdout)
cerr
Fehlerausgabe (entspricht stderr)
Grundlagen der Informatik
Folie 56
Arbeiten mit Dateien
Lesen von streams
>> der Extraktionsoperator
Bsp.:
int n;
cin >> n;
Schreiben in streams
<< der Schreiboperator
Bsp.:
int n = 5;
cout << "n = " << n << endl;
// gibt n = 5 aus
Grundlagen der Informatik
Folie 57
Arbeiten mit Dateien
Öffnen und Schließen einer Eingabedatei als Stream
istream ein(""C:\\MeinOrdner\\MeineDatei.dat"); //Öffnen
oder
istream ein;
ein.open("MeineDatei.dat")
ein.close(); // Schließen
Öffnen und Schließen einer Ausgabedatei als Stream
ostream aus(""C:\\MeinOrdner\\MeineDatei.dat"); //Öffnen
oder
ostream aus;
aus.open("MeineDatei.dat")
aus.close(); // Schließen
Grundlagen der Informatik
Folie 58
Sortieren von Feldern
Es soll ein Algorithmus entwickelt werden, der ganzzahlige Feldelemente
eines Feldes F in aufsteigend sortiert.
Es soll also gelten F[i] F[k] für i < k (eigentlich nicht fallend)
RippleSort
Vorgehensweise: (Datenstruktur int F[n])
1.Schritt: Suche kleinstes Element in der Folge von i = 0 bis n-1
int min = i;
for (int k = i; k < n; k++)
if (F[k] < F[min]) min = k;
2. Schritt: Vertausche i-tes Element mit dem Kleinsten
int h = F[i]; F[i] = F[min]; F[min] = h;
3. Schritt: Wiederhole Schritte 1 bis 3 mit i = i + 1 solange i < n-1
Grundlagen der Informatik
Folie 59
Sortieren von Feldern
void RippleSort(int F[n])
{
for (int i = 0; i < n-1; i++) {
int min = i;
for (int k = i+1; k < n; k++)
if (F[k] < F[min]) min = k;
int h = F[i]; F[i] = F[min]; F[min] = h;
}
}
Grundlagen der Informatik
Variable
n
i
k
min
F[0]
F[1]
F[2]
F[3]
h
Wert
4
undef.
2
1
0
undef.
1
2
3
4
undef.
0
3
1
2
10
3
5
10
3
8
10
8
undef.
10
5
Folie 60
Sortieren von Feldern
Handelt es sich um beliebige Felder so kann in C++ ein geeigneter < Operator
definiert werden. (In C++ lassen sich alle Standardoperatoren für beliebige
Datentypen definieren (Overloading))
Bsp. Namesliste
struct Name {
CString NName;
CString Vorname;
CSstring Strasse;
}
Sortierkriterien A1 < A2 (kommt vor)
1. A1.NName kommt alphabetisch vor A2.NName
2. Bei Namesgleichheit
A1.Vorname kommt alphabetisch vor A2.Vorname
3. Sind beide Namen gleich
werden die Strassen alphabetisch verglichen
4. Sind alle Einträge gleich ist das Ergebnis falsch
Grundlagen der Informatik
Folie 61
Sortieren von Feldern
Beispiel für die Deklaration eines Operators
//benötigte include Datei
#include <string.h>
bool operator<(const Name &N1, const Name &N2)
{
int c;
if (c = strcmp(N1.NName,N2.NName)) return (c<0)?true:false;
if (c = strcmp(N1.VName,N2.VName)) return (c<0)?true:false;
if (c = strcmp(N1.Strasse,N2.Strasse)) return (c<0)?true:false;
return false;
}
Grundlagen der Informatik
Folie 62
Ein weiterer Sortieralgorithmus
MergeSort
1. Schritt Aufteilen
Teile etwa in der Mitte
Anstatt den gesamten Vektor zu sortieren wird das Problem dadurch reduziert,
dass zweimal ein jeweils nur halb so großer Vektor sortiert wird.
Das Aufteilen wird solange fortgesetzt bis der Vektor nur noch ein Element
enthält. Dieses ist natürlich "sortiert"
Grundlagen der Informatik
Folie 63
Ein weiterer Sortieralgorithmus
2. Schritt Zusammenfügen
zwei sortierte Vektoren
<
Grundlagen der Informatik
Vergleiche die beiden ersten Elemente und
füge das Kleinere in den Ergebnisvektor ein.
Fahre mit dem jeweils nächsten fort.
Folie 64
MergeSort
void MergeSort(int Ein[], int Aus[], int left, int right) {
int diff = right - left;
if (diff > 0) {
MergeSort(Ein,Aus,left,left+diff/2);
MergeSort(Ein,Aus,left+diff/2+1,right);
int p = left, q = left, r = left+diff/2+1;
do{
if(Aus[q] < Aus[r])
Ein[p++] = Aus[q++];
else
Ein[p++] = Aus[r++];
} while((q <= left+diff/2) && (r <= right));
for( ; q <= left+diff/2; )
Ein[p++] = Aus[q++];
for( ; r <= right; )
Ein[p++] = Aus[r++];
}
for(int i = left; i <= right; i++)
Aus[i] = Ein[i];
Grundlagen der Informatik
}
Folie 65
Laufzeitvergleich
0,50000000
0,45000000
0,40000000
0,35000000
0,30000000
RippleSort
MergeSort
0,25000000
0,20000000
0,15000000
0,10000000
0,05000000
0,00000000
0
Grundlagen der Informatik
2000
4000
6000
8000
10000
12000
Folie 66
Laufzeitabschätzung
void RippleSort(int F[n])
{
S0 Zuweisungen
for (int i = 0; i < n-1; i++) {
S1 Vergleich, fünf Zuweisungen,
Inkrement
int min = i;
for (int k = i+1; k < n; k++)
S2 zwei Vergleiche, Inkrement
if (F[k] < F[min])
Zuweisung
z
min = k;
int h = F[i]; F[i] = F[min]; F[min] = h;
}
}
Problem: Die Zuweisung in der if-Anweisung wird nicht immer ausgeführt:
1. Schlimmster Fall (worst case): Die Zuweisung wird immer ausgeführt (WCET)
2. Bester Fall (best case): Die Zuweisung wird nie ausgeführt
3. Es wird nach der Wahrscheinlichkeit der Ausführung eine Mittelwert berechnet
τ WCET = τ S 0 + n ⋅ (τ S1 + n ⋅ (τ S 2 + τ Z ) ) = (τ S 2 + τ Z ) ⋅ n 2 + τ S1 ⋅ n + τ S 0
Grundlagen der Informatik
Folie 67
Laufzeitabschätzung
MergeSort
Stufen durch die Zerlegung der Eingabefolge
In jeder Stufe befinden sich n Elemente
Die folgende Berechnung ist nur eine grobe
Schätzung
In jeder Stufe erfolgen maximal n Vergleiche und 2 n Kopieroperationen
Wir können somit den Aufwand für eine Stufe mit n S abschätzen
Es gibt insgesamt ld(n) Stufen.
In jeder Stufe sollen ein weiterer Aufwand von
C
entstehen
τ WCET = ld (n ) ⋅ (τ C + n ⋅ τ S ) = ld (n ) ⋅ τ C + n ⋅ ld (n ) ⋅ τ S
Grundlagen der Informatik
Folie 68
Der O-Kalkül (Groß-O-Kalkül)
Für ein Programm ist der Rechenzeitaufwand für große Eingaben interessant.
Man spricht hier auch vom asymptotischen Verhalten.
Gegeben zwei Funktionen f(n) und g(n)
f(n) = O(g(n)), falls es ein n0 und ein C gibt mit n > n0 : f(n) < C g(n)
Bsp. f(n) = n2 + 10, g(n) = n3 für n > 3 gilt f(n) < g(n)
Rechenregeln
f(n) + C = O(f(n)) (f(n) Nullfkt.)
C f(n) = O(f(n))
am nm a(m-1) n(m-1) +…+a0 = O(nm)
Ist der Rechenzeitaufwand für ein Programm O(nm) so nennt man es polynomial
beschränkt.
Grundlagen der Informatik
Folie 69
Ein schwieriges Problem
Rucksackproblem
Gegeben: eine Menge D = {di | i = 1..n } von Dingen. Jedem di wird ein Volumen
V(di) und eine Nützlichkeit N(di) zugeordnet. Weiter gibt es einen Rucksack mit
einem maximalen Volumen Vmax.
Gesucht: Eine Auswahl A von Dingen, so dass diese in den Rucksack passen und
insgesamt die Nützlichkeit maximiert wird, oder formal
A⊆D:
∑ V (d ) ≤ V
di ∈A
i
max
!
und
∑ N ( d ) = max
di ∈A
i
mögliche Lösung:
1. Bestimme alle Teilmengen A von D
2. Prüfe, ob für eine gegebene Auswahl A das Volumen nicht überschritten wurde.
3. Berechne für jede gültige Auswahl die Nützlichkeit und wähle diejenige mit dem
höchsten Wert
Problem: es gibt 2n Teilmengen
Grundlagen der Informatik
Folie 70
Laufzeituntersuchungen
Eine Basisoperation dauert 1 ns = 10-9s
n
n ld(n)
n2
n3
2n
10 3,32193E-08
0,0000001 0,000001
0,000001024
20 8,64386E-08
0,0000004 0,000008
0,001048576
40 2,12877E-07
0,0000016 0,000064
1099,511628
80 5,05754E-07
0,0000064 0,000512 1,20893E+15 ca 920 Mio Jahre
160 1,17151E-06
0,0000256 0,004096
1,4615E+39
320 2,66302E-06
0,0001024 0,032768 2,13599E+87
640 5,96603E-06
0,0004096 0,262144 4,5624E+183
Algorithmen gelten als effizient, falls sie polynomial beschränkt sind. In der Praxis
O(n2) ausnahmsweise O(n3) .
Grundlagen der Informatik
Folie 71
NP-harte Probleme
Bei einigen Problemen sind für (deterministische) Rechner nur Algorithmen mit
exponentieller Laufzeit bekannt. Es handelt hierbei um so genannte NP-harte
Probleme. Beispiele
Rucksackproblem
Travelling Salesman
Suche nach einer optimalen Route bei einer Rundreise
Steiner-Baum-Problem
kürzeste Verdrahtung von mehreren Punkten
Scheduling
Belegungsplanung von Maschinen / Ablaufplanung
Graphen-Probleme
Bei diesen Problemen kann von einem Rechner eine optimale Lösung meist nur
angenähert werden.
Grundlagen der Informatik
Folie 72
Laufzeitoptimierungen
Ein Programm sollte möglichst kurze Laufzeiten haben:
– Optimierung des Algorithmus
Grundsätzlich sollte zunächst für ein gegebenes Problem ein möchlichst
effizienter Algorithmus verwendet werden mit O(nk), wobei k so klein als möglich
zu wählen ist. Eventuell kann es auch nützlich sein den mittleren Aufwand
abzuschätzen und gegebenenfalls zu optimieren
– Feinoptimierung
Es gilt üblicherweise die Regel, dass 80 – 90 % der Laufzeit in 10 -20 % der
Codezeilen verbraucht wird. Durch Analyse des Programms (Profiling) sollten
diese Stellen untersucht und falls möglich verbessert werden durch
• Umformulierung der Anweisungen
• Beachtung der Rechnerarchitektur (interne Parallelität, Cache)
• Verwendung von Assembler?
Durch Feinoptimierung kann die Laufzeit nur um einen konstanten Faktor
reduziert werden.
Grundlagen der Informatik
Folie 73
Einige Aspekte der Sotwaretechnik
Gütekriterien für Programme
– Wartbarkeit
Programme sollten so geschrieben werden, dass nachträglich (auch von
anderen Personen) Änderungen und Anpassungen leicht durchführbar sind.
– Portabilität
Programme sollten möglichst ohne Änderung auf verschiedenen Plattformen
lauffähig sein. Auch bei höheren Programmiersprachen ist diese Eigenschaft
durch einen geeigneten Programmierstiel sicherzustellen.
– Fehlerfreiheit
Das Programm muss durch ausreichende Tests validiert werden. Allerdings
kann durch Test nur die Anwesenheit von Fehlern erkannt werden, nicht die
Fehlerfreiheit.
Verfikation.
Es gilt die Regel, dass für den Test die gleiche Zeit wie für Codierung
einzuplanen ist.
Grundlagen der Informatik
Folie 74
Softwareentwicklung
Tätigkeiten
Problemanalyse
Dokumente
Pflichtenheft
Leistungsmerkmale
Testspezifikation
Systementwurf
Modularisierung
Codierung
Test
Modultest
Integrationstest
Abnahme
Grundlagen der Informatik
Modulbeschreibungen
Modultestspezifikation
Programmdokumentation
Testdokumentation
Folie 75
Softwareentwicklung
Prototypentwicklung
Grundlagen der Informatik
Folie 76
Aufgabe 1
Erstellen Sie ein C-Programm, das zwei Matrizen A und B einliest und die Matrix
C = A B ausgibt.
Die Matrizenmultiplikation von zwei n n Matrizen ist definiert als
n
ci, j = ∑ ai,k ⋅ bk,j
k =1
Das Programm soll für beliebiges n gelten.
Verwenden Sie zu Testzwecken die Deklarationen
const int n = 2;
float A[n][n], B[n][n], C[n][n];
Die Ein/Ausgabe von Gleitkommawerten wird in der Übung behandelt. Diese
gestalten sich ähnlich wie Festkommawerte.
Grundlagen der Informatik
Aufgabe 1
Entwickeln Sie einen Algorithmus für folgendes Problem:
Gegeben ist die Funktion y(t) = exp(- t) sin( t)
Die Funktion soll als Diagramm durch das Ausdrucken von ‚*‘ ausgegeben
werden
Hierbei liegt die y-Achse horizontal, die t-Achse vertikal.
Aufgabe 2
Erstellen Sie ein C-Programm, das eine Tabelle aus 18 Fußballvereinen
einlesen kann. Ein Verein wird durch die Daten
Vereinsname (max. 256 Zeichen),
Punkte
geschossene Tore
erhaltene Tore
beschrieben. Die eingelesenen Daten sollen als formatiert Ausgegeben werden.
Hinweis: Erstellen Sie einen Verbunddatentyp für die Vereinsdaten. Die Tabelle
kann dann als Feld von Vereinsdaten dargestellt werden.
Das Einlesen eines Strings mit der Deklaration
char str[256]; // Deklaration
erfolgt durch
scanf("%s",str); // Platzhalter %s Beachte KEIN & vor der Variable
Aufgabe 4
Erstellen Sie ein C-Programm, das eine Tabelle aus 18 Fußballvereinen sortiert.
Ein Verein wird durch den Namen, die Punkte, die Anzahl der geschossenen
Tore sowie die Anzahl der erhaltenen Tore charakterisiert.
Ein Verein V1 soll vor einem Verein V2 in der Tabelle stehen falls
1. V1 mehr Punkte als V2 hat.
2. Bei gleicher Punktzahl, falls V1 eine größere Tordifferenz als V2 hat.
Die Tordifferenz ist die Differenz aus geschossenen minus erhaltenen Toren.
3. Bei gleicher Tordifferenz, falls V1 mehr geschossene Tore als V2 hat.
4. Sind alle vorherigen Werte gleich so steht der alphabetisch kleinere vorn.
(Identische Einträge sollen ausgeschlossen sein)
Hinweis: die Funktion int strcmp(const char* s1, const char* s2) liefert
-1 falls s1 alphabetisch vor s2 kommt
0 bei Gleichheit
+1 falls s1 alphabetisch nach s2 kommt
Header-Datei <string.h>
Aufgabe 5
Verändern Sie das Programm aus Aufgabe 4 so, daß die Daten für die
Fußballtabelle aus der Datei "Liga.dat" eingelesen werden.
Hierbei besteht die Eingabe aus 18 Zeilen, d. h. eine Zeile pro Verein
Jede Zeile hat den Aufbau
<Name des Vereins> ; <Punkte> ; <Gesch. Tore> ; <Erhalt. Tore> \n
Herunterladen