430 likes | 536 Views
Chapter 11. Storage Allocation and Linked Lists. int n, float x; compile-time storage allocation: storage is allocated at compile time before run time. Run-time storage allocation: storage is allocated at run time Use malloc calloc. Compile-Time & Run-Time Storage Allocation. In C:
E N D
Chapter 11 Storage Allocation and Linked Lists
int n, float x; compile-time storage allocation: storage is allocated at compile time before run time Run-time storage allocation: storage is allocated at run time Use malloc calloc Compile-Time & Run-TimeStorage Allocation
In C: Storage is allocated when variables are defined compiler-time storage allocation … int abc; struct client clients[100]; program to run for all applications maximum size of definition has to be used #define maxsize 200 … float a[maxsize][maxsize]; …
int* ptr; ptr = malloc (sizeof(int)); malloc( sizeof (datatype)) returns a pointer to the allocated storage returns NULL if fails Run-time allocation: char* alpha; int* num; char r; r=getchar(); if(r==‘c’) alpha=malloc(sizeof(char)); else num=malloc(sizeof(int)); malloc
typedef struct complex { float real; float imag; } Complex; Complex* ptrc; ptrc = malloc(sizeof(Complex)); ptrc -> real=3.14; ptrc -> imag = 2.11; free (ptrc); Allocate structure at run time
Run-time storage allocation (dynamic memory allocation) dynamically allocate and deallocate memory when required • ptr = malloc ( number_of_bytes_to_be_allocated); • ptr: if successful a pointer to the allocated storage • if unsufficient memory is available null ptr • traditionally, malloc() returns the address of type pointer-to-char • ptr = malloc(n*sizeof(float));
number_of_bytes_to_be_allocated: • eg. 100 sizeof (datatype) • sizeof (variable) ptr = malloc ( 100); ptr = malloc (sizeof (int)) m=malloc( sizeof(complex1)); struct complex { float a; float b; }complex1;
calloc int *ptr1,*ptr2; ptr1 = malloc(sizeof(int)); ptr2 = calloc(20,sizeof(int)); • Allocates 20 int storage cells • Returns the address of first cell • Returns NULL if fails
Two ways to access storage • compile-time storage (name, pointer) int a, *a_ptr; a_ptr=&a; printf(“%d %d “, a, *a_ptr); • running-time storage (pointer only) a_ptr = malloc(sizeof(int));
int* ptr; ptr = malloc (sizeof(int)); *ptr =999; ptr = malloc (sizeof(int)); *ptr = -777; printf(“%d”, *ptr); Prints -777 The cell storing 999 cannot be accessed (garbage) Remedy int *ptr1,*ptr2; ptr1 = malloc (sizeof(int)); *ptr1=999; ptr2 = malloc (sizeof(int)); *ptr2 = -777; printf(“%d%d”, *ptr1,*ptr2); Garbage
Release run-time storage • free(*ptr); • deallocate the space pointed to by ptr • ptr • points to a block of memory previously allocated by calloc() or malloc() • int *ptr; • … • ptr = malloc (sizeof(int)); • … • free(ptr);
#include <stdio.h> #include <stdlib.h> typedef int** Matrix; /* hide the int** data type */ void store( char* file, Matrix m1, Matrix m2, int n ), mult( Matrix m1, Matrix m2, Matrix m3, int n ), print( Matrix m, int n ), freeMatrix( Matrix m, int n ); Matrix createMatrix( int n ); main() { int n; char filename[ FILENAME_MAX ]; Matrix m1, m2, m3; /* prompt user for side and file name */ printf( "Matrix size and file name: " ); scanf( "%d %s", &n, filename ); /* create the matrices */ m1 = createMatrix( n ); m2 = createMatrix( n ); m3 = createMatrix( n ); if ( NULL == m1 || NULL == m2 || NULL == m3 ) { /* success? */ fprintf( stderr, "Insufficient storage. Exiting...\n\n" ); exit( EXIT_SUCCESS ); } store( filename, m1, m2, n ); /* read data into m1 and m2 */ mult( m1, m2, m3, n ); /* m3 = m1 * m2 */ print( m3, n ); /* print m3 */ freeMatrix( m1, n ); freeMatrix( m2, n ); freeMatrix( m3, n ); /* free storage for m1, m2, and m3 */ return EXIT_SUCCESS; }
/* Create a matrix of side n, i.e., a matrix * that contains n x n int cells. */ Matrix createMatrix( int n ) { Matrix m; int i; m = ( Matrix ) malloc( n * sizeof ( int* ) ); if ( NULL == m ) return NULL; for ( i = 0; i < n; i++ ) { m[ i ] = ( int* ) malloc( n * sizeof ( int ) ); if ( NULL == m[ i ] ) { freeMatrix( m, i ); /* avoid garbage */ return NULL; } } return m; }
/* Free all storage associated with matrix m. */ void freeMatrix( Matrix m, int n ) { int i; for ( i = 0; i < n; i++ ) free( m[ i ] ); free( m ); }
/* Multiply matrix m1 by matrix m2, storing the product in matrix m3, where all three matrices are n by n in size: void mult( Matrix m1, Matrix m2, Matrix m3, int n ) { int i, j, k; for ( i = 0; i < n; i++ ) for ( j = 0; j < n; j++ ) { m3[ i ][ j ] = 0; for ( k = 0; k < n; k++ ) m3[ i ][ j ] += m1[ i ][ k ] * m2[ k ][ j ]; } }
Linked Lists Single linked list Linked list N1, N2,…, Nn nodes plus address of N1 Nk node contains the address of N(k+1) node Nn node (last) contains null
typedef struct cat { char name[10]; struct cat* next; } CAT; CAT cat1,cat2,cat3 CAT *start,*ptr strcpy(cat1.name,”abc”); strcpy(cat2.name,”nbc”); strcpy(cat3.name,”cbs”); cat1.next=&cat2; cat2.next=&cat3; cat3.next=NULL; start=&cat1; ptr=start; printf(“%s”, ptr-> name) ptr=ptr -> next printf(“%s”, ptr -> name) Prints abcnbc Example
typedef struct cat { char name[10]; struct cat* next; } CAT; CAT* get_cat(void); main() { CAT* start; start=get_cat(); } CAT* get_cat(void) CAT *curr,*first; int r; curr = first =malloc(sizeof(CAT)); printf(“\n enter name:”); scanf(“%s”,curr -> name); printf(“\nadd another?(1=y,0=no)”); scanf(“%d”,&r); Example-modified
while ( r ) { curr -> next =malloc(sizeof(CAT)); curr = curr -> next; printf(“\n enter name:”); scanf(“%s”,curr -> name); printf(“\nadd another?(1=y,0=no)”); scanf(“%d”,&r); } curr ->next=NULL; return first This modified code assigns storage at run time and does not require setting maximum number of storage cells. That is, the number of cells is flexible. Example-modified
typedef struct node { int num; struct node* next; } NODE; /* find the n-th node */ NODE* find_n(NODE* ptr, int n) /* ptr is pointer to first node */{ if (n<1) return NULL; while (- - n && ptr != NULL) ptr =ptr -> next; return ptr; } Let n=2 and assume that we have 3 nodes --n =1 ptr not NULL ptr = ptr ->next --n = 0 return ptr points to the second node Operations on Linked Listfind ptr of n-th node
NODE* find_n(NODE* ptr, int n); NODE* add_n(NODE* ptr, NODE* new, int n) { NODE pred; if (n==1){ new ->next = ptr; return new; } ptr = pointer to first node new = pointer to new node to be added n=position of the new node in the revised list returns pointer to the first node returns NULL if fails Add a node to existing linked list
pred=find_n(ptr, n-1); if(pred == NULL) return NULL; new ->next = pred -> next; pred -> next = new; return ptr; } Before after new n-1 n
NODE* find_n(NODE* ptr, int n); NODE* del_n(NODE* ptr, int n) { NODE *pred, *old; if (n==1){ old = ptr; ptr =ptr -> next; } else ptr = pointer to first node n=position of the node to be deleted returns pointer to the first node Delete a node to existing linked list
pred=find_n(ptr, n-1); if(pred == NULL||pred->next ==NULL) return ptr; old = pred -> next; pred -> next = old->next; free(old) return ptr; } old n-1 n
ELEE 3331 "Sample" Exam 2 I.(10pts)Select the best answer to each of the following concerning ANSI C and circle your choice. A. Which type of variables are initialized to zero by the C compiler? 1. auto 2. register 3. local 4. internal 5. static 6. all variables are initialized to zero Ans: 5
B. Given the declaration float x, *z=&x; which scanf would successfully read a float value into x? 1. scanf(“%f”,x); 2. scanf(“%f”,z); 3. scanf(“%f”,*z); 4. scanf(“%f”,&z); 5. all of the above Ans: 2
C. The sizeof operator used with an array name will give 1. the number of elements declared to be in the array 2. the number of elements actually in the array 3. the number of bytes allocated to the array 4. the number of bits allocated to the array 5. the number of dimensions of the array Ans: 3
D. Given the following declaration char t1[5]={‘a’},*t2=t1,*t3=“Lois”,*t4=“Rhoda Baggs”; which of the following statements would be valid? 1. t1 = t3; 2. t2 = t3; 3. *t2 = t4; (there was a typo here, there was supposed to have been the * in front) 4. t3 = &t4; Ans: 2
E. If temp is a member of the structure weather and the statement addweat = &weather; has been executed, then which of the following correctly references temp? 1. weather->temp; 2. (*weather).temp; 3. addweat.temp; 4. addweat->temp; Ans: 4
II.(6pts)Short answer 1. Assuming the first value in the array s is contained in s[0], give two different notations for referring to the 3rd element of s. s[2] *(s+2)
2. Given the declaration: int x = 25, *y; The statement *y = x; results in an “access violation” error. Explain the problem and indicate how it could be corrected, assuming we want y to point to a different memory location than x. no memory is allocated for what y points to so either precede with y=(*int)malloc(sizeof(int)); or declare separate variable and have z point to it first: {int z; y=&z;}
III.Indicate the output that would be produced by each of the following. Consider each case separately. A.(6pts) #include <stdio.h> #include <string.h> #include <math.h> int k = 55; main( ) { int i = 1, j=4, m; int f(int ); m = f(i); printf("\n %d %d %d \n", j,m,k); } int f(int j) {static int k = 2; if(j<3) k+=f(j+1); return(k);} f(1) k=2; k=k+f(2) return k; f(2) k=k+f(3) return k; f(3) k=2 return k; output: 4 8 55
2222 2222 3.1 7.4 2.8 1.9 6.3 9.8 2225 2225 B.(8pts) #include <stdio.h> main( ) { float a[2][3] = {{3.1,7.4,2.8},{1.9,6.3,9.8}}; printf(“\n%f %f %f %f \n”,*(*(a+1)+1),*(*(a)+1),*(*(a+1)),*(*(a)+1)+1); } 3.1 7.4 2.8 1.9 6.3 9.8 * -- point to raw **-- point to column **a *(*a+1) *a output: 6.3 7.4 1.9 8.4 *(a+1)
merry.dat 1 pole = 11/2 yard one gram = 0.035 ounces 1 gallon equals 3.79 liters 1 electron = 1/1837 photons C.(4pts) #include <stdio.h> #include <string.h> #include <math.h> main( ) { int n; float q1,q2; char u1[16], u2[16]; FILE *fptr; fptr=fopen(“merry.dat”,”r”); while((n=fscanf(fptr,"%f %15s = %f %15s", &q1,u1,&q2,u2))!=EOF) { printf("%d %f %f %s %s \n",n,q1,q2,u1,u2); fscanf(fptr,"%*[^\n]"); } fclose(fptr); } Output: 4 1.0 11.0 pole /2 0 1.0 11.0 pole /2 2 1.0 11.0 gallon /2 4 1.0 1.0 electron /1837
D.(10pts)Show exact spacing for this output by filling in the grid below main( ) {char ch = 'X'; char st[ ]= "Hello World"; int k = 52; float f = 12.978; double d = -97.4583; printf("%3d and %7.2f%c\n",k,f,ch); printf("%-14.5s\n\n",st); printf("%8.2f",d); printf("%.2f%.2e",f,f);} output cols: 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 line 1 _ 5 2 _ a n d _ _ _ 1 2 . 9 8 X _ _ _ _ _ _ _ _ _ _ _ _ _ _ line 2 H e l l o _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ line 3 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ line 4 _ _ - 9 7 . 4 6 1 2 . 9 8 1 . 3 0 e + 0 1 _ _ _ _ _ _ _ _ _
1 2 4 3 6 7 8 9 IV.(15pts)Long Integers Suppose the following declaration is available globally: struct longint { int digit; int power; struct longint *next; }; This template has been used in creating a linked list representation of large integers, where the pointer to the list "points" to the least significant digit. For example, the number 3,421,000,000 would be represented as Write a C function whose prototype is: struct longint *bigger(struct longint *int1, struct longint *int2); which will accept pointers to the beginning of two large integer linked lists and return a pointer to the beginning of the list which represents the larger integer. start
struct longint *bigger(struct longint *in1,struct longint *in2) {int n1=0,n2=0,i; struct longint *p1,*p2; p1 = in1; while(p1->next!=NULL) {n1++;p1=p1->next;} p2=in2; while(p2->next!=NULL) {n2++;p2=p2->next;} if(p1->power>p2->power)return in1; if(p2->power>p1->power)return in2; if(p1->digit>p2->digit)return in1; if(p2->digit>p1->digit)return in2;
while(n1>=0&&n2>=0) { p1=in1; for(i=0;i<n1;i++) p1=p1->next; p2=in2; for(i=0;i<n2;i++)p2=p2->next; if(p1->power>p2->power)return in1; if(p2->power>p1->power)return in2; if(p1->digit>p2->digit)return in1; if(p2->digit>p1->digit)return in2; n1--;n2--; } if(n1<0&&n2>=0)return(in2); if(n2<0&&n1>=0)return(in1); if(n1<0&&n2<0) printf("\n values same\n"); return(in1); }
V.(15pts)Cold Spots Suppose that the following declarations are available globally: struct citytemps { char city[35]; float temp[366];}; struct coldcnts { char city[35]; int count;}; Suppose further that a data file named cold.dat has been prepared containing the names of each city in Texas, along with that city's minimum temperatures(in Fahrenheit) for each day of the past year. The name of each city starts on a new line and is terminated by a semicolon (;). Following the name are the minimum temperatures for that city. For example: Austin; 44 48 38 ... Beeville; 38 37 35 ... San Antonio; 51 49 40 ..
Write a complete C program that will input the data into an array of type struct citytemps, where each array element corresponds to a city. Then create a new array of type struct coldcnts, consisting of the name of the city and the number of days that city's minimum temperature was at or below freezing. Do not include in this new array any cities which had all days above freezing. Then print this new array, one city per line. #include <stdio.h> #include <string.h> struct citytemps {char city[35]; float temp[366];}; struct coldcnts {char city[35]; /*not required*/ int count;};
main( ) {FILE *fin,*fout; struct citytemps cities[500]; struct coldcnts freeze[500]; int i,j,k,nfrz=0,ncity=0,done=0,nv; float t; char name[35]; fin=fopen("city.dat","r"); fout=fopen("city.out","w"); while(done==0) {nv=fscanf(fin,"%[^;];",name); if(name[1]=='\0')nv=0; if(nv>0) {strcpy(cities[ncity].city,name); fprintf(fout,"\n city %d %s:",ncity+1,cities[ncity].city); for(i=0;i<366;i++) {fscanf(fin,"%f",&t); cities[ncity].temp[i]=t; } ncity++; }
else done=1; } for(i=0;i<ncity;i++) {k=0; for(j=0;j<366;j++) {if(cities[i].temp[j]<=32) k++;} if(k>0) {freeze[nfrz].count=k; strcpy(freeze[nfrz].city,cities[i].city); nfrz++;} } for(i=0;i<nfrz;i++) fprintf(fout,"\n %s %d",freeze[i].city,freeze[i].count); }