990 likes | 1.22k Views
Chapter 16. Structures. Structures. A structure is a collection of one or more variables , possibly of different types , grouped together under a single name for convenient handling Structures permit a group of related variables to be treated as a unit instead of as separate entities
E N D
Chapter 16 Structures
Structures • A structure is a collection of one or morevariables, possibly of different types, grouped together under a single name for convenient handling • Structures permit a group of related variables to be treated as a unit instead of as separate entities • Variables in a structure are called fields of the structure
An Example • The information for an employee: • Name • Address • Phone number • Age • Sex • Identification number • Salary
An Example • struct employee { • char name[40]; • char address[100]; • char phone_number[10]; • int age; • int sex; • char id_number[10]; • int salary; • };
Operations on Structures • The only legal operations on a structure: • Copying it or assigning to it as a unit • Accessing its fields with ‘.’ and field names • Taking its address with ‘&’
(4,3) (0,0) An Example struct point { int x; int y; } x, y, z; struct point pt; struct point maxpt = {320, 200}; printf(“%d, %d”, pt.x, pt.y);
An Example struct rec { struct point pt1; struct point pt2; }; struct rec screen; printf(“%d”, screen.pt1.x); pt2 pt1
Returning Structures struct point makepoint(int x, int y) { struct point temp; temp.x = x; temp.y = y; return temp; }
Returning Structures struct rect screen; struct point middle; struct point makepoint(int x, int y); screen.pt1 = makepoint(0, 0); screen.pt2 = makepoint(320, 200); middle = makepoint((screen.pt1.x + screen.pt2.x)/2, (screen.pt1.y + screen.pt2.y)/2);
Structures Parameters struct point addpoint(struct point p1, struct point p2) { p1.x += p2.x; p1.y += p2.y; return p1; } int ptinrect(struct point p, struct rect r) { return p.x >= r.pt1.x && p.x < r.pt2.x && p.y >= r.pt1.y && p.y < r.pt2.y; }
Structures and Functions #define min(a, b) ((a) < (b) ? (a) : (b)) #define max(a, b) ((a) < (b) ? (b) : (a)) struct rect canonrect(struct rect r) { struct rect temp; temp.pt1.x = min(r.pt1.x, r.pt2.x); temp.pt1.y = min(r.pt1.y, r.pt2.y); temp.pt2.x = max(r.pt1.x, r.pt2.x); temp.pt2.y = max(r.pt1.y, r.pt2.y); return temp; }
Pointers to Structures struct point origin, *pp; pp = &origin; printf(“%d, %d”, (*pp).x, (*pp).y); printf(“%d, %d”, pp->x, pp->y); struct rect r, *rp = &r; r.pt1.x rp->pt1.x (r.pt1).x (rp->pt1).x
Counting Occurrences of Keywords “auto” “break” “case” “char” … “volatile” “while” 0 0 0 0 … 0 0 {“auto”, 0} {“break”, 0} {“case”, 0} {“char”, 0} … {“volatile”, 0} {“while”, 0} keyword keycount keytab
Arrays of Structures char *keyword[NKEYS]; int keycount[NKEYS]; struct key { char *word; int count; } keytab[NKEYS];
Arrays of Structures • struct key { • char *word; • int count; • } keytab[ ] = { • {“auto”, 0}, {“break”, 0}, • {“case”, 0}, {“char”, 0}, • … • {“volatile”, 0}, {“while”, 0} • };
Arrays of Structures main( ) { int n; char word[MAXWORD]; while (getword(word, MAXWORD) != EOF) if (isalpha(word[0])) if ((n= binsearch(word, keytab, NKEYS)) >= 0) keytab[n].count++; for (n = 0; n < NKEYS; n++) if (keytab[n].count > 0) printf("%4d %s\n", keytab[n].count, keytab[n].word); return 0; }
Arrays of Structures int binsearch(char *word, struct key tab[ ], int n) { int cond, low = 0, high = n - 1, mid; while (low <= high) { mid = (low + high) / 2; if ((cond = strcmp(word, tab[mid].word)) < 0) high = mid -1; else if (cond > 0) low = mid + 1; else return mid; } return -1; }
Arrays of Structures int getword(char *word, int lim) { int c; char *w = word; while (isspace(c = getch( ))) ; if (c != EOF) *w++ = c; if (!isalpha( c )) { *w = '\0'; return c; } for (; --lim > 0; w++) if (!isalnum(*w = getch( ))) { ungetch(*w); break; } *w = '\0'; return word[0]; }
Pointers to Structures main( ) { char word[MAXWORD]; struct key *p; while (getword(word, MAXWORD) != EOF) if (isalpha(word[0])) if ((p= binsearch(word, keytab, NKEYS)) != NULL) p->count++; for (p = keytab; p < keytab + NKEYS; p++) if (p->count > 0) printf("%4d %s\n", p->count, p->word); return 0; }
Pointers to Structures struct key *binsearch(char *word, struct key *tab, int n) { int cond; struct key *low = &tab[0], *high = &tab[n], *mid; while (low < high) { mid = low + (high - low) / 2; if ((cond = strcmp(word, mid->word)) < 0) high = mid - 1; else if (cond > 0) low = mid + 1; else return mid; } return NULL; }
Counting Occurrences of All Words now is the time for all good men to come to the aid of their party
Binary Trees now the is for men of time party their to all good aid come a pointer to the text of the word a count of the number of occurrences a pointer to the left child node a pointer to the right child node
Self-referential Structures struct tnode { char *word; int count; struct tnode *left; struct tnode *right; }
Self-referential Structures main( ) { char word[MAXWORD]; struct tnode *root = NULL; while (getword(word, MAXWORD) != EOF) if (isalpha(word[0])) root = addtree(root, word); treeprint(root); return 0; }
Self-referential Structures struct tnode *addtree(struct tnode *p, char *w) { int cond; if (p == NULL) { p = talloc( ); p->word = strdup(w); p->count = 1; p->left = p->right = NULL; } else if ((cond = strcmp(w, p->word)) == 0) p->count++; else if (cond < 0) p->left = addtree(p->left, w); else p->right = addtree(p->right, w); return p; }
Self-referential Structures void treeprint(struct tnode *p) { if (p != NULL) { treeprint(p->left); printf("%4d %s\n", p->count, p->word); treeprint(p->right); } }
Self-referential Structures struct tnode *talloc(void) { return (struct tnode *) malloc(sizeof(struct tnode)); } char *strdup(char *s) { char *p; p = (char *) malloc(strlen(s) + 1); if (p != NULL) strcpy(p, s); return p; }
Recursion • C functions may be used recursively; that is, a function may call itself either directly or indirectly • When a function calls itself recursively, each invocation gets a fresh set of all the automatic variables
An Example - Iteration #include <stdio.h> int factorial(int n) { int product, i; product = 1; for (i = 1; i <= n; i++) product *= i; return product; }
An Example - Recursion #include <stdio.h> int factorial(int n) { if (n = 0) { return 1; } else { return n * factorial(n – 1); } }
factorial(1) factorial(2) 2 1 1 n=0 factorial(0) n=1 n=1 n=2 n=2 n=2 An Example - Recursion
An Example - Iteration void itoa( int n, char s[ ] ) { int i, sign; if ((sign = n) < 0) n = -n; i = 0; do s[i++] = n % 10 + ‘0’; } while ((n /= 10) > 0); if (sign < 0) s[i++] = ‘-’; s[i] = ‘\0’; reverse(s); }
An Example - Recursion #include <stdio.h> void printd( int n) { if (n < 0) { putchar(‘-’); n = -n; } if (n / 10) printd(n / 10); putchar(n % 10 + ‘0’); }
printd(12) printd(123) 3 2 1 n=1 printd(1) n=12 n=12 n=123 n=123 n=123 An Example - Recursion
An Example - Iteration int binsearch(char *word, struct key tab[ ], int n) { int cond, low = 0, high = n - 1, mid; while (low <= high) { mid = (low + high) / 2; if ((cond = strcmp(word, tab[mid].word)) < 0) high = mid -1; else if (cond > 0) low = mid + 1; else return mid; } return -1; }
An Example - Recursion int binsearch(char *word, struct key tab[ ], int low, int high) { int cond, mid; if (low <= high) { return -1; } else { mid = (low + high) / 2; if ((cond = strcmp(word, tab[mid].word)) < 0) return binsearch(word, tab, low, mid - 1); else if (cond > 0) return binsearch(word, tab, mid + 1, high); else return mid; } }
Recursion • Recursion provides no saving in storage, since the data for every invocation must be maintained • Recursion provides no saving in execution time, since time for function invocations is higher than loops • Recursive functions are more compact, much easier to write and understand
An Example - Queues • A queue is a waiting line. Customers go to the back of the waiting line and wait for their turn • Some common operations on queues: • Create a new queue • Eliminate an existing queue • Add a customer to the end of the the queue • Remove a customer from the front of the queue • Determine how many customers are in the queue
First Implementation • A queue is implemented as an array and the front of the queue is always the first element of the array • The length of the queue is statically determined • Removing a customer is very inefficient
An Example typedef struct queue { void *array[MAXSIZE]; int len; } *queueT; array: len: 0 array: a len: 1 array: a b len: 2 array: a b c len: 3 array: b c len: 2
An Example queueT newQueue(void) { queueT q; q = (queueT) malloc(sizeof(struct queue)); q->len = 0; return q; } void freeQueue(queueT q) int queueLength(queueT q) { { free((char *) q); return q->len; } }
An Example void enqueue(queueT q, void *obj) { if (q->len == MAXSIZE) { error(“enqueue called on a full queue”); } q->array[q->len++] = obj; }
An Example void *dequeue(queueT q) { void *result; int i; if (q->len == 0) error(“dequeue called on an empty queue”); result = q->array[0]; for (i = 1; i < q->len; i++) q->array[i - 1] = q->array[i] ; q->len--; return result; }
Second Implementation • A queue is implemented as a ring buffer and the front of the queue will change dynamically • The length of the queue is statically determined • Removing a customer is very efficient
Ring Buffers tail head
An Example typedef struct queue { void *array[MAXSIZE]; int head; int tail; } *queueT; array: head: 0 tail: 0 array: a head: 0 tail: 1 array: a b head: 0 tail: 2 array: a b c head: 0 tail: 3 array: b c head: 1 tail: 3
An Example queueT newQueue(void) { queueT q; q = (queueT) malloc(sizeof(struct queue)); q->head = q->tail = 0; return q; } void freeQueue(queueT q) int queueLength(queueT q) { { free((char *) q); return ((q->tail-q->head) %MAXSIZE) ; } }
An Example void enqueue(queueT q, void *obj) { if (queueLength(q) == MAXSIZE) { error(“enqueue called on a full queue”); } q->array[q->tail++] = obj; q->tail %= MAXSIZE; }
An Example void *dequeue(queueT q) { void *result; int i; if (queueLength(q) == 0) error(“dequeue called on an empty queue”); result = q->array[q->head++]; q->head %= MAXSIZE; return result; }
Third Implementation • A queue is implemented as a linked list and the front of the queue will change dynamically • The length of the queue is dynamically determined • Removing a customer is very efficient