1 / 66

5.1 Introduction

5.1 Introduction. Pointers Powerful, but difficult to master Simulate call-by-reference Close relationship with arrays and strings Similar to Reference Use reference operator instead of pointer whenever possible. count. countPtr. count. 7. 7.

sachi
Download Presentation

5.1 Introduction

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. 5.1 Introduction • Pointers • Powerful, but difficult to master • Simulate call-by-reference • Close relationship with arrays and strings • Similar to Reference • Use reference operator instead of pointer whenever possible

  2. count countPtr count 7 7 5.2 Pointer Variable Declarations and Initialization • Pointer variables • Contain memory addresses as their values • Normal variables contain a specific value (direct reference) • Pointers contain the address of a variable that has a specific value (indirect reference) • Indirection • Referencing a pointer value • Pointer declarations • * indicates variable is a pointer int *myPtr; declares a pointer to an int, a pointer of type int * • Multiple pointers require multiple asterisks int *myPtr1, *myPtr2;

  3. 5.2 Pointer Variable Declarations and Initialization • Can declare pointers to any data type • Pointers initialization • Initialized to 0, NULL, or an address • 0 or NULL points to nothing

  4. yptr y y 5 yPtr address of y is value of yptr 500000 60000 60000 5 5.3 Pointer Operators • & (address operator) • Returns the address of its operand • Example int y = 5;int *yPtr;yPtr = &y; // yPtr gets address of y • yPtr “points to” y or yPtr contains the address where y is located in memory yPtr = 60000 Memory loc 60000 has 5

  5. 5.3 Pointer Operators • * (indirection/dereferencing operator) • Returns the value of what its operand points to • *yPtr returns y (because yPtr points to y) • * can be used to assign a value to a location in memory *yptr = 7; // changes y to 7 • Dereferenced pointer (operand of *) must be an lvalue (no constants) • * and & are inverses • Cancel each other out *&myVar == myVar and &*yPtr == yPtr

  6. 1 // Fig. 5.4: fig05_04.cpp The address of a is the value of aPtr. 2 // Using the & and * operators 3 #include <iostream> 4 The * operator returns an alias to what its operand points to. aPtr points to a, so *aPtr returns a. 5 using std::cout; 6 using std::endl; Notice how * and & are inverses 7 8 int main() 9 { 10 int a; // a is an integer 11 int *aPtr; // aPtr is a pointer to an integer 12 13 a = 7; 14 aPtr = &a; // aPtr set to address of a 15 16 cout << "The address of a is " << &a 17 << "\nThe value of aPtr is " << aPtr; 18 19 cout << "\n\nThe value of a is " << a 20 << "\nThe value of *aPtr is " << *aPtr; 21 22 cout << "\n\nShowing that * and & are inverses of " 23 << "each other.\n&*aPtr = " << &*aPtr 24 << "\n*&aPtr = " << *&aPtr << endl; 25 return 0; 26 } 1. Declare variables 2 Initialize variables 3. Print Program Output on next page

  7. The address of a is 006AFDF4 The value of aPtr is 006AFDF4 The value of a is 7 The value of *aPtr is 7 Showing that * and & are inverses of each other. &*aPtr = 006AFDF4 *&aPtr = 006AFDF4 Summary int a; // declare a variable ‘a’ of type integer, a gets a specific address int *aPtr; // declare a pointer ‘aPtr’ of type inter to an integer aPtr = &a; // Can only assign address to ‘aPtr’, Example, address of ‘a’ *aPtr = 100; // assign a value of 100 to address pointed by aPtr (55000) int b = *aPtr; // Var b now has a value of 100 by aPtr (55000) &b = aPtr; // ERROR, CANNOT CHANGE WHERE B IS LOCATED. b = aPtr; // ERROR, cannot convert from 'int *' to 'int' b = reinterpret_cast<int>(aPtr); The reinterpret_cast operator allows pointer of one type to be converted into a pointer of another type. It also allows any integral type to be converted into any pointer type and vice versa.

  8. Passing Arguments by Reference • Except for arrays, by default, C++ passes arguments by value. This can be very inefficient when large data items are passed • When data is large, or must be modified by the function, the argument can be passed by reference (address) • With Pointers, you must explicitly pass the address to the function and de-reference the argument within the function • Using the reference operator is a better way • Pass address of argument using & operator • Allows you to change the data at that location in memory • No need to use & with arrays. Array name is already a pointer

  9. Example of Call-by-ReferenceReference operator VS Pointer void swap (int *x, int *y); main () { int val1=1, val2=2; swap (&val1, &val2); return ; } void swap (int *x, int *y) { int temp = *x; *x = *y; *y = temp; return ; } void swap (int &x, int &y); main () { int val1=1, val2=2; swap (val1, val2); return ; } void swap (int &x, int &y) { int temp = x; x = y; y = temp; return ; }

  10. Summary - Calling Functions by Reference using pointers • Call-by-reference with pointer arguments • Pass address of the argument to the function using & operator int myNum = 3; int *iPtr = &myNum; //iPtr has myNum’s addr NumTimesTwo( &myNum ); (from main) NumTimesTwo( iPtr ); (from main) void NumTimesTwo( int *number ) { *number = 2 * ( *number );} • use *number to de-reference the pointer in the function

  11. 1 // Fig. 5.7: fig05_07.cpp 2 // Cube a variable using call-by-reference Notice how the address of number is given - cubeByReference expects a pointer (an address of a variable). 3 // with a pointer argument 4 #include <iostream> 5 6 using std::cout; Inside cubeByReference, *nPtr is used (*nPtr is number). 7 using std::endl; 8 9 void cubeByReference( int * ); // prototype 10 11 int main() 12 { 13 int number = 5; 14 15 cout << "The original value of number is " << number; 16 cubeByReference( &number ); 17 cout << "\nThe new value of number is " <<number<< endl; 18 return 0; 19 } 20 21 void cubeByReference( int *nPtr ) 22 { 23 *nPtr = *nPtr * *nPtr * *nPtr; // cube number in main 24 } 1. Function prototype - takes a pointer to an int. 1.1 Initialize variables 2. Call function 3. Define function Program Output The original value of number is 5 The new value of number is 125

  12. j i 7 7 More on Using References • A reference is not a pointer ! • It must be assigned a value when defined • It cannot be unassigned or re-assigned int i = 7; // creates i int &j=i; // creates an “independent” reference to i j++; // increments val of i, not the address of i • j is an alias of i. If the value of i changes, so does the value of j. You use j just as you would use i. • The address of a reference is actually the address of the value associated with the address • References can be returned just like any other function return parameters i 1000 j 1000

  13. #include <iostream> using namespace std; int main() { int i = 10; int &j = i; int *ip = &i; cout << "i = " << i << ", j= " << j << ", *ip=" << *ip << endl; j++; cout << "i = " << i << ", j= " << j << ", *ip=" << *ip << endl; cout << "&i = " << &i << ", &j= " << &j << ", ip=" << ip << endl; return 0; } Assigning a reference and a pointer to an integer. Note that incrementing j changes the value of i and not the address of i They all point to the same memory location For Address of ip, you do not use & i = 10, j= 10, *ip=10 i = 11, j= 11, *ip=11 &i = 0012FF7C, &j= 0012FF7C, ip=0012FF7C

  14. 5.5 Using the Const Qualifier with Pointers • const qualifier • Variable cannot be changed • const used when function must NOT change a variable • Attempting to change a const variable is a compiler error • Four ways to pass a pointer to a function data is constant or pointer is constant, or both non-const pointer to non-const datanon-const pointer to const dataconst pointer to non-const data const pointer to const data

  15. 2 3 6 7 myPtr 9 j Using the Const Qualifier with Pointers int array j[] = {2,3,6,7,9}; int * const myPtr = j; j and myPtr both have an address as their value and point to the same memory location. They are constant and cannot point to any other address. However, the data they point to, can change.

  16. 5.5 Using the Const Qualifier with Pointers • Four ways to pass a pointer to a function non-const pointer to non-const dataint *myPtr = &j; non-const pointer to const dataconst int* myPtr = &j; const pointer to non-const data int * const myPtr = &j; const pointer to const data const int*const myPtr = &j;

  17. non-const pointer to non-const data non-const pointer to non-const data int *myPtr ; int j = 20 ; int *myPtr = &j ; • Highest access granted • Pointer can be modified to point to another data • Data can be modified through the dereferenced pointer • Can be used to receive a string in a function that uses pointer arithmetic to process and possibly modify each char in the string

  18. // Fig. 5.10: fig05_10.cpp// Converting lowercase letters to uppercase letters// using a non-constant pointer to non-constant data #include <iostream> using namespace std; #include <cctype> void convertToUppercase( char * ); int main() { char string[] = "characters and $32.98"; cout << "The string before conversion is: " << string; convertToUppercase( string ); cout << "\nThe string after conversion is: " << string << endl; return 0; }

  19. void convertToUppercase( char *sPtr ) • { • while ( *sPtr != '\0' ) • { • if ( islower( *sPtr ) ) • // convert to uppercase • *sPtr = toupper( *sPtr ); • ++sPtr; // move sPtr to the next character • } • }

  20. non-const pointer to const data non-const pointers to const data const char *myPtr = &x; Read as: myPtr is a pointer to constant character • Pointer can be modified to point to other data of same type • Data to which this pointer points to cannot be modified by this pointer • (*myPtr)++ will result in compiler error • myPtr++ OK, myPtr points new memory location

  21. // Fig. 5.11: fig05_11.cpp// Printing a string one character at a time using// a non-constant pointer to constant data#include <iostream>using namespace std;void printCharacters( const char * );int main(){char string[] = "print characters of a string";   cout << "The string is:\n";   printCharacters( string );   cout << endl;return 0;} // In printCharacters, sPtr cannot modify the character // to which it points. sPtr is a "read-only" pointervoid printCharacters( const char *sPtr ){for ( ; *sPtr != '\0'; sPtr++ )   // no initialization     cout << *sPtr;}

  22. const pointer to non-const data const pointers to non-const data int *const myPtr = &x; Read as: myPtr is a constant pointer to integer data type Always point to the same memory location. If attempt is made to change the address, you get a compiler error • Name of an array is a constant pointer. Name of array always point to the first element in the array • Must be initialized when declared (*myPtr)++; // OK, just incrementing data *(myPtr++); // NOT OK, incrementing address *myPtr++; // NOT OK, incrementing address ++myPtr; // NOT OK, incrementing address

  23. 1 // Fig. 5.13: fig05_13.cpp 2 // Attempting to modify a constant pointer to 3 // non-constant data Changing *ptr is allowed - x is not a constant. 4 #include <iostream> 5 6 int main() Changing ptr is an error - ptr is a constant pointer. 7 { 8 int x, y; 9 10 int * const ptr = &x; // ptr is a constant pointer to an 11 // integer. An integer can be modified 12 // through ptr, but ptr always points 13 // to the same memory location. 14 *ptr = 7; 15 ptr = &y; 16 17 return 0; 18 } 1. Declare variables 1.1 Declare const pointer to an int. 2. Change *ptr (which is x). 2.1 Attempt to change ptr. 3. Output Program Output Error E2024 Fig05_13.cpp 15: Cannot modify a const object in function main()

  24. const pointer to const data const pointers to const data const int * const myPtr = &x; • Read as: myPtr is a constant pointer to const integer data type • Least amount of privilege is granted in this case • Always point to the same memory location. If attempt is made to change the address, you get a compiler error • Data to which this pointer points to cannot be modified by this pointer • Name of an array is a constant pointer. Name of array always point to the first element in the array • Must be initialized when declared (*myPtr)++; // NOT OK, just incrementing value *(myPtr++); // NOT OK, incrementing address *myPtr++; // NOT OK, incrementing address

  25.   1)// Fig. 5.14: fig05_14.cpp  2)// Attempting to modify a constant pointer to  3)// constant data.  4)#include <iostream>  5)  6)using std::cout;  7)using std::endl;  8)  9)int main() 10) { 11)int x = 5, y; 12) 13)const int *const ptr = &x;  // ptr is a constant pointer to a 14)// constant integer. ptr always  15)// points to the same location  16)// and the integer at that  17)// location cannot be modified. 18)    cout << *ptr << endl; 19)    *ptr = 7; 20)    ptr = &y; 21) 22)return 0; 23) }

  26.  1)  // Fig. 5.15: fig05_15.cpp13)void bubbleSort( int *, const int ); 1)  // Fig. 5.15: fig05_15.cpp13)void bubbleSort( int *, const int ); 17)const int arraySize = 10;18)int a[arraySize] = { 2, 6, 4, 8, 10, 12, 89, 68, 45, 37 };26)bubbleSort( a, arraySize ); 36)void bubbleSort(int *array, const intsize )37) {38)voidswap(int * const, int * const);39)40)for(intpass = 0; pass<size-1; pass++)42)for(int j = 0; j<size-1; j++)44)if (array[j] > array[j+1])45)           swap( &array[j], &array[j+1]);46) }47)48)voidswap(int* const element1Ptr,int * const element2Ptr)49) {50)int hold = *element1Ptr;51)    *element1Ptr = *element2Ptr;52)    *element2Ptr = hold;53) }

  27. sizeof operator • sizeof • Returns size of operand in bytes • For arrays, sizeof returns number of bytes in the array ( the SIZE of 1 element ) * ( number of elements ) • if sizeof( int ) = 4, then int myArray[10]; cout << sizeof(myArray); // will print 40 • sizeof can be used with • Variable names • Data Types • Constant values

  28. sizeof operator • size_t typedef unsigned int size_t defined in stdio.h header file It’s a pre-defined data type Example: size_t sz; sz = sizeof(int); // returns 4 double *dblPtr, dbl = 10.0; char *chrPtr, chr = 'a'; cout << "Size of Double Pointer = " << (sizeof dblPtr) << endl; cout << "Size of Char Pointer = " << (sizeof chrPtr) << endl; //Both pointer sizes are 4 bytes

  29. sizeof operator 12) // Example Fig 5.17 13) char c; 14) short s; 15) int i; 16) long l; 17) float f; 18) double d; 19) long double ld; 20) int array[ 20 ], *ptr = array; 21) 22) cout << "sizeof c = " << sizeof c 23) << "\tsizeof(char) = " << sizeof (char) 24) << "\nsizeof s = " << sizeof s 25) << "\tsizeof(short) = " << sizeof (short) 26) << "\nsizeof i = " << sizeof i 27) << "\tsizeof(int) = " << sizeof (int) 28) << "\nsizeof l = " << sizeof l 29) << "\tsizeof(long) = " << sizeof (long) 30) << "\nsizeof f = " << sizeof f 31) << "\tsizeof(float) = " << sizeof (float) 32) << "\nsizeof d = " << sizeof d 33) << "\tsizeof(double) = " << sizeof (double) 34) << "\nsizeof ld = " << sizeof ld 35) << "\tsizeof(long double) = " << sizeof (long double) 36) << "\nsizeof array = " << sizeof array 37) << "\nsizeof ptr = " << sizeof ptr 38) << endl;

  30. 5.6 Bubble Sort Using Call-by-reference • Implement bubblesort using pointers • swap function must receive the address (using &) of the array elements • array elements have call-by-value default • Using pointers and the * operator, swap is able to switch the values of the actual array elements • Psuedocode Initialize array print data in original order Call function bubblesort print sorted array Define bubblesort

  31. 1)//Fig. 5.15: fig05_15.cpp2)//This program puts values into an array, sorts the values 3)//into ascending order, and prints the resulting array.4) #include <iostream>9)#include <iomanip>11)using namespace std;12)13)void bubbleSort( int *, const int );14)15)int main()16) {17)const int arraySize = 10;18)int a[arraySize] = {2,6,4,8,10,12,89,68,45,37 };19)int i;20)21)    cout << "Data items in original order\n";22)23)for ( i = 0; i < arraySize; i++ )24)       cout << setw( 4 ) << a[ i ];25)26)    bubbleSort( a, arraySize );   // sort the array27)    cout << "\nData items in ascending order\n";28)29)for ( i = 0; i < arraySize; i++ )30)       cout << setw( 4 ) << a[ i ];31)32)    cout << endl;33)return 0;34) }

  32. 36)void bubbleSort( int *array, const int size )37){38)void swap( int * const, int * const );39)40)for(int pass = 0; pass < size - 1; pass++ )41)42)for(int j = 0; j < size - 1; j++ )43)44)if (array[ j ] > array[ j + 1 ] )45)            swap( &array[ j ], &array[ j + 1 ] );46)}47)48)void swap(int *const element1Ptr,int *const element2Ptr )49){50)int hold = *element1Ptr;51)  *element1Ptr = *element2Ptr;52)  *element2Ptr = hold;53)}36)void bubbleSort( int *array, const int size )37){38)void swap( int * const, int * const );39)40)for(int pass = 0; pass < size - 1; pass++ )41)42)for(int j = 0; j < size - 1; j++ )43)44)if (array[ j ] > array[ j + 1 ] )45)            swap( &array[ j ], &array[ j + 1 ] );46)}47)48)void swap(int *const element1Ptr,int *const element2Ptr )49){50)int hold = *element1Ptr;51)  *element1Ptr = *element2Ptr;52)  *element2Ptr = hold;53)} swap takes pointers (addresses of array elements) and dereferences them to modify the original array elements. Data items in original order 2 6 4 8 10 12 89 68 45 37 Data items in ascending order 2 4 6 8 10 12 37 45 68 89

  33. location 3000 3004 3012 3016 3008 pointer variable vPtr v[0] v[1] v[2] v[4] v[3] 5.7 Pointer Expressions and Pointer Arithmetic • Pointer arithmetic • Increment/decrement pointer (++ or --) • Add/subtract an integer to/from a pointer( + or += , - or -=) • Pointers may be subtracted from each other • Pointer arithmetic is meaningless unless performed on an array • 5 element int array on a machine using 4 byte ints • vPtr points to first element v[ 0 ], which is at location 3000 • vPtr = 3000 • vPtr += 2; • sets vPtr to 3008 • now vPtr points to v[ 2 ]

  34. 5.7 Pointer Expressions and Pointer Arithmetic • Subtracting pointers • Returns the number of elements between two addresses vPtr2 = &v[ 2 ];vPtr = &v[ 0 ];vPtr2 - vPtr == 2 // comparison • Pointer comparison • Test which pointer points to the higher numbered array element • Must compare pointers of same type

  35. 5.7 Pointer Expressions and Pointer Arithmetic • Pointers assignment • If not the same type, a cast operator must be used • Exception: pointer to void (type void *) • Void Pointer • Generic pointer, represents any type of pointer • No casting needed to convert a pointer to void pointer • All pointers can be assigned to void pointer • Void pointer cannot be assigned directly to another pointer. It must first be casted to the proper pointer type • void pointers cannot be dereferenced

  36. 5.8 The Relationship Between Pointers and Arrays • Arrays and pointers closely related • Array name is like a constant pointer • Pointers can do array subscripting operations • Having declared an array b[ 5 ] and a pointer bPtr • bPtr is equal to b bptr == b • bptr is equal to the address of the first element of b bptr == &b[ 0 ]

  37. 5.8 The Relationship Between Pointers and Arrays • Accessing array elements with pointers • Element b[ n ] can be accessed by *( bPtr + n ) • Called pointer/offset notation • Array itself can use pointer arithmetic. • b[ 3 ] same as *(b + 3) • Pointers can be subscripted (pointer/subscript notation) • bPtr[ 3 ] same as b[ 3 ]

  38. 1st [ ], number of strings 2nd [ ], # of elements in each string, must be > largest string 5.9 Arrays of Pointers • Arrays can contain pointers • Commonly used to store an array of strings char *suit[ 4 ] = {"Hearts", "Diamonds","Clubs", "Spades" }; char suit[4][9] = {"Hearts", "Diamonds","Clubs", "Spades" }; char *suit1 = {"Hearts"}; char suite1[] = {"Hearts"}; char *suit2 = {"Diamonds"}; char *suit3 = {"Clubs"}; char *suit4 = {"Spades"}; char suite5 [][5] = {"1234", "aaa", "bbb"}; char suite6 [3][5] = {"1234", "aaa", "bbb"};

  39. ’\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] 5.9 Arrays of Pointers • Arrays can contain pointers • Commonly used to store an array of strings char *suit[ 4 ] = {"Hearts", "Diamonds","Clubs", "Spades" }; • Each element of suit is a pointer to a char * (a string) • The strings are not in the array, only pointers to the strings are in the array • suit array has a fixed size, but strings can be of any size

  40. 5.10 Case Study: A Card Shuffling and Dealing Simulation • Card shuffling program • Use an array of pointers to strings, to store suit names • Use a double scripted array (suit by value) • Place 1-52 into the array to specify the order in which the cards are dealt Ace One Two Three Four Five Six Seven Eight Nine Ten Jack Queen King 0 1 2 3 4 5 6 7 8 9 10 11 12 0 Hearts 1 Diamonds 2 Clubs 3 Spades deck[2][12] represents the King of Clubs King Clubs

  41. 5.10 Case Study: A Card Shuffling and Dealing Simulation • Pseudocode for shuffling and dealingsimulation Third refinement • Choose slot of deck randomly • While chosen slot of deck has been previously chosenChoose slot of deck randomly • Place card number in chosen slot of deck First refinement Second refinement • Initialize the suit array • Initialize the face array • Initialize the deck array • Shuffle the deck • Deal 52 cards • For each of the 52 cards • Place card number in randomly selected unoccupied slot of deck • For each of the 52 cards • Find card number in deck array and print face and suit of card • For each slot of the deck array • If slot contains card numberPrint the face and suit of the card

  42. 1 // Fig. 5.24: fig05_24.cpp 2 // Card shuffling dealing program 3 #include <iostream> 4 5 using std::cout; 6 using std::ios; 7 8 #include <iomanip> 9 10 using std::setw; 11 using std::setiosflags; 12 13 #include <cstdlib> 14 #include <ctime> 15 16 void shuffle( int [][ 13 ] ); 17 void deal( const int [][ 13 ], const char *[], const char *[] ); 18 19 int main() 20 { 21 const char *suit[ 4 ] = 22 { "Hearts", "Diamonds", "Clubs", "Spades" }; 23 const char *face[ 13 ] = 24 { "Ace", "Deuce", "Three", "Four", 25 "Five", "Six", "Seven", "Eight", 26 "Nine", "Ten", "Jack", "Queen", "King" }; 27 int deck[ 4 ][ 13 ] = { 0 }; 28 29 srand( time( 0 ) ); 30 31 shuffle( deck ); 32 deal( deck, face, suit ); 33 1. Initialize suit and face arrays 1.1 Initialize deck array 2. Call function shuffle 2.1 Call function deal

  43. 34 return 0; The numbers 1-52 are randomly placed into the deck array. 35 } 36 Searches deck for the card number, then prints the face and suit. 37 void shuffle( int wDeck[][ 13 ] ) 38 { 39 int row, column; 40 41 for ( int card = 1; card <= 52; card++ ) { 42 do { 43 row = rand() % 4; 44 column = rand() % 13; 45 } while( wDeck[ row ][ column ] != 0 ); 46 47 wDeck[ row ][ column ] = card; 48 } 49 } 50 51 void deal( const int wDeck[][ 13 ], const char *wFace[], 52 const char *wSuit[] ) 53 { 54 for ( int card = 1; card <= 52; card++ ) 55 56 for ( int row = 0; row <= 3; row++ ) 57 58 for ( int column = 0; column <= 12; column++ ) 59 60 if ( wDeck[ row ][ column ] == card ) 61 cout << setw( 5 ) << setiosflags( ios::right ) 62 << wFace[ column ] << " of " 63 << setw( 8 ) << setiosflags( ios::left ) 64 << wSuit[ row ] 65 << ( card % 2 == 0 ? '\n' : '\t' ); 66 } 3. Define functions

  44. Six of Clubs Seven of Diamonds Ace of Spades Ace of Diamonds Ace of Hearts Queen of Diamonds Queen of Clubs Seven of Hearts Ten of Hearts Deuce of Clubs Ten of Spades Three of Spades Ten of Diamonds Four of Spades Four of Diamonds Ten of Clubs Six of Diamonds Six of Spades Eight of Hearts Three of Diamonds Nine of Hearts Three of Hearts Deuce of Spades Six of Hearts Five of Clubs Eight of Clubs Deuce of Diamonds Eight of Spades Five of Spades King of Clubs King of Diamonds Jack of Spades Deuce of Hearts Queen of Hearts Ace of Clubs King of Spades Three of Clubs King of Hearts Nine of Clubs Nine of Spades Four of Hearts Queen of Spades Eight of Diamonds Nine of Diamonds Jack of Diamonds Seven of Clubs Five of Hearts Five of Diamonds Four of Clubs Jack of Hearts Jack of Clubs Seven of Spades Program Output

  45. 5.11 Function Pointers • Pointers to functions • Contain the address of the function • Similar to how an array name is the address of its first element • Function name is starting address of code that defines function • Function pointers can be • Passed to functions • Stored in arrays • Assigned to other function pointers

  46. 5.11 Function Pointers • Example: bubblesort • Function bubble takes a function pointer • The function determines whether the the array is sorted into ascending or descending sorting • The argument in bubble for the function pointer bool ( *compare )( int, int ) tells bubble to expect a pointer to a function that takes two ints and returns a bool • If the parentheses were left out bool *compare( int, int ) would declare a function that receives two integers and returns a pointer to a bool

  47. 1 // Fig. 5.26: fig05_26.cpp 2 // Multipurpose sorting program using function pointers 3 #include <iostream> Notice the function pointer parameter. 4 5 using std::cout; 6 using std::cin; 7 using std::endl; 8 9 #include <iomanip> 10 11 using std::setw; 12 13 void bubble( int [], const int, bool (*)( int, int ) ); 14 bool ascending( int, int ); 15 bool descending( int, int ); 16 17 int main() 18 { 19 const int arraySize = 10; 20 int order, 21 counter, 22 a[ arraySize ] = { 2, 6, 4, 8, 10, 12, 89, 68, 45, 37 }; 23 24 cout << "Enter 1 to sort in ascending order,\n" 25 << "Enter 2 to sort in descending order: "; 26 cin >> order; 27 cout << "\nData items in original order\n"; 28 29 for ( counter = 0; counter < arraySize; counter++ ) 30 cout << setw( 4 ) << a[ counter ]; 31 32 if ( order == 1 ) { 33 bubble( a, arraySize, ascending ); 34 cout << "\nData items in ascending order\n"; 1. Initialize array 2. Prompt for ascending or descending sorting 2.1 Put appropriate function pointer into bubblesort 2.2 Call bubble 3. Print results

  48. 35 } 36 else { 37 bubble( a, arraySize, descending ); 38 cout << "\nData items in descending order\n"; ascending and descending return true or false. bubble calls swap if the function call returns true. 39 } 40 41 for ( counter = 0; counter < arraySize; counter++ ) 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. 42 cout << setw( 4 ) << a[ counter ]; 43 44 cout << endl; 45 return 0; 46 } 47 48 void bubble( int work[], const int size, 49 bool (*compare)( int, int ) ) 50 { 51 void swap( int * const, int * const ); // prototype 52 53 for ( int pass = 1; pass < size; pass++ ) 54 55 for ( int count = 0; count < size - 1; count++ ) 56 57 if ( (*compare)( work[ count ], work[ count + 1 ] ) ) 58 swap( &work[ count ], &work[ count + 1 ] ); 59 } 60 61 void swap( int * const element1Ptr, int * const element2Ptr ) 62 { 63 int temp; 64 65 temp = *element1Ptr; 66 *element1Ptr = *element2Ptr; 67 *element2Ptr = temp; 68 } 3.1 Define functions

  49. 69 70 bool ascending( int a, int b ) 71 { 72 return b < a; // swap if b is less than a 73 } 74 75 bool descending( int a, int b ) 76 { 77 return b > a; // swap if b is greater than a 78 } 3.1 Define functions Program output Enter 1 to sort in ascending order, Enter 2 to sort in descending order: 1 Data items in original order 2 6 4 8 10 12 89 68 45 37 Data items in ascending order 2 4 6 8 10 12 37 45 68 89 Enter 1 to sort in ascending order, Enter 2 to sort in descending order: 2 Data items in original order 2 6 4 8 10 12 89 68 45 37 Data items in descending order 89 68 45 37 12 10 8 6 4 2

  50. Pointer to Function void vline(int i); funciton prototype void hline(int i);funciton prototype • p is Pointer to a function that take an int and returns nothing. void (*p)(int); p = vline;// Pass the address of function vline (*p)(4); // call or execute function vline; p = hline; // Pass the address of function hline (*p)(10); // call or execute function hline;

More Related