890 likes | 990 Views
Unit II : Pointers in C and file handling. Contents :
E N D
Unit II : Pointers in C and file handling Contents : Pointer, pointer to pointer ,pointer to single and multidimensional arrays, array of pointers , string and structure manipulation using pointers , pointer to functions. Pointer to file structure and basic operations on file, functions used for text and binary file handling in C. • Objective : • To understand the basic operations with pointers. • To make the student understand the concept of static and dynamic memory allocation and conservation of memory for the programs. • To make the student know how to access the underlining hardware and also to understand the disadvantage of it. • To introduce the student to access and manipulate data stored in disk file.
Teaching Plan for Unit2 • Pointer Variable Declarations and Initialization • Relationship Between Pointers and Arrays • String Pointers • Arrays of Pointers • Pointer to an array • Pointer to Pointer • Function returning Pointer • Pointer to Function • Dynamic memory allocation for 1 D array • Dynamic memory allocation for 1 D array • Pointer to structure • File Handling • Command Line arguments • University Solved Question Paper
Pointer Variable Declarations and Initialization • Pointer declarations • * used with pointer variables int *myPtr; • Declares a pointer to an int (pointer of type int *) • Multiple pointers require using a * before each variable declaration int *myPtr1, *myPtr2; • Can declare pointers to any data type • Initialize pointers to 0, NULL, or an address • 0 or NULL– points to nothing (NULL preferred)
yptr y y 5 yPtr Address of y is value of yptr 500000 600000 600000 5 • & (address operator) • Returns address of operand int y = 5; int *yPtr; yPtr = &y; // yPtr gets address of y yPtr “points to” y
Array Example Using a Pointer int x[4] = {12, 20, 39, 43}, *y; y = &x[0]; // y points to the beginning of the array printf("%d\n", x[0]); // outputs 12 printf("%d\n", *y); // also outputs 12 printf("%d\n", *y+1); // outputs 13 (12 + 1) printf("%d\n", (*y)+1); // also outputs 13 printf("%d\n", *(y+1)); // outputs x[1] or 20 y+=2; // y now points to x[2] printf("%d\n", *y); // prints out 39 *y = 38; // changes x[2] to 38 printf("%d\n", *y-1); // prints out x[2] - 1 or 37 *y++; // sets y to point at the next array element printf("%d\n", *y); // outputs x[3] (43) (*y)++; // sets what y points to to be 1 greater printf("%d\n", *y); // outputs the new value of x[3] (44)
Relationship Between Pointers and Arrays • Arrays and pointers closely related • Array name like constant pointer • Pointers can do array subscripting operations • Accessing array elements with pointers • Element b[ n ] can be accessed by *( bPtr + n ) • Called pointer/offset notation • Addresses • &b[ 3 ] same as bPtr + 3 • Array name can be treated as pointer • b[ 3 ] same as *( b + 3 ) • Pointers can be subscripted (pointer/subscript notation) • bPtr[ 3 ] same as b[ 3 ]
1 // 20.cpp 2 // Using subscripting and pointer notations with arrays. 3 4 #include <iostream> 5 6 using std::cout; 7 using std::endl; 8 9 int main() 10 { 11 int b[] = { 10, 20, 30, 40 }; 12 int *bPtr = b; // set bPtr to point to array b 13 14 // output array b using array subscript notation 15 cout << "Array b printed with:\n" 16 << "Array subscript notation\n"; 17 18 for ( inti = 0; i < 4; i++ ) 19 cout << "b[" << i << "] = " << b[ i ] << '\n';
21 // output array b using the array name and 22 // pointer/offset notation 23 cout << "\nPointer/offset notation where " 24 << "the pointer is the array name\n"; 25 26 for ( intoffset1 = 0; offset1 < 4; offset1++ ) 27 cout << "*(b + " << offset1 << ") = " 28 << *( b + offset1 ) << '\n'; 29 30 // output array b using bPtr and array subscript notation 31 cout << "\nPointer subscript notation\n"; 32 33 for ( intj = 0; j < 4; j++ ) 34 cout << "bPtr[" << j << "] = " << bPtr[ j ] << '\n'; 35 36 cout << "\nPointer/offset notation\n"; 37
38 // output array b using bPtr and pointer/offset notation 39 for ( intoffset2 = 0; offset2 < 4; offset2++ ) 40 cout << "*(bPtr + " << offset2 << ") = " 41 << *( bPtr + offset2 ) << '\n'; 42 43 return0; // indicates successful termination 44 // All Notations used -> b[ i ] ,*( b + i ) ,* ( i +b), i [ b ] 45 } // end main Array b printed with: Array subscript notation b[0] = 10 b[1] = 20 b[2] = 30 b[3] = 40
Pointer/offset notation where the pointer is the array name *(b + 0) = 10 *(b + 1) = 20 *(b + 2) = 30 *(b + 3) = 40 Pointer subscript notation bPtr[0] = 10 bPtr[1] = 20 bPtr[2] = 30 bPtr[3] = 40 Pointer/offset notation *(bPtr + 0) = 10 *(bPtr + 1) = 20 *(bPtr + 2) = 30 *(bPtr + 3) = 40
1D String Array and Pointers Example main() { char name[]=“scoe”; inti; while(name[i]) { printf(“\n %c %c %c %c”, name[i], *(name+i), *(i+name), i[name]); i++; } } Output: ssss cccc oooo eeee
Implementing String Operations intstrcmp(char *s, char *t) { inti; for(i=0;s[i] = = t[i];i++) if(s[i] = = ‘\0’) return 0; return s[i] – t[i]; } intstrlen(char *s) { int n; for(n = 0; *s != ‘\0’; s++) n++; return n; } intstrcmp(char *s, char *t) { for( ; *s = = *t; s++, t++) if(*s = = ‘\0’) return 0; return *s - *t; }
Implementing String Operations (Contd..) void strcpy(char *s, char *t) { while((*s = *t) != ‘\0’) { s++; t++; } } void strcpy(char *s, char *t) { inti = 0; while((s[i] = t[i]) != ‘\0’) i++; } void strcpy(char *s, char *t) { inti; while( *(*t+i)!=‘\0’) { *(s+i)= *( t+i); s++ ;t++; i++; } *( s + i )= ‘\0’; } void strcpy(char *s, char *t) { while((*s++ = *t++) != ‘\0’); }
’\0’ ’\0’ ’\0’ ’\0’ ’n’ ’d’ ’o’ ’u’ ’a’ ’s’ ’d’ ’b’ ’m’ ’H’ ’s’ ’a’ ’D’ ’i’ ’a’ ’s’ ’l’ ’C’ ’r’ ’s’ ’S’ ’p’ ’e’ ’t’ ’e’ suit[0] suit[1] suit[2] suit[3] Arrays of Pointers • Arrays can contain pointers • For example: an array of strings char *suit[ 4 ] = { "Hearts", "Diamonds", "Clubs", "Spades" }; • Strings are pointers to the first character • char *– each element of suit is a pointer to a char • The strings are not actually stored in the array suit, only pointers to the strings are stored • suit array has a fixed size, but strings can be of any size
Arrays of Pointers ( contd..) inti; char *college[]= {“scoe",”skn",”nbn"}; for (i= 0; i < 3; i++} { printf ("String %d is %s\n",i+1,college[i]); } Will print: String 1 is scoe String 2 is skn String 3 is nbn
Arrays of Pointer char *x[ ] = {"hello", "goodbye", "so long", "thanks for all the fish"}; // our array of strings x is a set of 4 pointers char *y; // let y be a pointer to a char so it can be used to move through a single string inti; for(i=0;i<4;i++) // iterate for each string in x { y = x[i]; // x[i] is an array, x is really a pointer, so this sets y to x’s starting addr. while(*y!='\0') // while the thing y points to is not the end of a string { printf("%c", *y); // print what y points to y++; // and go on to the next char in x } printf("\n"); // separate strings in output with \n }
Pointer to an array main() { int a[][4]={5,7,5,9,4,6,3,1,2,9,0,6}; int *p; int (*q)[4]; p=(int*)a; q=a; printf(:\n %u %u”,p,q); p++; q++; printf(“\n %u %u”,p,q); } Output : 65500 65500 65502 65508
Pointers to Pointers A pointer can also be made to point to a pointer variable (but the pointer must be of a type that allows it to point to a pointer) Example: int V = 101; int *P = &V; /* P points to int V */ int **Q = &P; /* Q points to int pointer P */ printf(“%d %d %d\n”,V,*P,**Q); /* prints 101 3 times */
Pointers to Pointers(Contd..) char **marker; char course[0]=“numerical “,course[1]=“methods”; marker=&course[0]; //pointer to course[0] which points to numerical marker ++; //points to course[1] which points to methods (*marker)++; //will point to ‘e’
Function Returning Pointers float *findMax(float A[], int N) { int I; float *theMax = &(A[0]); for (I = 1; I < N; I++) if (A[I] > *theMax) theMax = &(A[I]); return theMax; } void main() { float A[5] = {0.0, 3.0, 1.5, 2.0, 4.1}; float *maxA; maxA = findMax(A,5); *maxA = *maxA + 1.0; printf("%.1f %.1f\n",*maxA,A[4]); }
Function Returning Pointers (Contd..) /* function to generate and return random numbers. */ int * getRandom( ) { static int r[10]; inti; /* set the seed */ srand( (unsigned)time( NULL ) ); for ( i = 0; i < 10; ++i) { r[i] = rand(); printf("%d\n", r[i] ); } return r; } /* main function to call above defined function */ int main () { /* a pointer to an int */ int *p; inti; p = getRandom(); for ( i = 0; i < 10; i++ ) { printf("*(p + [%d]) : %d\n", i, *(p + i) ); } return 0; }
Function Returning Pointers (Contd..) main() { int *p; int *fun(); p=fun(); printf(“\n %u”,p); printf(“\n %d”,*p); } int *fun() { inti=20; return (&i); } Output :Garbage value Declare static inti=20 in fun()
Declarations Examples int * E [5] E is a 1D array of size 5 of pointers to ints int (* F) [5] F is a pointer to a 1D array of size 5 of ints char * H (…) H is a function returning a pointer to a char int *p(char *a) p is function that accept pointer to cahr argument & return pointer to integer • int (*p)(char *a) p is pointer to a function that accept pointer to char • argument & return an integer quantity • Int (*p)(char (*a)[]) p is pointer to a function that accept pointer to char • array as a argument & return an integer quantity • int *(*p) (char *a[]) p is pointer to a function that accept array of char • as a argument & return a pointer to an integer
Pointers to Functions • Example: bubblesort • Function bubble takes a function pointer • bubble calls this helper function • this determines ascending or descending sorting • The argument in bubblesort for the function pointer: int ( *compare )( int a, int b ) tells bubblesort to expect a pointer to a function that takes two ints and returns an int • If the parentheses were left out: int *compare( int a, int b ) • Defines a function that receives two integers and returns a pointer to a int
ascending and descending return true or false. bubble calls swap if the function call returns true. Notice how function pointers are called using the dereferencing operator. The * is not required, but emphasizes that compare is a function pointer and not a function.
Pointers to Functions intfunc (int a, int b) { printf("\n a = %d\n",a); printf("\n b = %d\n",b); return 0; } int main(void) { int(*fptr)(int,int); // Function pointer fptr = func; // Assign address to function pointer func(2,3); fptr(2,3); return 0; } Output: a = 2 b = 3 a = 2 b = 3
Passing Arrays • Arrays are passed “by reference”. • When an array is passed to a function, the address of the array is copied onto the function parameter. Since an array address is a pointer, the function parameter may be declared in either fashion. E. g.intsumArray( int a[ ], int size)is equivalent tointsumArray( int *a, int size) • The code in the function is free to use “a” as an array name or as a pointer as it sees fit. • The compiler always sees “a” as a pointer. In fact, any error messages produced will refer to “a” as an int *
sumArray intsumArray( int a[ ], int size) { int k, sum = 0; for (k = 0; k < size; k++) sum += a[ k ]; return sum; } intsumArray( int a[ ], int size) { int k, sum = 0; for (k = 0; k < size; k++) sum += *(a + k); return sum; } intsumArray( int a[ ], int size) { int k, sum = 0; for (k = 0; k < size; k++) } sum += *a; ++a; } return sum; }
malloc • Prototype: intmalloc(int size); • function searches heap for size contiguous free bytes • function returns the address of the first byte • programmers responsibility to not lose the pointer • programmers responsibility to not write into area past the last byte allocated • Example: Key char *ptr; ptr = malloc(4); // new allocation new allocation 10 ptr 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
free • Prototype: int free(intptr); • releases the area pointed to by ptr • ptr must not be null • trying to free the same area twice will generate an error • Example: free(ptr); Key 2 5 p2 free memory p1 initial memory 0 1 2 3 4 5 6 7 null 2 p1 p2 after free
sizeof() Function • The sizeof() function is used to determine the size of any data type • prototype: intsizeof(data type); • returns how many bytes the data type needs • for example: sizeof(int) = 4, sizeof(char) = 1 • works for standard data types and user defined data types (structures)
Dynamic Memory allocation for 1D Array • main() { int l; char s[10]; char *p; printf(“\n Enter Strings :”); gets(s); l=strlen(s); p=(char*)malloc(sizeof(l+1)); for(i=0; *(s+i)!=‘\0’;i++) * (p + i) =*( s + i ); *(p+i)=‘\0’; printf(Copied String : %s”,s); free(p); } main() { int n, avg,*p, sum=0; printf(“\n Enter the number of Students :”); scanf(“%d”,&n); p=(int*)malloc(n*2); if(p==NULL) { printf(“\n Memory allocation unsuccessful); exit(0); } for(i=0;i<n;i++) scanf(“%d”,(p+i); for(i=0; i<n;i++) sum=sum+ *(p+i); avg=sum/n; printf(“\n Average Marks %d”, avg); free(p); }
Passing 2D array to function void info( int *q[4], int row, intcol) { inti , j; for(i=0;i<row;i++) for(j=0;j<col;j++) printf(“ %d”,*(*(q+ i)+j)); } main() { int a[3][4]= {1,2,3,4,5,6,7,8,9,10,11,12}; display(a,3,4); show(a,3,4); info(a,3,4); } void display( int *q, int row, intcol) { inti , j; for(i=0;i<row;i++) for(j=0;j<col;j++) printf(“ %d”,*(q+i*col+j); } void show(int *q[4],introw,intcol) { inti,j, *p; for(i=0;i<row;i++) { p=q+i; for(j=0;j<col;j++) printf(“ %d”, *(p+j); } }
Dynamic memory allocation for 2D-Array main() { intcol,row,nrows,ncols; int *a[20]; printf(“\n Enter Rows”); scanf(“%d”,&nrows); printf(“\n Enter Cols”); scanf(“%d”,&ncols); for(row=0;row<nrows;row++) //Memory allocation { a[row]=(int*)malloc(ncols*sizeof(int)); } printf(“\n Enter Matrix:”); for(row=0;row<nrows;row++) { for(col=0;col<ncols;col++) scanf(“%d”,(*(a+row)+col); //scanf(“%d”,a[row][col]); }
Dynamic memory allocation for 2D-Array main() { int **a; //pointer to pointer intr,c; printf(“\n Eneter row and col :”); scanf(“%d%d”,&r,&c); *a=(int*)malloc(sizeof(int)*r); for(i=0;i<r;i++) a[i]=(int*)malloc (sizeof(int)*c); for(i=0;i<r;i++) for(j=0;j<c;j++) scanf(“%d”,(*(a+i)+j); }
Dynamic memory allocation for 2D-Array • Assume a 2-D array of characters is needed • this is basically an array of strings • Assume 4 strings with a max of 80 chars int main() { char** names; inti; names = (char**)malloc(4 * sizeof(char*)); for(i=0; i<4; i++) names[i] = (char*)malloc(80 * sizeof(char)); for(i=0; i<4; i++) free(names[i]); free(names); return 0; }
Dynamically Allocating 2D Array using calloc() float **A; /* A is an array (pointer) of float pointers */ int I; A = (float **) calloc(5,sizeof(float *)); /* A is a 1D array (size 5) of float pointers */ for (I = 0; I < 5; I++) A[I] = (float *) calloc(4,sizeof(float)); /* Each element of array points to an array of 4 float variables */ /* A[I][J] is the Jth entry in the array that the Ith member of A points to */
Realloc • Realloc it is for times when you've used malloc to get the size of array but need it bigger again (or perhaps smaller). • Realloc allows you to say "the memory I grabbed before was the wrong size - I need to change the size but keep the first bit the same). • You will probably not use realloc much. • In any case realloc is inefficient.
realloc Example float *nums; int I; nums = (float *) calloc(5, sizeof(float)); /* nums is an array of 5 floating point values */ for (I = 0; I < 5; I++) nums[I] = 2.0 * I; /* nums[0]=0.0, nums[1]=2.0, nums[2]=4.0, etc. */ nums = (float *) realloc(nums,10 * sizeof(float)); /* An array of 10 floating point values is allocated, the first 5 floats from the old nums are copied as the first 5 floats of the new nums, then the old nums is released */
Pointers to Structs #include <stdio.h> structfoo { // a global definition, the structfoo is known in all of int a, b, c; // these functions }; // function prototypes void inp(structfoo *); // both functions receive a pointer to a structfoo void outp(structfoo); void main( ) { structfoo x; // declare x to be a foo inp(&x); // get its input, passing a pointer to foo outp(x); // send x to outp, this requires 2 copying actions } void inp(structfoo *x) { // notice the notation here: &ptr->member scanf("%d%d%d", &x->a, &x->b, &x->c); } void outp(structfoo x) // same notation, but without the & { printf("%d %d %d\n", x.a, x.b, x.c); }
Nested structs through pointers struct point { int x; int y; } struct rectangle { struct point pt1; struct point pt2; } If we have struct rectangle r; Then we can reference r.pt1.x, r.pt1.y, r.pt2.x and r.pt2.y Now consider the following struct rectangle r, *rp; rp = &r; Then the following are all equivalent r.pt1.x rp->pt1.x (r.pt1).x (rp->pt1).x But not rp->pt1->x (since pt1 is not a pointer to a point)
Accessing Structure array using Pointers typedefstruct Student { intRollNo; char Name[20]; } S; void main() { S Student[3],*p; inti,n=3; for(i=0;i<3;i++) scanf(“%d%s”,&s[i].Rollno,s[i].Name); p=&s[0]; for(i=0;i<3;i++) { printf(“\n Rollno %d Name %s”,p->RollNo,p->Name); p++; } }
Dynamic Memory allocation for Structure typedefstruct Student { intRollNo; char Name[20]; } S; void main() { S *p; inti,n; printf("\n Enter total no. of Records :"); scanf("%d",&n); p=(S*)malloc(sizeof(S)*n); for(i=0;i<n;i++) { printf("\n Enter the RollNo & Name :"); scanf("%d",&(p->RollNo)); flushall(); gets(p->Name); p++; //go to next record } for(i=0;i<n;i++) { printf("\nRollNo %d",p->RollNo); printf("\nName %s",p->Name); p++; } }
What is a File? • A file is a collection of related data that a computers treats as a single unit. • Computers store files to secondary storage so that the contents of files remain intact when a computer shuts down. • When a computer reads a file, it copies the file from the storage device to memory; when it writes to a file, it transfers data from memory to the storage device. • C uses a structure called FILE (defined in stdio.h) to store the attributes of a file.
Steps in Processing a File • Create the stream via a pointer variable using the FILE structure:FILE *p; • Open the file, associating the stream name with the file name. • Read or write the data. • Close the file.