320 likes | 393 Views
Introduction to Programming 3D Applications CE0056-1. Lecture 10 Pointers in C. Pointers. Pointers are necessary for understanding and use of: Passing Parameters by Reference Arrays (especially strings) Dynamic Allocation of Memory Dynamic Data Structures
E N D
Introduction to Programming 3D ApplicationsCE0056-1 Lecture 10 Pointers in C
Pointers Pointers are necessary for understanding and use of: • Passing Parameters by Reference • Arrays (especially strings) • Dynamic Allocation of Memory • Dynamic Data Structures A Pointer is a reference to (or address of) a memory location.
1) Passing Parameters by Reference Function swap exchanges the values of its 2 parameters: #include “stdio.h” void swap(int *, int *); // prototype int main(void) { int a=3, b=7; swap(&a, &b); // addresses of values to be swapped printf(“1st is %d, 2nd is %d”, a, b); return 0; }
Function swap void swap(int *x, int *y) // x, y are copies of the addresses a, b { int temp; temp = *x; // using pointers to access *x = *y; // originals (not copies) *y = temp; // and swap them via temp }
2) Arrays and Strings Consider the declaration: char x[10]; // a string of size 10 • x[3] is the character in element 3 of array x • &x[3] is the address of element 3 of array x • x is the address of array x (actually the same as &x[0]) • *x is the character that x points to (ie same as x[0])
Strings as pointers • Strings should always be declared as arrays inside the main function, so that required storage can be allocated. Thus char x[10] allocates 10 bytes. • Strings can be declared explicitly as pointers – typically inside functions, e.g. char *s; declares variable, s, as a pointer to a character – (ie string pointer). It can point to any string –or any part of a string – or to examine all the characters within a string.
Arrays as parameters • Arrays and strings, such as x above, passed to functions as parameters are already addresses. Example: int list [100]; sort(list, n); The address of array, list, is passed to the sort function. void sort(int a[], int n) So that array, a, also refers to the original elements of list.
Example of a String Function The function, print_reverse, • given a string (as a parameter) • prints the string in reverse by dealing with one character at a time, using a pointer starting with the last and continuing while it has not yet reached the start of the string.
Main function Main function reads, reverse and writes a string. #include “stdio.h” int main(void) { char line[81] ; // for string storage gets(line); // whole line is the string printf(“Reversed line is\n”); print_reverse(line); // line is address return 0; }
print_reverse function void print_reverse(char *s) //s is a string { char *ptr; ptr = s + strlen(s) - 1; // last char while ( ptr != s) // not start of string { printf(“%c”, *ptr); // the character ptr--; // previous char } printf(“%c”, *ptr);// ptr == s // first character of s }
String function example • The function, string_tolower, converts all upper case letters in a string to lower case and leaves all other characters unchanged. • It uses a standard function, tolower, to convert each character. • A pointer will examine each character one at a time while it has not yet reached the end of the string, i.e. ‘\0’. • A pointer to the beginning of the string is returned.
Function string_tolower char * string_tolower(char *s)//s is string { // return p as a pointer char *p; p = s; // start of string, s while ( *s != ‘\0’) // not end of string { *s = tolower(*s); // upper to lower s++; // next character } return p; // start of result }
Main function #include “stdio.h” #include “ctype.h” // for tolower function int main(void) { char line[81] ; // for string storage gets(line); // string of upper & lower case letters string_tolower(line); printf(“\nresulting string is:\n”); printf(“%s\n”, line); return 0; }
The function, string_tower, also returns a pointer to the result – so that it could be used as follows: printf(“\nresulting string is:\n%s”, string_tolower(line));
Another string function example • Function, isinteger, checks whether all the characters in a string are digits or not. • It returns true, i.e. 1, if all characters are the digits ‘0’ to ‘9’, otherwise it returns false, i.e. 0. • It uses a standard function, isdigit, to check each character:
Function isinteger int isinteger(char *s) // s is a string { // returns 1(true) or 0(false) while (*s != ‘\0’) { // while not end of string if (!isdigit(*s)) // not a digit { return 0; // false } s++; // next character } return 1; // true }
Validate Room Number Example Here is a program, using our functions, that reads and validates a room number for our computing labs. Room numbers range from KC01 to KC16 inclusive. Note that KC1 and KC01 are the same and that the letter prefixes, ‘K’ and ‘C’ may be in upper or lower case. #include “stdio.h” #include “string.h” #include “ctype.h” // isdigit, atoi, tolower // prototypes int isinteger(char *); char *string_tolower(char *);
int main(void) { char room[10]; int room_num; printf(“type in room number\n”); scanf(“%s”, room); // read as a string if (strlen(room) < 3) // too short { printf(“\n%s too short\n”, room); } else if (strlen(room) > 4) // too long { printf(“\n%s too long\n”, room); } else // length is ok
{ string_tolower(room);// lower case if ((room[0] != ‘k’) // not k or || (room[1] != ‘c’)) // not c { printf(“\nroom must start kc\n”); } else // kc or KC found if (!isinteger(room + 2)) // integer starting room[2]? { printf(“\nroom number not digits”); } else // is integer room no.
{ room_num = atoi(room + 2); // convert to integer if (room_num == 0||room_num >16) { printf(“\nroom %s ”, room); printf(“not a Concourse lab”); } else // out of range { printf(“\nroom %s ”, room); printf(“is a Concourse lab”); } } // end integer room number } // end length ok return 0; } // end main
Allocation of Static Memory • A declaration such as char name[1000][21], allocates sufficient memory for 1000 names of 21 characters each. • This storage of 21 000 characters is reserved at compilation time, i.e. before the program begins execution. • This wastes space as most names are rather less than 20 letters. • It also restricts names to a maximum of 20 characters. • We can resolve this wastage and restriction by allocation of memory as and when required, during execution of the program.
Dynamic Allocation using malloc function • A standard function, malloc(n)allocates n bytes (for n characters) in memory and returns a pointer to it. For example: the following code • Prompts the user for the size of the string • Reads the size • Allocates memory for a string of this size • Reads the string
Example using malloc int size; char *s; printf(“\nhow many characters?\n”); scanf(“%d”, &size); s = malloc(size+1); // one extra for ‘\0’ printf(“type string\n”); gets(s); allocates only enough memory for the expected string.
Use of malloc for any data type malloc can be used to allocate memory for any <data type>. <data type> *<variable>; // pointer to <data type> // some other code here <variable> = (<data type> *)malloc(n * sizeof(<data type>)); allocates sufficient memory for n values of <data type> and returns a pointer which must be casted as the same pointer type as the <variable>.
Using malloc for an array of integers For example: To allocate storage for 10 integers int *p; p = (int *) malloc (10 * sizeof(int)); This is machine-independent, as sizeof returns size of an integer for any machine.
Ragged Arrays Declare 6 variable length names – array of string pointers char *name[6] = {“abdul”, “abraham”, “al “, “bill”, “fred”, “jean-pierre”}; We can declare functions on ragged arrays: void print_list(char *table1[ ], int n) so that it can deal with strings of any length.
Ragged array example Read a list of strings (one on each line) into an array where the size of each element is precisely the length of each string, ie the strings are of variable length - a ragged array. #include "stdio.h" #include "string.h" #include "stdlib.h" // for malloc // prototypes void sort(char *[], int); int read_strings(char *[], int); void print_strings(char *[], int);
Main function int main(void) { char *list[1000]; // array of 1000 string pointers int n; // actual number of strings n = read_strings(list, 1000); // read n strings, max of 1000 sort(list, n); // sort n strings print_strings(list, n); // print n strings return (0); }
print_strings function void print_strings(char *list[], int n) { int i; printf("\nalphabetical order is\n\n"); for (i=0; i<n; i++) { printf("%s\n", list[i]); } }
void sort(char *a[], int n) { // array of n strings as pointers int i, j; char *temp; // string pointer for (j = n -1; j > 0; j--) { // each pass of j comparisons for (i=0; i < j; i++) { // each comparison if (strcmp(a[i], a[i+1]) > 0) { // swap the POINTERS temp = a[i]; a[i] = a[i+1]; a[i+1] = temp; } // else no swap } // end of pass } // end of all passes } // end sort
int read_strings(char *list[], int max) { int i = 0; char line[81]; // store for each line printf("\ntype one string per line\n"); while (gets(line) != NULL && i < max) { // while not end of input list[i] = malloc (strlen(line)+1); // list[i] big enough // for line + 1 for ‘\0’ strcpy(list[i], line); // copy line into list[i] i++; // next element } return i; // actual number of strings }