1 chapter 16 structures. 2 structures a structure is a collection of one or more variables, possibly...

Post on 23-Dec-2015

215 Views

Category:

Documents

0 Downloads

Preview:

Click to see full reader

TRANSCRIPT

1

Chapter 16Chapter 16

Structures

2

StructuresStructures

• 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

• Variables in a structure are called fields of the structure

3

An ExampleAn Example

• The information for an employee:– Name– Address– Phone number– Age– Sex– Identification number– Salary

4

An ExampleAn Example

struct employee {

char name[40];

char address[100];

char phone_number[10];

int age;

int sex;

char id_number[10];

int salary;};

5

Operations on StructuresOperations 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 ‘&’

6

An ExampleAn Example

(0,0)

(4,3)

struct point { int x; int y;} x, y, z;

struct point pt;struct point maxpt = {320, 200};

printf(“%d, %d”, pt.x, pt.y);

7

An ExampleAn Example

pt1

pt2

struct rec { struct point pt1; struct point pt2;};

struct rec screen;

printf(“%d”, screen.pt1.x);

8

Returning Structures Returning Structures

struct point makepoint(int x, int y){ struct point temp;

temp.x = x; temp.y = y; return temp;}

9

Returning StructuresReturning 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);

10

Structures ParametersStructures 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;}

11

Structures and FunctionsStructures 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;}

12

Pointers to StructuresPointers 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.xrp->pt1.x(r.pt1).x(rp->pt1).x

13

Counting Occurrences of Counting Occurrences of KeywordsKeywords

{“auto”, 0}

{“break”, 0}

{“case”, 0}

{“char”, 0}

{“volatile”, 0}

{“while”, 0}

“auto”

“break”

“case”

“char”

“volatile”

“while”

0

0

0

0

0

0

keyword keycount keytab

14

Arrays of StructuresArrays of Structures

char *keyword[NKEYS];int keycount[NKEYS];

struct key { char *word; int count;} keytab[NKEYS];

15

Arrays of StructuresArrays of Structures

struct key { char *word; int count;} keytab[ ] = { {“auto”, 0}, {“break”, 0}, {“case”, 0}, {“char”, 0},

… {“volatile”, 0}, {“while”, 0}};

16

Arrays of StructuresArrays of Structuresmain( ) { 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;}

17

Arrays of StructuresArrays 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;}

18

Arrays of StructuresArrays of Structuresint 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];}

19

Pointers to StructuresPointers to Structuresmain( ) { 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;}

20

Pointers to StructuresPointers to Structuresstruct 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;}

21

Counting Occurrences of All Counting Occurrences of All WordsWords

now is the time for all good men

to come to the aid of their party

22

Binary TreesBinary Trees

now

is the

men of timefor

party their togoodall

comeaid a pointer to the text of the worda count of the number of occurrencesa pointer to the left child nodea pointer to the right child node

23

Self-referential StructuresSelf-referential Structures

struct tnode { char *word; int count; struct tnode *left; struct tnode *right;}

24

Self-referential StructuresSelf-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;}

25

Self-referential StructuresSelf-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;}

26

Self-referential StructuresSelf-referential Structures

void treeprint(struct tnode *p) { if (p != NULL) { treeprint(p->left); printf("%4d %s\n", p->count, p->word); treeprint(p->right); }}

27

Self-referential StructuresSelf-referential Structuresstruct 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;}

28

RecursionRecursion

• 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

29

An Example - IterationAn Example - Iteration

#include <stdio.h>

int factorial(int n) { int product, i; product = 1; for (i = 1; i <= n; i++) product *= i; return product; }

30

An Example - RecursionAn Example - Recursion

#include <stdio.h>

int factorial(int n) { if (n = 0) { return 1; } else { return n * factorial(n – 1); } }

31

An Example - RecursionAn Example - Recursion

factorial(1)factorial(2) factorial(0)

112

n=2 n=2

n=1

n=0

n=2

n=1

32

An Example - IterationAn 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); }

33

An Example - RecursionAn 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’); }

34

An Example - RecursionAn Example - Recursion

printd(12)printd(123) printd(1)

123

n=123 n=123

n=12

n=1

n=123

n=12

35

An Example - IterationAn 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;}

36

An Example - RecursionAn Example - Recursionint 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; } }

37

RecursionRecursion

• 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

38

An Example - QueuesAn 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

39

First ImplementationFirst 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

40

An ExampleAn Example

typedef struct queue { void *array[MAXSIZE]; int len;} *queueT;

array:len: 0

array: alen: 1

array: a blen: 2

array: a b clen: 3

array: b clen: 2

41

An ExampleAn ExamplequeueT 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;} }

42

An ExampleAn Example

void enqueue(queueT q, void *obj){ if (q->len == MAXSIZE) { error(“enqueue called on a full queue”); } q->array[q->len++] = obj;}

43

An ExampleAn 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;}

44

Second ImplementationSecond 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

45

Ring BuffersRing Buffers

head tail

46

An ExampleAn Example

typedef struct queue { void *array[MAXSIZE]; int head; int tail;} *queueT;

array:head: 0 tail: 0

array: ahead: 0 tail: 1

array: a bhead: 0 tail: 2

array: a b chead: 0 tail: 3

array: b chead: 1 tail: 3

47

An ExampleAn ExamplequeueT 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) ;} }

48

An ExampleAn 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;}

49

An ExampleAn 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;}

50

Third ImplementationThird 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

51

Linked ListsLinked Lists

data data data data

52

An ExampleAn Example

head: NULLtail: NULL

ahead: tail:

a bhead: tail:

a b chead: tail:

b chead: tail:

typedef struct element { void *data; struct element *next;} *elementT;

typedef struct queue { elementT head; elementT tail; int len;} *queueT;

53

An ExampleAn Example

queueT newQueue(void){ queueT q; q = (queueT) malloc(sizeof(struct queue)); q->head = q->tail = NULL; q->len = 0; return q;}

54

An ExampleAn Example

void freeQueue(queueT q) int queueLength(queueT q){ { elementT e, pe; return q->len;

} e = q->head; while (e != NULL) { pe = e; e = e->next; free((char *) pe); } free((char *) q);}

55

An ExampleAn Examplevoid enqueue(queueT q, void *obj){ elementP e; e = (elementP) malloc(sizeof(struct element)); e->data = obj; e->next = NULL; if (q->len == 0) { q->head = q->tail = e; } else { q->tail->next = e; q->tail = e; } q->len++;}

56

An ExampleAn Examplevoid *dequeue(queueT q) { void *result; elementP e; if (q->len == 0) { error(“dequeue called on an empty queue”); } else { e = q->head; result = e->data; q->head = e->next; q->len--; if (q->len == 0) q->tail = NULL; free((char *) e); } return result;}

57

Macro ProcessingMacro Processing

/* macro definition */#define IN 1

#define min(a, b) ((a) < (b) ? (a) : (b))

/* macro expansion */state = IN;/* state = 1; */value = min(2, 3); /* value = ((2) < (3) ? (2) : (3)); */

58

Hash TablesHash Tables

name

defn

next

name

defn

next

name

defn

next struct nlist{ struct nlist *next; char *name; char *defn;}

59

The Hash FunctionThe Hash Function

#define HASHSIZE 101

static struct nlist *hashtab[HASHSIZE];

unsigned hash(char *s){ unsigned hashval; for (hashval = 0; *s != ‘\0’; s++) hashval = *s + 31 * hashval; return hashval % HASHSIZE;}

60

An ExampleAn Example

“IN”

“1”

next

name

defn

next

name

defn

next“min(a, b)”

“((a) < (b)) ? (a) : (b)”

name

defn

“OUP”

“2”

61

Lookup an ElementLookup an Element

struct nlist *lookup(char *s){ struct nlist *np;

for (np = hashtab[hash(s)]; np != NULL; np = np->next)

if (strcmp(s, np->name) == 0) return np; return NULL;}

62

Install an ElementInstall an Elementstruct nlist *install(char *name, char *defn) { struct nlist *np; unsigned hashval; if ((np = lookup(name)) == NULL) { np = (struct nlist *) malloc(sizeof(*np)); if (np == NULL || (np->name=strdup(name)) == NULL) return NULL; hashval = hash(name); np->next = hashtab[hashval]; hashtab[hashval] = np; } else free((void *) np->defn); if ((np->defn = strdup(defn)) == NULL) return NULL; return np;}

63

Syntax TreesSyntax Trees

if-stmt

expr stmt stmt

+

* 4

53

treenode

treenode

64

UnionsUnions

• A union is a variable that may hold (at different times) objects of different types and sizes

union u_tag {int ival;float fval;char *sval;

} u;

• The variable u will be large enough to hold the largest of the three types

65

UnionsUnions

• Members of a union may be accessed asunion-name.member

orunion-pointer->member

• A union may only be initialized with a value of the type of its first member

union u_tag u = 10;

66

An ExampleAn Example

struct treenode {int utype;union utag u;

} node;

67

An ExampleAn Example

/* If the variable utype is used to keep *//* track of the current type stored in u */

if (node.utype == INT) printf(“%d\n”, node.u.ival);else if (node.utype == FLOAT) printf(“%f\n”, node.u.fval);else if (node.utype == STRING) printf(“%s\n”, node.u.sval);else printf(“bad type %d in utype\n”, node.utype);

68

FlagsFlags

• A compiler needs to record information about identifiers– Whether it is a keyword– Whether it is static– Whether it is external

• The most compact way to encode such information is a set of one-bit flags in a single char or int

69

An ExampleAn Example

#define KEYWORD 01#define EXTERNAL 02#define STATIC 04

enum { KEYWORD = 01, EXTERNAL = 02, STATIC = 04};

flags |= EXTERNAL | STATIC; /* turn on */flags &= ~(EXTERNAL | STATIC); /* turn off */if ((flags & (EXTERNAL | STATIC)) == 0) …

70

Bit FieldsBit Fields

• A bit-field, or field for short, is a set of adjacent bits within a single implementation-defined storage unit

• The syntax of field definition and access is based on structures

71

An ExampleAn Example

struct { unsigned int is_keyword : 1; unsigned int is_external : 1; unsigned int is_static : 1;} flags;

flags.is_extern = flags.is_static = 1; /* turn on */flags.is_extern = flags.is_static = 0; /* turn off */if (flags.is_extern == 0 && flags.is_static == 0) …

72

Bit FieldsBit Fields

• Almost everything about fields is implementation-dependent

• Fields may be declared only as ints; for portability, specify signed or unsigned explicitly

• Fields need not be named; unnamed fields are used for padding

• The special width 0 may be used to force alignment at the next word boundary

73

Bit FieldsBit Fields

struct example {

unsigned int a : 13;

unsigned int : 3;

unsigned int c : 4;

} ;

struct example {

unsigned int a : 13;

unsigned int : 0;

unsigned int c : 4;

} ;

74

Abstract Data TypesAbstract Data Types

• A type defined in terms of its behavior rather than its representation is called an abstract data type

• The type string defined in strlib.h is an abstract data type, while the type string defined in string.h is not an abstract data type

75

Abstract Data TypesAbstract Data Types

• An abstract type is exported by an interface along with a collection of functions that define its behavior

• The representation is a property of the implementation

• As with any abstraction, it is appropriate to change the implementation as long as the interface remains the same queue: array, ring buffer, linked list

76

Abstract Data TypesAbstract Data Types

basic data types

operators: +, -, *, /, = basic data values: int,float, char

control statements: if,switch,while, for, do

composite data values:array, struct, union, pointer

functions

abstract data types

77

Computational ComplexityComputational Complexity

• The computation complexity of an algorithm is a proportional measure of running time in terms of the problem size

• Quadratic time: selection sort• Linear time: linear search, dequeue (via arra

y)• Logarithic time: binary search• Constant time: dequeue (via ring buffer or li

nked list)

78

Selection SortSelection Sort

void sortIntArray(int array[], int size){ int lh, rh;

for (lh = 0; lh < size; lh++) { rh = findSmallestInt(array, lh, size – 1); swap(array, lh, rh); }}

79

Selection SortSelection Sort

int findSmallestInt(int array[], int low, int high){ int i, spos;

spos = low for (i = low; i <= high; i++) { if (array[i] < array[spos]) spos = i; } return spos;}

80

Selection SortSelection Sort

The number of comparisons

= N + (N –1) + (N – 2) + … + 3 + 2 + 1

= (N2 + N) / 2

The performance of the selection sort

algorithm is N2

81

Merge SortMerge Sort

void sortIntArray(int array[], int n){ int i, n1, n2, *arr1, *arr2; if (n > 1) { n1 = n / 2; n2 = n – n1; arr1 = newArray(n1, int); arr2 = newArray(n2, int); copy(array, arr1, 0, n1) copy(array, arr2, n1+1, n2); sortIntArray(arr1, n1); sortIntArray(arr2, n2); merge(array, arr1, n1, arr2, n2); }}

82

Merge SortMerge Sortvoid merge(int array[], int arr1[], int n1, int arr2[], int n2){ int p, p1, p2; p = p1 = p2 = 0; while (p1 < n1 && p2 < n2) { if (arr1[p1] < arr2[p2]) { array[p++] = arr1[p1++]; } else { array[p++] = arr1[p1++]; } } while (p1 < n1) array[p++] = arr1[p1++]; while (p2 < n2) array[p++] = arr2[p2++];}

83

Merge SortMerge Sort

The depth of recursion = log2N

The number of comparisons = N log2N

The performance of the merge sort

algorithm is N log2N

84

ComparisonsComparisons

N N2 NLogN 10 100 33 100 10000 644 1000 1000000 996510000 100000000 132877

N Selection sort Merge sort 10 0.00013 0.00094 100 0.00967 0.012 1000 1.08 0.1410000 110.0 1.6

85

A Record-Based ApplicationA Record-Based Application

• A teaching tool that asks a series of questions so that previous answers determine the order of subsequent questions

• This tool must be able to– Ask the student a question– Get an answer from the student– Move on to the next question, the choice of

which depends on the student’s response

86

A Record-Based ApplicationA Record-Based Application

• This tool can be implemented as a set of functions. Each function asks a question, reads in an answer, and then calls another function appropriate to the answer the student supplies

• This program is difficult to change, in particular, for teachers who are not programmers

87

A Record-Based ApplicationA Record-Based Application

• Instead, we want to design a teaching tool that presents a programmed instruction course to the student but allows teachers without programming skills to supply the questions, expected answers, and cross-reference information so that your tool can present the questions in the appropriate order

88

A Record-Based ApplicationA Record-Based Application

• The best approach is to design your tool as a general tool that takes all data pertaining to the programmed instruction course from a file

• If we adopt this approach, the same program can present many different courses by using different data files

89

A Record-Based ApplicationA Record-Based Application

• What are the overall requirements of the general problem?

• How can you represent the data for courses in the context of your program?

• What should a course data file look like?• How do you convert the external representation

used in the data file into the internal one?• How do you write the program that manipulates

the database?

90

A Record-Based ApplicationA Record-Based Application

• Ask the student the current question.• Request an answer from the student• Look up the answer in a list of possibilities

provided for that question. If the answer appears in the list, consult the data structure to choose the next question. Otherwise, the student is informed of this fact and given another chance at the same question

91

Internal RepresentationInternal Representationdb db

title

questions

typedef struct { string title; questionT questions[MaxQuestions + 1];} *courseDB;

courseDB db;

92

Internal RepresentationInternal Representation

nAnswers

answersqtext typedef struct { string qtext[MaxLinesPerQuestion+1]; answerT answers[maxAnswersPerQuestion]; int nAnswers;} *questionT;

ans nextq

typedef struct { string ans; int nextq;} answerT;

93

Internal RepresentationInternal Representation

db

title

questions

nAnswers

answersqtext

94

External RepresentationExternal Representation

1True or false: The earth revolves around the sun.-----true: 2false: 3

2…

95

Process CourseProcess Coursevoid processCourse(courseDB course){ questionT q; int gnum; string ans; int index; qnum = 1; while (qnum != 0) { q = course->questions[qnum]; askQuestion(q); ans = ConvertToUpperCase(getline()); index = findAnswer(ans, q); if (index == -1) printf(“I don’t understand that.\n”); else qnum = q->answers[index].nextq; }}

96

Ask QuestionAsk Question

void askQuestion(questionT q){ int i;

for (i = 0; q->qtext[i] != NULL; i++) { printf(“%s\n”, q->qtext[i]); }}

97

Find AnswerFind Answer

int findAnwer(string ans, questionT q){ int i;

for (i = 0; i < q->nAnswers; i++) { if (stringEqual(ans, q->answers[i].ans)) return i; } return –1;}

98

Data-Driven DesignData-Driven Design

• Programs that control their entire operation on the basis of information from a database are said to be data-driven

• Data-driven programs are usually shorter, more flexible, and easier to maintain than programs that incorporate the same information directly into the program design

top related