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

  • View
    216

  • Download
    2

Embed Size (px)

Text of Programmieren in C Eigene . Dr. Nikolaus Wulff Programmieren in C 2 C Datentypen • Variablen in C...

  • Prof. Dr. Nikolaus Wulff

    Programmieren in CProgrammieren in C

    Eigene Datentypen per typedef und Strukturen

  • Prof. Dr. Nikolaus Wulff Programmieren in C 2

    C Datentypen

    Variablen in C sind immer von einem bestimmten Datentyp, z. B. int, float, char, etc.

    Zustzlich definiert die Sprache Operationen die mit den Datentypen erlaubt sind, +,*, etc.

    Diese Typen sind eng angelegt an die Mglichkeiten einer CPU und den primitiven mathematischen Operationen, die damit mglich sind.

    Fr fachliche Anwendungen ist es wnschenswert eigene Datentypen zu verwenden, wie z.B. einen Geldbetrag, ein Datum, eine Farbe, etc.

  • Prof. Dr. Nikolaus Wulff Programmieren in C 3

    Eigene Datentypen

    C kennt verschiedene Mechanismen, um eigene Datentypen zu definieren.

    Diese Typen knnen dann mit sprechenden Typnamen versehen sein.

    Dies ermglicht es sprachlich nher an der Semantik des Problembereichs zu bleiben.

    Dies erleichtert die Lesbarkeit und kann auch verwendet werden, um Programme leichter zwischen verschiedenen Maschinenarchitekturen zu portieren.

  • Prof. Dr. Nikolaus Wulff Programmieren in C 4

    Aufzhlungstypen

    Das Konzept von Aufzhlungen (eng. Enumeration) kommt derart hufig vor, das C hierfr eine eigene Anweisung besitzt, um einen Aufzhlungstypen fr Konstanten zu definieren.

    Statt vieler Konstanten per #define wird die enum Anweisung verwendet, um einen ganzen Satz von Konstanten zu definieren.

    enum { value1,...,valueN};

  • Prof. Dr. Nikolaus Wulff Programmieren in C 5

    Boolean per enum

    C kennt keinen Booleschen Datentyp, daher werden die Variablen TRUE und FALSE hufig per #define Anweisung definiert:

    Sauberer geht es per enum:

    Die Voreinstellung ist, dass der erste Bezeichner (hier false) mit 0 belegt wird und dann wird jeweils um eins inkrementiert.

    #define FALSE 0#define TRUE 1

    enum Boolean { false, true};

  • Prof. Dr. Nikolaus Wulff Programmieren in C 6

    Wochentage

    Wir wollen ein Programm Kalender zur Bearbeitung von Wochentagen entwickeln.

    Die Header Datei Kalender.h knnte so aus sehen:

    #define MONDAY 1#define TUESDAY 2#define WEDNESDAY 3#define THURSDAY 4#define FRIDAY 5#define SATURDAY 6#define SUNDAY 7

    void printDay(int day);

  • Prof. Dr. Nikolaus Wulff Programmieren in C 7

    Aufzhlungstypen

    Statt vieler Konstanten per #define wird die enum Anweisung verwendet.

    Damit die Zhlung nicht mit monday bei 0 beginnt, kann explizit der erste Wert belegt werden.

    Der enum Typ Day kann sogar als Parametertyp in der Methode printDay deklariert werden.

    enum Day { monday=1, tuesday, wednesday, thursday, friday, saturday,

    sunday};

    void printDay(enum Day day);

  • Prof. Dr. Nikolaus Wulff Programmieren in C 8

    Verwendung von enum

    Die Methode printDay kann nun mit den Konstanten des Aufzhlungstypen Day gerufen werden:

    aber auch ein Aufruf mit int funktioniert:

    Intern wird enum immer als eine Konstante vom Typ int reprsentiert.

    Leider kann auch Unsinn bergeben werden:

    Merke: Wir kmmern uns um die Namen, der Compiler um die Werte...

    printDay(tuesday);

    printDay(2);

    printDay(-20);

  • Prof. Dr. Nikolaus Wulff Programmieren in C 9

    Enum sind intern Integers

    Fr solche Flle muss eine Mglichkeit der Fehlerbehandlung vorgesehen werden...

    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(); };}

  • Prof. Dr. Nikolaus Wulff Programmieren in C 10

    Enum Konstanten vorbelegen

    Die enum Konstanten knnen beliebig vergeben werden auch mit negativen Werten:

    Es lassen sich mehrere Bezeichner mit dem selben Wert belegen:

    enum example { a, b, c, d, e=-2, f, g, h i=-3, j, k, l, m, ...};

    Wert Name-3 i-2 e j-1 f k 0 a g l 1 b h m 2 c 3 d

  • Prof. Dr. Nikolaus Wulff Programmieren in C 11

    Alias per typdef

    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:

    So kann z.B. das Konstrukt char* mit einer Zeichenkette als String identifiziert werden:

    s ist immer noch eine Variable vom Typ char*!

    typedef ;

    typedef char* String;

    String s = "Hallo";

  • Prof. Dr. Nikolaus Wulff Programmieren in C 12

    Anwendungen von typedef

    Ein paar Beispiele zur Anwendung von typedef:

    Die Bedeutung des Codes erschliet sich mit den Typen Alter und Geld wesentlich leichter, als wenn dort mit unsigned short gearbeitet worden wre.

    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 ...

    typedef float Geld;typedef unsigned short Alter;

    Alter volljaehrig = 18;Geld gehalt = 4711.00;

  • Prof. Dr. Nikolaus Wulff Programmieren in C 13

    typedef und enum

    Etwas unschn beim Day Beispiel war es berall in den Methodensignaturen enum mit einzufgen:

    Wesentlich eleganter geht es mit typedef :

    oder in einem Rutsch:

    enum Day { monday=1, tuesday, ...};

    void printDay(enum Day day);

    enum day_enum { monday=1, tuesday,...};typedef enum day_enum Day;

    void printDay(Day day);

    typedef enum { monday=1, tuesday,...} Day;

  • Prof. Dr. Nikolaus Wulff Programmieren in C 14

    Ein altes Beispiel ...

    /** two constants for f2c and c2f calculus */#define SHIFT 32.0#define SCALE (9.0/5.0)

    /** 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;}

    Da msste sich doch mit typedef etwas machen lassen ...

  • Prof. Dr. Nikolaus Wulff Programmieren in C 15

    Nochmal Celsius zu Fahrenheit

    So wird der Code sprechend ...

    /** two constants for f2c and c2f calculus */#define SHIFT 32.0#define SCALE (9.0/5.0)

    typedef double Celsius;typedef double Fahrenheit;

    /** 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;}

  • Prof. Dr. Nikolaus Wulff Programmieren in C 16

    C Datentypen Die bis lang vorgestellten Konstrukte, enum und

    typedef, erfllen noch nicht die Anforderung an selbst definierten Datentypen.

    enum definiert Aufzhlungen von int Konstanten. typedefs sind lediglich alias Bezeichner fr bereits

    existierende Datentypen. Keines der beiden Konstrukte liefert wirklich einen

    neuen Datentyp.

  • Prof. Dr. Nikolaus Wulff Programmieren in C 17

    Do it yourself... Wir mchten den Datentyp Farbe (Color)

    implementieren. Color soll die drei Werte (r,g,b) als Triple, jeweils

    im Bereich 0

  • Prof. Dr. Nikolaus Wulff Programmieren in C 18

    Farbe als Ganzzahl modelliert Ein int mit 4 Byte (ansonsten typedef mit long)

    bietet genug Platz, um 3 Byte rgb-Werte abzulegen, mit entsprechenden Bit und Shift Operationen...

    Die get-Methoden lesen mit entsprechenden Masken und shift Operationen die rgb-Werte.

    typedef int Color;

    #define R_MASK 0x00FF0000#define G_MASK 0x0000FF00#define B_MASK 0x000000FF

    #define getR(C) ( ((C) & R_MASK)>>16 )#define getG(C) ( ((C) & G_MASK)>>8 )#define getB(C) ( ((C) & B_MASK) )

    Bits: 0| 1| ... |7|8| ... |15|16| ... |23|24| ... |32

  • Prof. Dr. Nikolaus Wulff Programmieren in C 19

    Farbe als Ganzzahl setzen Ein Farb-Byte gezielt innerhalb des 4 Byte Color int

    zu setzten erfordert schon mehr Operationen:

    Zunchst werden die Bits der zu setzenden Farbe gelscht, ohne die beiden anderen Farben zu lschen.

    Anschlieend wird mit oder der neue Wert gesetzt. Diese Bytefolge ergibt sich aus einer Shift-Operation

    des Farbwertes und anschlieender Maskierung.

    #define setR(C,x) ( (C) = \ ((C) & ~R_MASK)|(((x)

  • Prof. Dr. Nikolaus Wulff Programmieren in C 20

    Ganzzahl Variante Durch die Macros lassen sich per get/setX die Bit

    und Shift-Operationen verstecken und in eine Color.h Datei auslagern.

    Ein Nachteil ist, dass fr jeden getX/setX Befehl Berechnungen durchgefhrt werden mssen.

    Eine Zuweisung per = Operanden funktioniert nicht, es ist immer ein setX Befehl notwendig.

    Color color; setR(color,238); setG(color,124); setB(color, 32); printf("Color (%d,%d,%d)\n", getR(color),getG(color),getB(color));

  • Prof. Dr. Nikolaus Wulff Programmieren in C 21

    Farbe als Feld modellieren

    In diesem Fall werden die Farbeintrge als Feld abgelegt und auf jede Komponente kann direkt zugegriffen werden.

    Die Makros verstecken vor der Testroutine wieder die Implementierungsdetails ...

    typedef unsigned char Color[3];

    #define getR(C) ( (C)[0])#define getG(C) ( (C)[1])#define getB(C) ( (C)[2])

    #define setR(C,x) ( (C)[0] = x)#define setG(C,x) ( (C)[1] = x)#define setB(C,x) ( (C)[2] = x)

  • Prof. Dr. Nikolaus Wulff Programmieren in C 22

    Feld Variante Fr die getX/setX Methoden sind keine

    Berechnungen notwendig. Es ist mglich direkte Zuweisungen