A Complete Guide to Programming in C++ part 71 pptx

10 312 0
A Complete Guide to Programming in C++ part 71 pptx

Đang tải... (xem toàn văn)

Thông tin tài liệu

SOLUTIONS ■ 679 kde.setNr(10L); kde.setName("Peter"); hash.insert( kde ); kde.setNr(17L); kde.setName("Alexa"); hash.insert( kde ); kde.setNr(21L); kde.setName("Peter"); hash.insert( kde ); kde.setNr(15L); kde.setName("Jeany"); hash.insert( kde ); cout << "\nInsertion complete: " << endl; hash.display(); unsigned long key; cout << "Key? "; cin >> key; HashEntry temp = hash.retrieve(key); if(temp.getNr() != 0L) temp.display(); else cout << "Key " << key << " not found" << endl; } catch(OpenError& err) { cerr << "Error in opening the file:" << err.getName() << endl; exit(1); } catch(WriteError& err) { cerr << "Error writing to file: " << err.getName() << endl; exit(1); } catch(ReadError& err) { cerr << "Error reading from file: " << err.getName() << endl; exit(1); } return 0; } This page intentionally left blank 681 More about Pointers This chapter describes advanced uses of pointers.These include pointers to pointers, functions with a variable number of arguments, and pointers to functions. An application that defines a class used to represent dynamic matrices is introduced. chapter 30 682 ■ CHAPTER 30 MORE ABOUT POINTERS // accSort.cpp: Sorts an array of pointers to accounts // according to the account numbers // #include "account.h" void ptrSwap(Account**, Account** ); void accSort( Account** kptr, int n) { Account **temp, **minp, **lastp; lastp = kptr + n - 1; // Pointer to the last // pointer in the array. for( ; kptr < lastp; ++kptr ) { minp = kptr; for( temp = kptr + 1; temp <= lastp; ++temp ) { if( (*temp)->getNr() < (*minp)->getNr() ) minp = temp; } ptrSwap( kptr, minp ); } } void ptrSwap( Account **p1, Account **p2 ) { Account *help; help = *p1; *p1 = *p2; *p2 = help; } ■ POINTER TO POINTERS The function accSort() POINTER TO POINTERS ■ 683 ᮀ Motivation Pointer variables are objects that have an address in memory, and this means you can use pointers to address them. It is thus possible to create pointers to pointers. This is necessary if ■ an array of pointers is to be dynamically allocated, or ■ a function expects an array of pointers as an argument. In both cases you need to declare a pointer variable that can access the first element in the array. Since each element in the array is a pointer, this pointer variable must be a pointer to a pointer. ᮀ Generating Pointer Arrays Dynamically Now let’s look into creating a dynamic array of pointers to Account class objects. Example: Account** ptr = new Account*[400]; The pointer ptr is now pointing at the first pointer in the array with a total of 400 Account* type pointers. The array elements can be addressed as follows: *ptr and ptr[0] (pointer to index 0) *(ptr + i) and ptr[i] (pointer to index i) Access to objects managed by the array is achieved as follows: **ptr and *ptr[0] (object addressed by pointer at index 0) **(ptr+i) and *ptr[i] (object addressed by pointer at index i) ᮀ Pointer Arrays as Arguments When you define a function that expects an array of pointers as an argument, you must define parameters to match. Example: void accSort( Account **kptr, int len); You can use the kptr parameter to manipulate a pointer array whose length is stored in the second parameter, len. After calling Example: accSort( ptr, 100); kptr points to the first pointer ptr[0] in the pointer array ptr. Instead of Account **kptr you can also use the equivalent form Account *kptr[]. The opposite page shows an implementation of the function accSort(). The func- tion uses the selection sort algorithm (which you have already worked with) for sorting. In this case it is important not to sort the accounts itself, but to sort the pointers instead. This saves time-consuming copying. 684 ■ CHAPTER 30 MORE ABOUT POINTERS Fixed arguments First varying argument Varying arguments Last varying argument va_start(argp,max) char *buffer int max • • • #include <stdarg.h> int func( char *buffer, int max, ) { va_list argptr; // Declares argument pointer. long arg3; . . . va_start( argptr, max); // Initialization. arg3 = va_arg( argptr, long ); // Read arguments. // To use argument arg3. . . . . va_end(argptr); // Set argument pointer to NULL. } ■ VARIABLE NUMBER OF ARGUMENTS Fixed and varying arguments on the stack Scheme of a function with varying arguments VARIABLE NUMBER OF ARGUMENTS ■ 685 C++ allows you to define functions that allow a variable number of arguments. One example of a function of this type is the standard C function printf(), which requires at least one argument, a format string. The printf() function uses the conversion specifiers in the format string to compute the number and type of arguments that follow. ᮀ Obligatory and Optional Arguments Functions with a variable number of arguments always expect a fixed number of obliga- tory arguments and a variable number of optional arguments. At least one obligatory argu- ment is required. As you would expect, you need to define an appropriate parameter for each obligatory argument when you define a function of this type. The optional arguments are repre- sented by three dots in the parameter list. The function shown opposite, func(), expects two or more arguments. The prototype is, thus, as follows Prototype: int func( char *buffer, int max, ); To allow functions with a variable number of arguments to be defined, C++ pushes the last argument onto the stack first. After calling the sample function func(), the stack looks like the diagram opposite. The optional arguments are accessed via a pointer, the so-called argument pointer, which is designated by argptr here. The header files cstdarg or stdarg.h contain macros, which conform to ANSI standard, to manage the pointer and assure that the source code will be portable. ᮀ Access to Arguments The following steps are required to read the optional arguments: 1. The va_list type argument pointer argptr must be declared in addition to other local variables. The type va_list is defined in the header file stdarg.h as a typeless or char pointer. 2. The macro va_start() is then called to point the argument pointer argptr to the first optional argument. va_start() expects two arguments: the name of the argument pointer and the name of the last obligatory parameter. Example: va_start( argptr, max ); 686 ■ CHAPTER 30 MORE ABOUT POINTERS // input.cpp: The function input() reads characters // from the keyboard and appends '\0'. // The input can be corrected with backspace. // Arguments: 1. Pointer to the input buffer. // 2. Maximum number of characters to be read / 3. Optional arguments: Characters that // terminate the input. // This list has to end with CR = '\r'! // Returns: Character that breaks the input. // #include <stdarg.h> #include <conio.h> // For getch() and putch() int input(char *buffer, int max, ) { int c, breakc; // Current character, character to // break with. int nc = 0; // Number of characters read. va_list argp; // Pointer to the following arguments. while(true) { *buffer = '\0'; if( ( c = getch()) == 0) // Read a character. c = getch() + 256; // For special keys: // Extended code + 256. va_start(argp, max); // Initialize argp. do // Compare with break characters: if( c == (breakc = va_arg(argp,int)) ) return(breakc); while( breakc != '\r'); va_end( argp); if( c == '\b' && nc > 0) // Backspace? { nc, buffer; putch(c); putch(' '); putch(c); } else if( c >= 32 && c <= 255 && nc < max ) { // Place character into the buffer ++nc, *buffer++ = c; putch(c); // and output. else if( nc == max) // Is end of buffer reached? putch('\a'); // Beep. } } ■ VARIABLE NUMBER OF ARGUMENTS (CONTINUED) The function input() VARIABLE NUMBER OF ARGUMENTS (CONTINUED) ■ 687 3. When the macro va_arg() is called, the optional argument pointed to by argptr is read from the stack. The arguments of va_arg() are the name of the argument pointer and the type of the optional argument: Example: arg3 = va_arg( argptr, long); Each call to the macro va_arg() sets the argument pointer to the next optional argument. The result of va_arg() has the type stated in the call. It must be identical to the type of the corresponding optional argument. There is no special terminating condition for the last optional argument. A spe- cific value (such as NULL, Ϫ 1 or CR) can be used, or the current number of argu- ments can be defined by an obligatory argument. 4. After evaluating the arguments the argument pointer is set to NULL by the va_end() macro: Example: va_end( argptr); Optional arguments can also be read more than once. The procedure described above is repeated beginning at Step 2, that is, with the macro va_start(). ᮀ Notes on the Example Opposite The sample function input() on the opposite page uses the getch() function to read character input from the keyboard and store it in the buffer addressed by the first argu- ment. The second argument defines the maximum number of characters to be read. All other arguments are characters that can terminate keyboard input. The last argument must be a return character ('\r')! Example: #define ESC 27 // ESC key #define F1 (256 + 59) // F1 key input( name, 20, ' ', ESC, F1, '\r'); This call to input() reads up to 20 characters and stores them in the array name. Input can be terminated by pressing the space, ESC, F1, or return keys. The return value is the corresponding character code. Non-printable characters are ignored unless stated as optional arguments. Special keys, such as the function keys, return a value of 0 for the first call to getch() and the extended code for the second call. For function keys this code is within the range 59–68. To distinguish extended codes from normal ASCII codes (0–255), the value 256 is added to the extended code. A table of extended codes is available in the Appendix. 688 ■ CHAPTER 30 MORE ABOUT POINTERS // funcptr.cpp: Demonstrates the use of an array // of pointers to functions. // #include <iostream> #include <cstdlib> // Prototype of atoi() #include <cctype> // Macros toupper(), tolower() using namespace std; void error_message(char *), message(char *), message_up(char *), message_low(char *); void (*functab[])(char *) = { error_message, message, message_up, message_low }; char call[]="Input: 1,2, or 3"; int main() { int n = 0; cout << "Which of the three functions " << "do you want call (1,2, or 3)?\n"; cin >> n; if( n<1 || n>3) (*functab[0])( call ); else (*functab[n])("Hello, world\n"); return 0; } void error_message( char *s) { cerr << s << endl; } void message( char *s) { cout << s << endl; } void message_up( char *s) { int c; for( ; *s != '\0';++s) c = toupper(*s),cout.put(c); } void message_low( char *s) { int c; for( ; *s != '\0';++s) c = tolower(*s), cout.put(c); } ■ POINTERS TO FUNCTIONS A jump table . element in the array. Since each element in the array is a pointer, this pointer variable must be a pointer to a pointer. ᮀ Generating Pointer Arrays Dynamically Now let’s look into creating a dynamic. necessary if ■ an array of pointers is to be dynamically allocated, or ■ a function expects an array of pointers as an argument. In both cases you need to declare a pointer variable that can access the. varying argument Varying arguments Last varying argument va_start(argp,max) char *buffer int max • • • #include <stdarg.h> int func( char *buffer, int max, ) { va_list argptr; // Declares

Ngày đăng: 06/07/2014, 17:21

Tài liệu cùng người dùng

Tài liệu liên quan