Abstract Data Types (Adts), After More on the Heap Preparing for The

Abstract Data Types (Adts), After More on the Heap Preparing for The

Preparing for the Midterm Exam • Exam logistics o Date/time: Thursday October 26 in lecture o Open books, open notes, open mind, but not open laptop/PDA Abstract Data Types (ADTs), o Covering material from lecture, precept, and reading, but not tools After More on the Heap • Preparing for the midterm o Lecture and precept materials available online o Course textbooks, plus optional books on reserve Prof. David August o Office hours and the course listserv o Old midterm exams on the course Web site COS 217 1 2 A Little More About the Heap… Example: Read a Line (or URL) • Memory layout of a C program • Write a function that reads a word from stdin o Text: code, constant data o Read from stdin until encountering a space, tab, ‘\n’, or EOF o Data: initialized global & static variables o Output a pointer to the sequence of characters, ending with ‘\0’ BSS: uninitialized global & static variables 0 o Text • Example code (very, very buggy) o Heap: dynamic memory Stack: local variables Data o #include <stdio.h> • Purpose of the heap BSS o Memory allocated explicitly by the programmer Heap int main(void) { o Using the functions malloc and free char* buf; • But, why would you ever do this??? scanf(“%s”, buf); o Glutton for punishment??? printf(“Hello %s\n”, buf); return 0; } Stack 0xffffffff 3 4 Problem: Need Storage for String Problem: Input Longer Than Array • Improving the code • Improving the code o Allocate storage space for the string o Don’t allow input that exceeds the array size Example: define an array o • Example (better, but not perfect) • Example (still somewhat buggy) #include <stdio.h> #include <stdio.h> int main(void) { int main(void) { char buf[64]; char buf[64]; if (scanf(“%63s”, buf) == 1) scanf(“%s”, buf); printf(“Hello %s\n”, buf); printf(“Hello %s\n”, buf); else return 0; fprintf(stderr, Input error\n”); } return 0; 5 } 6 Problem: How Much Storage? Really Solving the Problem • Improving the code • Remaining problems o Finding out how much space you need from the user o User can’t input long words o Allocate exactly that much space, to avoid wasting o Storage wasted on short words • Beginning of the example (is this really better?) • But, how do we proceed? o Too little storage, and we’ll run pass the end or have to truncate int main(void) { Yet, we don’t know how big the word might be int n; o char* buf; • The gist of a solution Pick a storage size (“line_size”) and read up to that length printf(“Max size of word: “); o scanf(“%d”, &n); o If we stay within the limit, we’re done o If the user input exceeds the space, we can buf = malloc((n+1) * sizeof(char)); – Allocate space for another line, and keep on reading scanf(“%s”, buf); – At the end, allocate one big buffer and copy all the lines into it printf(“Hello %s\n”, buf); return 0; } 7 8 Abstract Data Type (ADT) • An ADT module provides: o Data type o Functions that operate on the type • Client does not manipulate the data representation directly Abstract Data Types (ADTs) o The client should just call functions • “Abstract” because the observable results (obtained by client) are independent of the data representation • Programming language support for ADT o Ensure that client cannot possibly access representation directly o C++, Java, other object-oriented languages have private fields o C has opaque pointers 9 10 An ADT Example: Stacks Stack Interface (stack.h) • LIFO: Last-In, First-Out #ifndef STACK_INCLUDED What’s this for? • Like the stack of trays at the cafeteria #define STACK_INCLUDED o “Push” a tray onto the stack o “Pop” a tray off the stack typedef struct Item *Item_T; typedef struct Stack *Stack_T; • Useful in many contexts extern Stack_T Stack_new(void); extern int Stack_empty(Stack_T stk); extern void Stack_push(Stack_T stk, Item_T item); extern Item_T Stack_pop(Stack_T stk); #endif 11 12 Notes on stack.h Stack Implementation: Array •Type Stack_T is an opaque pointer stack.c Clients can pass Stack_T around but can’t look inside #include <assert.h> o #include <stdlib.h> •Type Item_T is also an opaque pointer #include “stack.h” o … but defined in some other ADT enum {CAPACITY = 1000}; is a disambiguating prefix • Stack_ struct Stack { o A convention that helps avoid name collisions int count; Item_T data[CAPACITY]; }; Stack_T Stack_new(void) { Stack_T stk = malloc(sizeof(*stk)); assert(stk != NULL); stk->count = 0; return stk; } 13 14 Careful Checking With Assert Stack Implementation: Array (Cont.) stack.c int Stack_empty(Stack_T stk) { #include <assert.h> assert(stk != NULL); #include <stdlib.h> return (stk->count == 0); #include “stack.h” } void Stack_push(Stack_T stk, Item_T item) { enum {CAPACITY = 1000}; assert(stk != NULL); assert(stk->count < CAPACITY); struct Stack { stack->data[stack->count] = item; int count; stack->count++; Item_T data[CAPACITY]; }; } Item_T Stack_pop(Stack_T stk) { Stack_T Stack_new(void) { assert(stk != NULL); Stack_T stk = malloc(sizeof(*stk)); assert(stk->count > 0); assert(stk != NULL); stk->count--; stk->count = 0; Make sure stk!=NULL, return stk->data[stk->count]; return stk; or halt the program! } } 15 16 Problems With Array Implementation Linked List Would be Better… CAPACITY too large: waste memory struct Stack { val int val; data wasted space next struct Stack *next; } *head; CAPACITY too small: head empty stack data push(1); push(2); push(3); assertion failure (if you were careful) buffer overrun (if you were careless) 3 2 1 head 17 18 Popping and Pushing Stack Implementation: Linked List 3 2 1 stack.c head #include <assert.h> #include <stdlib.h> pop( ); #include “stack.h” 3 2 1 struct Stack {struct List *head;}; struct List {Item_T val; struct List *next;}; head Stack_T Stack_new(void) { Stack_T stk = malloc(sizeof(*stk)); 4 push(4); assert(stk != NULL); stk->head = NULL; return stk; 3 2 1 } head 19 20 Stack Implementation: Linked List stack.c, continued int Stack_empty(Stack_T stk) { assert(stk != NULL); Item_T Stack_pop(Stack_T stk) { return (stk->head == NULL); Item_T x; } struct List *p; void Stack_push(Stack_T stk, Item_T item) { assert(stk != NULL); Stack_T t = malloc(sizeof(*t)); assert(stk->head != NULL); assert(t != NULL); x = stk->head->val; assert(stk != NULL); p = stk->head; t->val = item; t->next = stk->head; stk->head = stk->head->next; stk->head = t; free(p); } return x; Draw pictures of } Draw pictures of these data structures! these data structures! 21 22 Client Program: Uses Interface Problem: Multiple Kinds of Stacks? client.c • Good, but still not flexible enough What about a program with multiple kinds of stacks #include <stdio.h> o E.g., a stack of books, and a stack of pancakes #include <stdlib.h> o But, can you can only define Item_T once #include “item.h” o #include “stack.h” • Solution in C, though it is a bit clumsy o Don’t define Item_T (i.e., let it be a “void *”) int main(int argc, char *argv[]) { o Good flexibility, but you lose the C type checking int i; Stack_T s = Stack_new(); typedef struct Item *Item_T; for (i = 1; i < argc; i++) typedef struct Stack *Stack_T; Stack_push(s, Item_new(argv[i])); while (!Stack_empty(s)) extern Stack_T Stack_new(void); Item_print(Stack_pop(s)); extern int Stack_empty(Stack_T stk); return 0; extern void Stack_push(Stack_T stk, void *item); extern void *Stack_pop(Stack_T stk); } 23 24 Conclusions •Heap o Memory allocated and deallocated by the programmer o Useful for making efficient use of memory o Useful when storage requirements aren’t known in advance Backup Slides • Abstract Data Types (ADTs) on Void Opaque Pointers o Separation of interface and implementation o Don’t even allow the client to manipulate the data directly o Example of a stack – Implementation #1: array – Implementation #2: linked list o Backup slides on void pointers follow… 25 26 stack.h (with void*) Stack Implementation (with void*) stack.c #ifndef STACK_INCLUDED #define STACK_INCLUDED #include <assert.h> #include <stdlib.h> typedef struct Item *Item_T; #include “stack.h” typedef struct Stack *Stack_T; struct Stack {struct List *head;}; extern Stack_T Stack_new(void); extern int Stack_empty(Stack_T stk); struct List {void *val; struct List *next;}; extern void Stack_push(Stack_T stk, void *item); extern void *Stack_pop(Stack_T stk); Stack_T Stack_new(void) { Stack_T stk = malloc(sizeof(*stk)); /* It’s a checked runtime error to pass a NULL Stack_T to any routine, or call Stack_pop with an empty stack assert(stk); */ stk->head = NULL; return stk; #endif } 27 28 stack.c (with void*) continued stack.c (with void*) continued int Stack_empty(Stack_T stk) { assert(stk != NULL); void *Stack_pop(Stack_T stk) { return stk->head == NULL; void *x; } struct List *p; assert(stk != NULL); void Stack_push(Stack_T stk, void *item) { assert(stk->head != NULL); Stack_T t = malloc(sizeof(*t)); x = stk->head->val; assert(t != NULL); p = stk->head; assert(stk != NULL); stk->head = stk->head->next; t->val = item; free(p); t->next = stk->head; return x; stk->head = t; } } 29 30 Client Program (With Void) Structural Equality Testing Suppose we want to test two stacks for equality: client.c (with void*) #include <stdio.h> #include <stdlib.h> int Stack_equal(Stack_T s1, Stack_T s2); #include “item.h” #include “stack.h” How can this be implemented? int main(int argc, char *argv[]) { int Stack_equal(Stack_T s1, Stack_T s2) { int i; Stack_T s = Stack_new(); return (s1 == s2); for (i = 1; i < argc; i++) } Stack_push(s, Item_new(argv[i])); while (!Stack_empty(s)) We want to test whether two stacks are equivalent stacks, printf(“%s\n”,Stack_pop(s)); not whether they are the same stack. return 0; } 31 32 Almost, But Not Quite... Item ADT Provides Equal Test How about this: How about this: int Stack_equal(Stack_T s1, Stack_T s2) { int Stack_equal(Stack_T s1, Stack_T s2) { struct List *p, *q; struct List *p, *q; for (p=s1->head, q=s2->head; p && q; for (p=s1->head, q=s2->head; p && q; p=p->next, q=q->next) p=p->next, q=q->next) if ( ! Item_equal(p->val, q->val)) if (p->val != q->val) return 0; return 0; return p==NULL && q==NULL; return p==NULL && q==NULL; } } This is good for the “Item_T” version of stacks (provided the This is better, but what we want to test whether s1->val is Item interface has an Item_equal function), but what about equivalent to s2->val, not whether it is the same.

View Full Text

Details

  • File Type
    pdf
  • Upload Time
    -
  • Content Languages
    English
  • Upload User
    Anonymous/Not logged-in
  • File Pages
    9 Page
  • File Size
    -

Download

Channel Download Status
Express Download Enable

Copyright

We respect the copyrights and intellectual property rights of all users. All uploaded documents are either original works of the uploader or authorized works of the rightful owners.

  • Not to be reproduced or distributed without explicit permission.
  • Not used for commercial purposes outside of approved use cases.
  • Not used to infringe on the rights of the original creators.
  • If you believe any content infringes your copyright, please contact us immediately.

Support

For help with questions, suggestions, or problems, please contact us