Week 04
Week 04 | 1/34 |
Nerds You Should Know #3 | 2/34 |
She developed COBOL ... and bugs!
... Nerds You Should Know #3 | 3/34 |
Grace Hopper
|
|
... Nerds You Should Know #3 | 4/34 |
Data Types | 5/34 |
Major classes of data types:
++
--
Atomic Data Types | 6/34 |
Families of atomic data types:
int
float
char
char *
int *
char **
size_t
enum Colour {red, blue, green, yellow, white}
= + - == != > < >= <= ++ --
* /
Enums | 7/34 |
Enumerated types (enum
int
enum Mood { depressed, sad, well, happy };
is equivalent to the definitions:
#define depressed 0 #define sad 1 #define well 2 #define happy 3
and a new type enum Mood
unsigned int
Exercise: Enumerated Types | 8/34 |
Define enumerated types for:
Aggregate Data Types | 9/34 |
Families of aggregate data types:
char s[50]
int v[100]
struct
union
struct
struct
Defining New Data Types | 10/34 |
C allows us to define new data type (names) via typedef
typedef ExistingDataType NewTypeName;
Examples:
typedef int Integer; typedef float Temperature; typedef char String[100]; typedef int Matrix[20][20];
... Defining New Data Types | 11/34 |
Reasons to use typedef
Temperature
Dollars
Volts
typedef float Real; Real complex_calculation(Real a, Real b) { Real c = log(a+b); ... return c; }
Matrix
Exercise: Using typedef | 12/34 |
Suggest typedefs
Using typedef | 13/34 |
Example of using typedef
#define NUM_WORKERS 150 #define MAX_NAME_LENGTH 60// version 1 char worker[NUM_WORKERS][MAX_NAME_LENGTH]; char status[NUM_WORKERS][3];// e.g. "FT", "PT", ... float salary[NUM_WORKERS];// version 2 typedef char FullName[MAX_NAME_LENGTH]; typedef enum {casual, part_time, full_time} EmpType; typedef float Dollars FullName worker[NUM_WORKERS]; EmpType status[NUM_WORKERS]; Dollars salary[NUM_WORKERS]; strcpy(worker[i], "John"); status[i] = full_time; salary[i] = 55325.50;
... Using typedef | 14/34 |
Possible memory layout produced by above example:
... Using typedef | 15/34 |
The use of parallel arrays works in limited cases
Worker
Structures | 16/34 |
A structure
struct
struct date { int day; int month; int year; };// don't forget the semicolon!
... Structures | 17/34 |
Defining a structure itself does not allocate any memory
We need to declare a variable in order to allocate memory
struct date christmas;
The components of the structure can be accessed using the "dot" operator
christmas.day = 25; christmas.month = 12; chirstmas.year = 2015;
... Structures | 18/34 |
A structure can be passed as a parameter to a function:
void print_date(struct date d) { printf("%d/%d/%d\n", d.day, d.month, d.year); } int is_leap_year(struct date d) { return ( ((d.year%4 == 0) && (d.year%100 != 0)) || (d.year%400 == 0) ); }
Nested Structures | 19/34 |
One structure can be nested inside another
struct date { int day, month, year; }; struct time { int hour, minute; }; struct speeding { char plate[7]; double speed; struct date d; struct time t; };
typedef struct | 20/34 |
We can now define a structured data type for Worker
typedef char Date[11]; // e.g. "18-08-2014" typedef struct { char name[MAX_NAME_LENGTH]; Date birthday; EmpType status; float salary; } WorkerT;
... typedef struct | 21/34 |
Note: structures can be defined in two different styles:
struct Point0 {float x; float y;};// or typedef struct { float x; float y; } Point1;// which would be used as struct Point0 anumber; Point1 anothernumber;
The definitions produce objects with identical structures.
... typedef struct | 22/34 |
With the above WorkerT
typedef struct {...} WorkerT; WorkerT boss;// single struct WorkerT worker[1500];// array of structs boss.status = full_time; boss.salary = 675000.00; strcpy(boss.name, "John Elliot"); strcpy(boss.birthday, "29-02-1958"); for (i = 0; i < 1500; i++) { fgets(line,60,stdin); strcpy(worker[i].name, line); scanf("%f", &worker[i].salary); ... }
... typedef struct | 23/34 |
Possible memory layout produced for WorkerT
Note: padding is needed to ensure that
birthday
Don't normally care about internal layout, since fields are accessed by name.
Exercise: typedef struct | 24/34 |
Define a structure for entries in this table:
Pointers and struct | 25/34 |
Like any object, we can get the address of a struct
&
WorkerT w; WorkerT *wp; wp = &w;// a problem ... *wp.salary = 125000.00;// does not have the same effect as w.salary = 125000.00;// because it is interpreted as *(wp.salary) = 125000.00;// to achieve the correct effect, we need (*wp).salary = 125000.00;// a simpler alternative is normally used in C wp->salary = 125000.00;
Learn this well; you will see it many more times this semester.
... Pointers and struct | 26/34 |
Diagram of scenario from program above:
... Pointers and struct | 27/34 |
General principle ...
If we have:
SomeStructType s, *sp = &s;
then the following are all equivalent:
s.SomeElem sp->SomeElem (*sp).SomeElem
Linked Structures | 28/34 |
One particularly useful kind of structure:
typedef struct Node { char name[MAXNAME]; int value; struct Node *next; } NodeT;
Allows us to build structures like:
Note that struct Node
NodeT
Exercise: Find Value in List | 29/34 |
Write a function
int valueOf(char *name, NodeT *list)
that returns the value associated with name
list
If the name does not appear in the list, return -1.
Unions | 30/34 |
Sometimes we want a struct
union
struct
Example: nodes in an expression tree
All objects are nodes, but each contains an operator, a variable or a value.
... Unions | 31/34 |
One possible representation for the above:
typedef enum { Opr, Val, Var } NodeKindT; typedef enum { add, sub, mul, div } OperatorT; typedef struct ExprNode { NodeKindT ntype;// e.g. Opr, Val, Var OperatorT opr;// e.g. add, sub char var[8];// e.g. "x", "y" int val;// e.g. 5, -20 struct ExprNode *left;// subtree struct ExprNode *right;// subtree } ExprNodeT;
... Unions | 32/34 |
A problem with this representation:
typedef struct ExprNode { NodeKind ntype;// size = 4 bytes Operator opr;// size = 4 bytes char var[8];// size = 8 bytes int val;// size = 4 bytes struct ExprNode *left;// size = 4 bytes struct ExprNode *right;// size = 4 bytes } ExprNodeT;
... Unions | 33/34 |
Using a union
typedef struct ExprNode { NodeKindT ntype;// size = 4 bytes union { OperatorT opr; char var[8]; int val; } data;// size = 8 bytes struct ExprNode *left;// size = 4 bytes struct ExprNode *right;// size = 4 bytes } ExprNodeT;
Size of ExprNodeT
The data field can be interpreted 3 ways (determined by ntype
... Unions | 34/34 |
Printing an expression rooted in an ExprNodeT *
int print(ExprNodeT *expr) { switch (expr->ntype) { case Val: printf("%d", expr->data.val); break; case Var: printf("%s", expr->data.var); break; case Opr: switch (expr->data.opr) { case add: print(expr->left); putchar('+'); print(expr->right); break; case sub: print(expr->left); putchar('-'); print(expr->right); break; case mul: print(expr->left); putchar('*'); print(expr->right); break; case div: print(expr->left); putchar('/'); print(expr->right); } } }
Note: I'm violating the style guide here
Produced: 11 Aug 2016