1 Homework / Quiz Exam 2 – Solutions Posted – Questions? Continuing K&R Chapter 6 HW6 is on line...
-
Upload
miranda-dennis -
Category
Documents
-
view
219 -
download
0
Transcript of 1 Homework / Quiz Exam 2 – Solutions Posted – Questions? Continuing K&R Chapter 6 HW6 is on line...
1
Homework / Quiz
• Exam 2– Solutions Posted– Questions?
• Continuing K&R Chapter 6
• HW6 is on line – due class 22
2
Self Referential structs, K&R 6.5
• Look at this binary tree structure (Pg. 139)now
is the
for
all
aid come
men of time
party their togood
3
Self Referential structs
struct tnode { /* the tree node struct */ char *word; /* points to the word at this node */ int count; /* has a count of occurances */ struct tnode *left; /* a word < one at this node */ struct tnode *right; /* a word > one at this node */};• OK to have a pointer to a struct of same type in its
own definition• NOT OK to have a struct itself in its own definition!
4
Tree of struct tnodes
char *wordint counttnode *lefttnode *right
keyword \0
char *wordint counttnode *lefttnode *rightchar *word
int counttnode *lefttnode *right
…
……
…
……
tnode *root
5
Self Referential structs
• Each node is a struct tnode with a string value and a count of occurrences
• Each node also contains a pointer to a left child and a right child
• Each child is another struct tnode
6
Declarations / Prototypes
#include <stdio.h>#include <ctype.h> (see functions in App. B2, pp. 248-249, K&R)#include <string.h> (see functions in App. B3, pp. 249-250, K&R)#include “getch.h”
#define MAXWORD 100
int getword(char *word, int lim);struct tnode *addtree(struct tnode *, char *);void treeprint(struct tnode *);
7
Main program
int main( ){ struct tnode *root; /* ptr to root for binary tree */ char word[MAXWORD]; /* word to get from stdin */ root = NULL; /* initially, no tnodes in tree */ /* OK that root pointer points to NULL initially */
while (getword(word, MAXWORD) != EOF) /* getword from stdin */ if (isalpha(word[0])) /* from ctype.h library */ root = addtree(root, word); /* expect not NULL anymore */ treeprint(root); /* print it out in order */ return 0; }
8
treeprint ( )
• To print out tree contents in order:void treeprint (struct tnode *p) {
if (p != NULL) {treeprint (p->left);printf (%4d %s\n”, p->count, p->word);treeprint (p->right);
}}
9
getword ( )int getword(char *word, int lim) {
int c; char *w = word;while isspace(c = getch()) /* skip spaces; c first non-space */
;if (c != EOF) *w++=c; /* c might be EOF here (empty word)
*/if(!isalpha(c)) { /* c (identifier) starts with alpha */
*w = '\0'; return c; /* if not, word empty */}for( ; --lim > 0; w++)
if (!isalnum(*w = getch())) { /* identfier alpha or digits */ungetch(*w); break; /* e.g., + might be needed later */}
*w = '\0'; return word[0];
}
10
addtree ( )struct tnode *talloc(void); /* allocate. return ptr to tnode */char *strdup(char *); /* allocate space, copy word there */
struct tnode *addtree(struct tnode *p, char *w){ int cond;
/*for empty tree, root is NULL */ if (p == NULL) { /* nothing at this node yet */ p = talloc(); /* allocate a new node */ p->word = strdup(w); /* allocate space, copy word there */ p->count = 1; /* count is 1 */ p->left = p->right = NULL; /* this works; see precedence */ } else if ((cond = strcmp(w, p->word)) == 0) /* string.h */ p->count++; /* repeated word, increment count */ else if (cond < 0) /* note cond remembers strcmp above */ p->left = addtree(p->left, w); /* less: go left subtree */ else /* more, go to right subtree */ p->right = addtree(p->right, w); return p;}
11
addtree( )
• Note, that addtree is recursive. If it adds a node, it might need to add root or any left or right child anywhere down the tree
• We pass struct tnode *p as first argument, and also pass back the same type - always a pointer to the node at the current recursive nesting level
• Any time a new node is created: root, p->left or p->right in node above will be set for the FIRST time based on return value from addtree
12
addtree ( )
• When main calls addtree, the return sets root value each time even if the root already pointed to tnode
• Allows for possible addition of a pointer to a node• Why do we need to return a struct tnode *p when
we have struct tnode *p as an argument?• Can't we just set it via argument, return void from
addtree, and write (in main)?addtree(root, word);
instead of root = addtree(root, word);
13
addtree ( )
• No, root is already a pointer, struct tnode *, but it is the pointer root itself that must be modified
• To modify root, we would need to declare addtree with a pointer to a struct tnode * as the first arg:void addtree(struct tnode **pptr, char *w){ struct tnode *p = *pptr;
• Call it from main recursively by invocation: addtree(&root, word);
• Then, addtree could set the value for root directly *pptr = p;
• Same is true when adding a left or right child
14
talloc ( )
• How to write talloc to allocate a tnode and return a pointer.
struct tnode *talloc(void)
{
return (struct tnode *) malloc (sizeof(struct tnode));
}
15
strdup ( )• strdup ( ) creates space for a character string, copies a word
into it (up to null terminator) and returns the char pointer char *strdup(char *s){
p = (char *) malloc (strlen(s)+1); /* +1 for '\0' */ if (p != NULL) /* if malloc didn’t fail */ strcpy(p, s); /* library function in string.h */ return p;
}
16
Intro to HW6
• Memory model for malloc( ) and free( )Before any calls to alloc( ):
allocbuf:
After two calls to alloc( ) and before call to freef( ):
allocbuf:
After call to freef( ) on first block alloc gave out:
allocbuf:
Free
Free
In UseIn Use
Free FreeIn Use
17
Intro to HW6
• Fragmentation with malloc( ) and free( )Before call to alloc( ) for a large memory block:
allocbuf:
alloc can NOT provide a large contiguous blockof memory - even though there is theoreticallysufficient free memory! Memory is fragmented!!
In use Free In use Free In use Free In use
18
Intro to HW6
• Not possible to “defragment” allocbuf memory after the fact as you would do for a disk
• On a disk, the pointers to memory are in the disk file allocation table and can be changed
• With malloc, programs are holding pointers to memory they own - so can’t be changed!!
• Can only defragment as blocks are freed by using program
19
Intro to HW6
• Initial structures in allocbuf[]
• Structures after two calls to alloc()
blockl blockl blocklblockr blockr blockr
Inuse 1Inuse 2Free Memory
blockl blockr
Free Memory
20
Intro to HW6
• Structures after free call on first block only
• Structures after free call on second block only
blockl blocklblockr blockr
Inuse 1Free Memory
blockl blockl blocklblockr blockr blockr
Free Memory Inuse 2 Free Memory
Note effect of coalesce!
21
Intro to HW6
• Four possible states for block being freed– Between two blocks that are still in-use– Above a free block and below an in-use block– Above an in-use block and below a free block– Above a free block and below a free block
• When freeing a block, coalesce with adjacent free blocks to avoid unnecessary fragmentation of allocbuf (allows alloc to serve later requests for large amounts of memory)