Programmieren in C Eigene . Dr. Nikolaus Wulff Programmieren in C 2 C Datentypen • Variablen in C sind immer von einem bestimmten Datentyp, z. B. int, float, char, etc

  • Published on
    06-Feb-2018

  • View
    216

  • Download
    2

Embed Size (px)

Transcript

<ul><li><p>Prof. Dr. Nikolaus Wulff</p><p>Programmieren in CProgrammieren in C</p><p>Eigene Datentypen per typedef und Strukturen </p></li><li><p>Prof. Dr. Nikolaus Wulff Programmieren in C 2</p><p>C Datentypen</p><p> Variablen in C sind immer von einem bestimmten Datentyp, z. B. int, float, char, etc. </p><p> Zustzlich definiert die Sprache Operationen die mit den Datentypen erlaubt sind, +,*, etc. </p><p> Diese Typen sind eng angelegt an die Mglichkeiten einer CPU und den primitiven mathematischen Operationen, die damit mglich sind. </p><p> Fr fachliche Anwendungen ist es wnschenswert eigene Datentypen zu verwenden, wie z.B. einen Geldbetrag, ein Datum, eine Farbe, etc.</p></li><li><p>Prof. Dr. Nikolaus Wulff Programmieren in C 3</p><p>Eigene Datentypen</p><p> C kennt verschiedene Mechanismen, um eigene Datentypen zu definieren.</p><p> Diese Typen knnen dann mit sprechenden Typnamen versehen sein.</p><p> Dies ermglicht es sprachlich nher an der Semantik des Problembereichs zu bleiben.</p><p> Dies erleichtert die Lesbarkeit und kann auch verwendet werden, um Programme leichter zwischen verschiedenen Maschinenarchitekturen zu portieren.</p></li><li><p>Prof. Dr. Nikolaus Wulff Programmieren in C 4</p><p>Aufzhlungstypen</p><p> Das Konzept von Aufzhlungen (eng. Enumeration) kommt derart hufig vor, das C hierfr eine eigene Anweisung besitzt, um einen Aufzhlungstypen fr Konstanten zu definieren.</p><p> Statt vieler Konstanten per #define wird die enum Anweisung verwendet, um einen ganzen Satz von Konstanten zu definieren.</p><p>enum { value1,...,valueN};</p></li><li><p>Prof. Dr. Nikolaus Wulff Programmieren in C 5</p><p>Boolean per enum</p><p> C kennt keinen Booleschen Datentyp, daher werden die Variablen TRUE und FALSE hufig per #define Anweisung definiert:</p><p> Sauberer geht es per enum:</p><p> Die Voreinstellung ist, dass der erste Bezeichner (hier false) mit 0 belegt wird und dann wird jeweils um eins inkrementiert.</p><p>#define FALSE 0#define TRUE 1</p><p>enum Boolean { false, true};</p></li><li><p>Prof. Dr. Nikolaus Wulff Programmieren in C 6</p><p>Wochentage</p><p> Wir wollen ein Programm Kalender zur Bearbeitung von Wochentagen entwickeln. </p><p> Die Header Datei Kalender.h knnte so aus sehen:</p><p>#define MONDAY 1#define TUESDAY 2#define WEDNESDAY 3#define THURSDAY 4#define FRIDAY 5#define SATURDAY 6#define SUNDAY 7</p><p>void printDay(int day);</p></li><li><p>Prof. Dr. Nikolaus Wulff Programmieren in C 7</p><p>Aufzhlungstypen</p><p> Statt vieler Konstanten per #define wird die enum Anweisung verwendet.</p><p> Damit die Zhlung nicht mit monday bei 0 beginnt, kann explizit der erste Wert belegt werden.</p><p> Der enum Typ Day kann sogar als Parametertyp in der Methode printDay deklariert werden.</p><p>enum Day { monday=1, tuesday, wednesday, thursday, friday, saturday, </p><p> sunday};</p><p>void printDay(enum Day day);</p></li><li><p>Prof. Dr. Nikolaus Wulff Programmieren in C 8</p><p>Verwendung von enum</p><p> Die Methode printDay kann nun mit den Konstanten des Aufzhlungstypen Day gerufen werden:</p><p> aber auch ein Aufruf mit int funktioniert:</p><p> Intern wird enum immer als eine Konstante vom Typ int reprsentiert.</p><p> Leider kann auch Unsinn bergeben werden:</p><p> Merke: Wir kmmern uns um die Namen, der Compiler um die Werte...</p><p>printDay(tuesday);</p><p>printDay(2);</p><p>printDay(-20);</p></li><li><p>Prof. Dr. Nikolaus Wulff Programmieren in C 9</p><p>Enum sind intern Integers</p><p> Fr solche Flle muss eine Mglichkeit der Fehlerbehandlung vorgesehen werden...</p><p>void printDay(enum Day day) { switch(day) { case monday: case tuesday: case wednesday: case thursday: case friday: printf("Go to work\n"); break; case saturday: case sunday: printf("Sleep well it's weekend\n"); break; default: printf("Unknown day %d\n", day); handleError(); };}</p></li><li><p>Prof. Dr. Nikolaus Wulff Programmieren in C 10</p><p>Enum Konstanten vorbelegen</p><p> Die enum Konstanten knnen beliebig vergeben werden auch mit negativen Werten:</p><p> Es lassen sich mehrere Bezeichner mit dem selben Wert belegen:</p><p>enum example { a, b, c, d, e=-2, f, g, h i=-3, j, k, l, m, ...};</p><p>Wert Name-3 i-2 e j-1 f k 0 a g l 1 b h m 2 c 3 d</p></li><li><p>Prof. Dr. Nikolaus Wulff Programmieren in C 11</p><p>Alias per typdef</p><p> Whrend enums immer Konstanten vom Typ int sind gibt es mit dem typedef Konstrukt eine Mglichkeit ein Alias fr einen schon existierenden beliebigen Typ zu vergeben:</p><p> So kann z.B. das Konstrukt char* mit einer Zeichenkette als String identifiziert werden:</p><p> s ist immer noch eine Variable vom Typ char*!</p><p>typedef ;</p><p>typedef char* String;</p><p>String s = "Hallo";</p></li><li><p>Prof. Dr. Nikolaus Wulff Programmieren in C 12</p><p>Anwendungen von typedef</p><p> Ein paar Beispiele zur Anwendung von typedef:</p><p> Die Bedeutung des Codes erschliet sich mit den Typen Alter und Geld wesentlich leichter, als wenn dort mit unsigned short gearbeitet worden wre.</p><p> Sollte die Genauigkeit von float nicht ausreichen, gengt es den typedef auf double zu ndern und an allen Stellen, wo Geld vorkommt wird mit double gerechnet ...</p><p>typedef float Geld;typedef unsigned short Alter;</p><p>Alter volljaehrig = 18;Geld gehalt = 4711.00;</p></li><li><p>Prof. Dr. Nikolaus Wulff Programmieren in C 13</p><p>typedef und enum</p><p> Etwas unschn beim Day Beispiel war es berall in den Methodensignaturen enum mit einzufgen:</p><p> Wesentlich eleganter geht es mit typedef :</p><p> oder in einem Rutsch:</p><p>enum Day { monday=1, tuesday, ...};</p><p>void printDay(enum Day day);</p><p>enum day_enum { monday=1, tuesday,...};typedef enum day_enum Day;</p><p>void printDay(Day day);</p><p>typedef enum { monday=1, tuesday,...} Day;</p></li><li><p>Prof. Dr. Nikolaus Wulff Programmieren in C 14</p><p>Ein altes Beispiel ...</p><p>/** two constants for f2c and c2f calculus */#define SHIFT 32.0#define SCALE (9.0/5.0)</p><p>/** calulate celsius as fct of fahrenheit */double f2c(double f) { double c = (f - SHIFT)/SCALE; return c;}/** calulate fahrenheit as fct of celsius */double c2f(double c) { double f = c*SCALE + SHIFT; return f;}</p><p> Da msste sich doch mit typedef etwas machen lassen ...</p></li><li><p>Prof. Dr. Nikolaus Wulff Programmieren in C 15</p><p>Nochmal Celsius zu Fahrenheit</p><p> So wird der Code sprechend ...</p><p>/** two constants for f2c and c2f calculus */#define SHIFT 32.0#define SCALE (9.0/5.0)</p><p>typedef double Celsius;typedef double Fahrenheit;</p><p>/** calulate celsius as fct of fahrenheit */Celsius f2c(Fahrenheit f) { Celsius c = (f - SHIFT)/SCALE; return c;}/** calulate fahrenheit as fct of celsius */Fahrenheit c2f(Celsius c) { Fahrenheit f = c*SCALE + SHIFT; return f;}</p></li><li><p>Prof. Dr. Nikolaus Wulff Programmieren in C 16</p><p>C Datentypen Die bis lang vorgestellten Konstrukte, enum und </p><p>typedef, erfllen noch nicht die Anforderung an selbst definierten Datentypen.</p><p> enum definiert Aufzhlungen von int Konstanten. typedefs sind lediglich alias Bezeichner fr bereits </p><p>existierende Datentypen. Keines der beiden Konstrukte liefert wirklich einen </p><p>neuen Datentyp.</p></li><li><p>Prof. Dr. Nikolaus Wulff Programmieren in C 17</p><p>Do it yourself... Wir mchten den Datentyp Farbe (Color) </p><p>implementieren. Color soll die drei Werte (r,g,b) als Triple, jeweils </p><p>im Bereich 0</p></li><li><p>Prof. Dr. Nikolaus Wulff Programmieren in C 18</p><p>Farbe als Ganzzahl modelliert Ein int mit 4 Byte (ansonsten typedef mit long) </p><p>bietet genug Platz, um 3 Byte rgb-Werte abzulegen, mit entsprechenden Bit und Shift Operationen...</p><p> Die get-Methoden lesen mit entsprechenden Masken und shift Operationen die rgb-Werte.</p><p>typedef int Color;</p><p>#define R_MASK 0x00FF0000#define G_MASK 0x0000FF00#define B_MASK 0x000000FF</p><p>#define getR(C) ( ((C) &amp; R_MASK)&gt;&gt;16 )#define getG(C) ( ((C) &amp; G_MASK)&gt;&gt;8 )#define getB(C) ( ((C) &amp; B_MASK) )</p><p>Bits: 0| 1| ... |7|8| ... |15|16| ... |23|24| ... |32</p></li><li><p>Prof. Dr. Nikolaus Wulff Programmieren in C 19</p><p>Farbe als Ganzzahl setzen Ein Farb-Byte gezielt innerhalb des 4 Byte Color int </p><p>zu setzten erfordert schon mehr Operationen:</p><p> Zunchst werden die Bits der zu setzenden Farbe gelscht, ohne die beiden anderen Farben zu lschen.</p><p> Anschlieend wird mit oder der neue Wert gesetzt. Diese Bytefolge ergibt sich aus einer Shift-Operation </p><p>des Farbwertes und anschlieender Maskierung.</p><p>#define setR(C,x) ( (C) = \ ((C) &amp; ~R_MASK)|(((x)</p></li><li><p>Prof. Dr. Nikolaus Wulff Programmieren in C 20</p><p>Ganzzahl Variante Durch die Macros lassen sich per get/setX die Bit </p><p>und Shift-Operationen verstecken und in eine Color.h Datei auslagern.</p><p> Ein Nachteil ist, dass fr jeden getX/setX Befehl Berechnungen durchgefhrt werden mssen. </p><p> Eine Zuweisung per = Operanden funktioniert nicht, es ist immer ein setX Befehl notwendig. </p><p> Color color; setR(color,238); setG(color,124); setB(color, 32); printf("Color (%d,%d,%d)\n", getR(color),getG(color),getB(color)); </p></li><li><p>Prof. Dr. Nikolaus Wulff Programmieren in C 21</p><p>Farbe als Feld modellieren</p><p> In diesem Fall werden die Farbeintrge als Feld abgelegt und auf jede Komponente kann direkt zugegriffen werden.</p><p> Die Makros verstecken vor der Testroutine wieder die Implementierungsdetails ...</p><p>typedef unsigned char Color[3];</p><p>#define getR(C) ( (C)[0])#define getG(C) ( (C)[1])#define getB(C) ( (C)[2])</p><p>#define setR(C,x) ( (C)[0] = x)#define setG(C,x) ( (C)[1] = x)#define setB(C,x) ( (C)[2] = x)</p></li><li><p>Prof. Dr. Nikolaus Wulff Programmieren in C 22</p><p>Feld Variante Fr die getX/setX Methoden sind keine </p><p>Berechnungen notwendig. Es ist mglich direkte Zuweisungen mit dem = </p><p>Operanden vorzunehmen. Es muss immer bercksichtigt werden, dass es sich </p><p>bei diesem Color Typ um ein Feld der Lnge drei handelt, d.h. Zuweisungen geschehen per Index:</p><p> Beide bisherigen Varianten sind unbefriedigend...</p><p> Color color ={0,255,127}; color[1] = 32; setR(color,125);</p></li><li><p>Prof. Dr. Nikolaus Wulff Programmieren in C 23</p><p> C Strukturen Im Allgemeinen kennen Programmiersprachen fr </p><p>genau diese Problematik ein eigenstndiges Model- lierungselement: z.B. in Pascal den record, in C das struct und OO-Sprachen besitzen hierzu das Konzept der Klasse. </p><p> Ein struct ist ein neuer Datentyp. Zusammengesetzt als Aggregat aus bereits bekannten Datentypen:</p><p>struct { type1 ; ... ; typeN ;};</p></li><li><p>Prof. Dr. Nikolaus Wulff Programmieren in C 24</p><p>Color struct</p><p> Die Zuweisungen sind viel deutlicher und klarer. Ein struct ist ein eigenstndiger neuer Datentypen. Per typedef wird hufig ein struct-Zeiger definiert.</p><p>struct color_struct { unsigned char r; unsigned char g; unsigned char b;};typedef struct color_struct Color;</p><p>#define getR(C) ( (C).r )#define getG(C) ( (C).g )#define getB(C) ( (C).b )</p><p>#define setR(C,x) ( (C).r = (x) )#define setG(C,x) ( (C).g = (x) )#define setB(C,x) ( (C).b = (x) )</p><p>struct Definition</p><p>typedef mit struct</p></li><li><p>Prof. Dr. Nikolaus Wulff Programmieren in C 25</p><p>struct Verwendung</p><p> Ein struct kann bei der Erzeugung direkt mit entsprechenden Werten vorbelegt werden.</p><p> Mit dem Operator wird auf die einzelnen Elemente des struct in beliebiger Reihenfolge sowohl lesend als auch schreibend zugegriffen.</p><p> Die getX/setX Makros sind im Prinzip berflssig.</p><p> Color white = {255,255,255}; Color color;</p><p> color.r = white.r; color.g = 64; color.b = 32;</p><p> printf("Color (%d,%d,%d)\n", color.r, color.g, color.b);</p><p>.</p></li><li><p>Prof. Dr. Nikolaus Wulff Programmieren in C 26</p><p>Der komplexe Datentyp Fr die Ingenieurwissenschaften sind in vielen </p><p>Bereichen die komplexen Zahlen von Bedeutung. Mit Hilfe eines struct fllt es leicht diesen </p><p>Datentypen zu implementieren und auch entsprechende Methoden wie +, - , * und / zu definieren.</p><p> Ein gut modellierter abstrakter Datentyp (ADT) zeichnet sich nicht nur dadurch aus, dass er Felder besitzt, sondern auch noch einen Satz von Methoden, fr die gltigen Operationen dieses ADT.</p></li><li><p>Prof. Dr. Nikolaus Wulff Programmieren in C 27</p><p>Complex.h#ifndef __COMPLEX_H#define __COMPLEX_H/** * Structure for the complex ADT. */typedef struct { double real, imag;} Complex;</p><p>/** * The basic operations for the complex ADT. */Complex cadd(const Complex u, const Complex v);Complex csub(const Complex u, const Complex v);Complex cmul(const Complex u, const Complex v);Complex cdiv(const Complex u, const Complex v);</p><p>#endif /* __COMPLEX_H */</p><p>struct Definition undtypedef in einemSchritt ...</p></li><li><p>Prof. Dr. Nikolaus Wulff Programmieren in C 28</p><p>Complex.c/** multiplication of two complex numbers */Complex cmul(const Complex u, const Complex v) { Complex z = { u.real * v.real - u.imag * v.imag, u.real * v.imag + u.imag * v.real }; return z;}</p><p> Sobald die wesentlichen Operationen definiert und implementiert sind lsst sich leicht mit komplexen Zahlen rechnen.</p><p> Leider erlaubt es C nicht die Operatoren fr +,-,*,/ zu berladen, wie es mit C++ mglich ist. Deshalb werden die Methoden cadd, cmul, etc. definiert.</p></li><li><p>Prof. Dr. Nikolaus Wulff Programmieren in C 29</p><p>structs verschachteln Strukturen knnen ihrerseits wieder aus Strukturen </p><p>zusammengesetzt sein:typedef struct { String town; String street; long zipCode;} Adress;</p><p>typedef struct { short year, month, day;} Date;</p><p>typedef struct { String name; String surname; Adress adresse; Date birthday;} Person;</p></li><li><p>Prof. Dr. Nikolaus Wulff Programmieren in C 30</p><p>Anwendung von Strukturen Mit Hilfe von geschachtelten Strukturen lassen sich </p><p>Zugriffe recht bersichtlich programmieren: Person nw;</p><p> nw.name = "Nikolaus"; nw.surname = "Wulff";</p><p> nw.adresse.town = "Steinfurt"; nw.adresse.street = "Stegerwaldstr. 39"; nw.adresse.zipCode = 48565;</p><p> nw.birthday.month = 11; nw.birthday.day = 20; ...</p></li></ul>

Recommended

View more >