1 / 46

Chapter 20 - C Legacy Code Topics

Chapter 20 - C Legacy Code Topics. Outline 20.1 Introduction 20.2 Redirecting Input/Output on UNIX and DOS Systems 20.3 Variable-Length Argument Lists 20.4 Using Command-Line Arguments 20.5 Notes on Compiling Multiple-Source-File Programs

cirila
Télécharger la présentation

Chapter 20 - C Legacy Code Topics

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. Chapter 20 - C Legacy Code Topics Outline 20.1 Introduction 20.2 Redirecting Input/Output on UNIX and DOS Systems 20.3 Variable-Length Argument Lists 20.4 Using Command-Line Arguments 20.5 Notes on Compiling Multiple-Source-File Programs 20.6 Program Termination with exit and atexit 20.7 The volatile Type Qualifier 20.8 Suffixes for Integer and Floating-Point Constants 20.9 Signal Handling 20.10 Dynamic Memory Allocation with calloc and realloc 20.11 The Unconditional Branch: goto 20.12 Unions 20.13 Linkage Specifications

  2. 20.1 Introduction • Several advanced topics in chapter • Many capabilities specific to OS • Especially UNIX and/or DOS • Chapter for C++ programmers working with C legacy code

  3. 20.2 Redirecting Input/Output on UNIX and DOS Systems • Standard I/O • Keyboard (input) and screen (output) • Can redirect I/O • Inputs can come from a file, output can go to a file • Redirect symbol (<) • Operating system feature (not C++ feature!) • UNIX and DOS • $ myProgram < input • myProgram is an executable file • input is a data file • $ is the command-line prompt • Input to program now comes from file input, not the keyboard

  4. 20.2 Redirecting Input/Output on UNIX and DOS Systems • Pipe command ( | ) • Output of one program becomes input of another • $ firstProgram | secondProgram • Output of firstProgram goes to secondProgram • Redirect output ( > ) • Output of program goes to a file • $ myProgram > myFile • Output goes tomyFile(erases previous contents)

  5. 20.2 Redirecting Input/Output on UNIX and DOS Systems • Append output (>>) • Output of program appends to end of file • $ myProgram >> myFile • Output goes to end of myFile

  6. 20.3 Variable-Length Argument Lists • In C++, we use function overloading • Variable-length arguments for programmers working with C • Create functions with unspecified number of arguments • Function format • Include <cstdarg> • Use ellipsis (…) at end of parameter list • Must be last item in parameter list • Must be one named parameter before ellipsis • double myFunction(int i, …);

  7. 20.3 Variable-Length Argument Lists • Usage (inside function) • Declare object of type va_list • Holds data needed by other macros • va_list myList; • Run macro va_start • First argument is va_list object • Second is last parameter before ellipsis starts • va_start( myList, i );

  8. 20.3 Variable-Length Argument Lists • Usage • Access arguments with macro va_arg • First argument is va_list • Second is the expected type of variable • Returns the value • myArg = va_arg( myList, double ); • Can use different data types for different arguments • Run macro va_end • va_end( myList );

  9. 1 // Fig. 20.2: fig20_02.cpp 2 // Using variable-length argument lists. 3 #include <iostream> 4 5 using std::cout; 6 using std::endl; 7 using std::ios; 8 9 #include <iomanip> 10 11 using std::setw; 12 using std::setprecision; 13 using std::setiosflags; 14 using std::fixed; 15 16 #include <cstdarg> 17 18 double average( int, ... ); 19 20 int main() 21 { 22 double double1 = 37.5; 23 double double2 = 22.5; 24 double double3 = 1.7; 25 double double4 = 10.2; 26 Note use of ellipsis in the prototype, and one defined argument before it. fig20_02.cpp(1 of 3)

  10. 27 cout << fixed << setprecision( 1 ) << "double1 = " 28 << double1 << "\ndouble2 = " << double2 << "\ndouble3 = " 29 << double3 << "\ndouble4 = " << double4 << endl 30 << setprecision( 3 ) 31 << "\nThe average of double1 and double2 is " 32 << average( 2, double1, double2 ) 33 << "\nThe average of double1, double2, and double3 is " 34 << average( 3, double1, double2, double3 ) 35 << "\nThe average of double1, double2, double3" 36 << " and double4 is " 37 << average( 4, double1, double2, double3, double4 ) 38 << endl; 39 40 return0; 41 42 } // end main 43 Call function with a variable number of arguments (passing the number of arguments as a parameter). fig20_02.cpp(2 of 3)

  11. 44 // calculate average 45 double average( int count, ... ) 46 { 47 double total = 0; 48 va_list list; // for storing information needed by va_start 49 50 va_start( list, count ); 51 52 // process variable length argument list 53 for ( int i = 1; i <= count; i++ ) 54 total += va_arg( list, double ); 55 56 // end the va_start 57 va_end( list ); 58 59 return total / count; 60 61 } // end function average Create a va_list object and call macro va_start. count is the parameter before the ellipsis. Extract each argument from list, treat as a double. End the macros, helps with a normal function return. fig20_02.cpp(3 of 3)

  12. double1 = 37.5 double2 = 22.5 double3 = 1.7 double4 = 10.2 The average of double1 and double2 is 30.000 The average of double1, double2, and double3 is 20.567 The average of double1, double2, double3 and double4 is 17.975 fig20_02.cppoutput (1 of 1)

  13. 20.4 Using Command-Line Arguments • Can pass arguments to main in UNIX/DOS • Include parameters in main • int main( int argc, char *argv[] ) • int argc • Number of arguments • char *argv[] • Array of strings that contains command-line arguments • Example: $ copy input output argc: 3 argv[0]: "copy" argv[1]: "input" argv[2]: "output"

  14. 20.4 Using Command-Line Arguments • Upcoming example • Program to copy input file to output file • copy input output • Read a character from file input and write to file output • Stop when no more characters to read (EOF)

  15. 1 // Fig. 20.3: fig20_03.cpp 2 // Using command-line arguments 3 #include <iostream> 4 5 using std::cout; 6 using std::endl; 7 using std::ios; 8 9 #include <fstream> 10 11 using std::ifstream; 12 using std::ofstream; 13 14 int main( int argc, char *argv[] ) 15 { 16 // check number of command-line arguments 17 if ( argc != 3 ) 18 cout << "Usage: copyFile infile_name outfile_name" << endl; 19 20 else { 21 ifstream inFile( argv[ 1 ], ios::in ); 22 23 // input file could not be opened 24 if ( !inFile ) { 25 cout << argv[ 1 ] << " could not be opened" << endl; 26 return-1; 27 28 } // end if Notice parameters in main. argv[1] is the input file -- open for reading. fig20_03.cpp(1 of 2)

  16. 29 30 ofstream outFile( argv[ 2 ], ios::out ); 31 32 // output file could not be opened 33 if ( !outFile ) { 34 cout << argv[ 2 ] << " could not be opened" << endl; 35 inFile.close(); 36 return-2; 37 38 } // end if 39 40 char c = inFile.get(); // read first character 41 42 while ( inFile ) { 43 outFile.put( c ); // output character 44 c = inFile.get(); // read next character 45 46 } // end while 47 } // end else 48 49 return0; 50 51 } // end main argv[2] is the output file -- open for writing. Read a character from inFile, and write to outFile. Loop stops when EOF reached. fig20_03.cpp(2 of 2)

  17. 20.5 Notes on Compiling Multiple-Source-File Programs • Program with multiple source files • Function definition must be entirely in one file • Cannot be split up into multiple files • Global variables accessible to functions in same file • Must be defined in every file they are used • Use extern to access global variable in another file • Indicates variable defined later in file or in another file • Example • int myGlobal; (defined in file1) • extern int myGlobal; (appears in file2)

  18. 20.5 Notes on Compiling Multiple-Source-File Programs • Function prototypes • Can be used in other files, extern not needed • Include prototype in each file function used • Compile files together • Prototype indicates function defined later in same file, or in another file • Example: loading header files • #include <cstring> • Contains prototypes of functions • We do not need to know where definitions are

  19. 20.5 Notes on Compiling Multiple-Source-File Programs • Keyword static • In context of global variables/functions • Can only be used by functions in same file • Internal linkage • Globals/functions have external linkage by default • Used with utility functions called only in one file • For functions • If defined before used, include static in definition • Otherwise, use with prototype • Makefiles • make - utility to aid compilation and linking • Saves effort of constantly recompiling for minor changes

  20. 20.6 Program Termination with exit and atexit • Function exit • Forces program to end • Usually takes EXIT_SUCCESS or EXIT_FAILURE • Symbolic constants (#define) • exit(EXIT_SUCCESS); • Returns value to environment, indicating success or failure • Exact value varies with system

  21. 20.6 Program Termination with exit and atexit • Function atexit • Takes pointer to function (function name) • atexit( myFunction ) • Functions must take void, return void • Registers function to run when program ends successfully • When exit called, or when main terminates • atexit does not terminate the program • Can register up to 32 functions • Use multiple atexit calls • Called in reverse order of registration

  22. 1 // Fig. 20.4: fig20_04.cpp 2 // Using the exit and atexit functions 3 #include <iostream> 4 5 using std::cout; 6 using std::endl; 7 using std::cin; 8 9 #include <cstdlib> 10 11 void print(); 12 13 int main() 14 { 15 atexit( print ); // register function print 16 17 cout << "Enter 1 to terminate program with function exit" 18 << "\nEnter 2 to terminate program normally\n"; 19 20 int answer; 21 cin >> answer; 22 Register print to be called when the program terminates. print must return void and take no arguments. print will be called if the program ends successfully. fig20_04.cpp(1 of 2)

  23. 23 // exit if answer is 1 24 if ( answer == 1 ) { 25 cout << "\nTerminating program with function exit\n"; 26 exit( EXIT_SUCCESS ); 27 28 } // end if 29 30 cout << "\nTerminating program by reaching the end of main" 31 << endl; 32 33 return0; 34 35 } // end main 36 37 // display message before termination 38 void print() 39 { 40 cout << "Executing function print at program termination\n" 41 << "Program terminated" << endl; 42 43 } // end function print Call function exit, passing a symbolic constant. fig20_04.cpp(2 of 2)

  24. Enter 1 to terminate program with function exit Enter 2 to terminate program normally 2 Terminating program by reaching the end of main Executing function print at program termination Program terminated Enter 1 to terminate program with function exit Enter 2 to terminate program normally 1 Terminating program with function exit Executing function print at program termination Program terminated fig20_04.cppoutput (1 of 1)

  25. 20.7 The volatile Type Qualifier • volatile qualifier • Indicates variable may be altered outside of program • Variable not under control of program • Compiler cannot perform certain optimizations

  26. 20.8 Suffixes for Integer and Floating-Point Constants • C++ has suffixes for constants • Integer suffixes • u or U (unsigned) • l or L (long) • ul or UL (unsignedlong) • Without suffix, uses smallest type that can hold number • Examples: 174u, 1322L, 7364ul • Floating point suffixes • f or F (float) • l or L (long double) • Without suffix, double • Examples: 3.14159L, 1.28f • Incorrect suffix is compiler error

  27. 20.9 Signal Handling • Signal • Unexpected event, can terminate program • Interrupts (ctrl-c) • Illegal instructions • Floating-point exceptions (division by zero) • Function signal traps unexpected signals • <csignal> • Takes signal number (symbolic constants defined) • Takes pointer to function (function name) • Signal handler passed signal number • May be required to call signal again inside handler • Depends on system • Reinitialize handler after it handles signal

  28. 20.9 Signal Handling

  29. 20.9 Signal Handling • Function raise • Takes signal number • Creates signal

  30. 1 // Fig. 20.6: fig20_06.cpp 2 // Using signal handling 3 #include <iostream> 4 5 using std::cout; 6 using std::cin; 7 using std::endl; 8 9 #include <iomanip> 10 11 using std::setw; 12 13 #include <csignal> 14 #include <cstdlib> 15 #include <ctime> 16 17 void signalHandler( int ); 18 19 int main() 20 { 21 signal( SIGINT, signalHandler ); 22 srand( time( 0 ) ); 23 Register signalHandler to deal with SIGINT events. fig20_06.cpp(1 of 3)

  31. 24 // create and output random numbers 25 for ( int i = 1; i <= 100; i++ ) { 26 int x = 1 + rand() % 50; 27 28 // raise SIGINT when x is 25 29 if ( x == 25 ) 30 raise( SIGINT ); 31 32 cout << setw( 4 ) << i; 33 34 // output endl when i is a multiple of 10 35 if ( i % 10 == 0 ) 36 cout << endl; 37 38 } // end for 39 40 return0; 41 42 } // end main 43 Note call to function raise. fig20_06.cpp(2 of 3)

  32. 44 // handles signal 45 void signalHandler( int signalValue ) 46 { 47 cout << "\nInterrupt signal (" << signalValue 48 << ") received.\n" 49 << "Do you wish to continue (1 = yes or 2 = no)? "; 50 51 int response; 52 53 cin >> response; 54 55 // check for invalid responses 56 while ( response != 1 && response != 2 ) { 57 cout << "(1 = yes or 2 = no)? "; 58 cin >> response; 59 60 } // end while 61 62 // determine if it is time to exit 63 if ( response != 1 ) 64 exit( EXIT_SUCCESS ); 65 66 // call signal and pass it SIGINT and address of signalHandler 67 signal( SIGINT, signalHandler ); 68 69 } // end function signalHandler May be required to reinitialize. fig20_06.cpp(3 of 3)

  33. 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 Interrupt signal (2) received. Do you wish to continue (1 = yes or 2 = no)? 1 100 1 2 3 4 Interrupt signal (2) received. Do you wish to continue (1 = yes or 2 = no)? 2 fig20_06.cppoutput (1 of 1)

  34. 20.10 Dynamic Memory Allocation with calloc and realloc • Dynamic memory allocation • Can create dynamic arrays • Function calloc • void *calloc(size_t nelmt, size_t size) • nelmt - number of elements in array • size - size of each element • Returns pointer to dynamic array • Elements initialized to 0

  35. 20.10 Dynamic Memory Allocation with calloc and realloc • Function realloc • Resizes dynamic object • Data not modified if size increased • If shrunk, beginning the same • void *realloc(void *ptr, size_t newSize) • ptr - pointer to object being reallocated • newSize - new size of the object • If ptr == 0, acts like malloc • If newSize == 0 and ptr != 0, memory freed • Returns pointer to reallocated memory (NULL if no space)

  36. 20.11 The Unconditional Branch: goto • Unstructured programming • Use when performance crucial • Using break to exit loop • goto statement • goto label; • Program jumps to first statement after label • Label is an identifier and colon (start:) • Quick escape from deeply nested loop • goto start;

  37. 1 // Fig. 20.7: fig20_07.cpp 2 // Using goto. 3 #include <iostream> 4 5 using std::cout; 6 using std::endl; 7 8 #include <iomanip> 9 10 using std::left; 11 using std::setw; 12 13 int main() 14 { 15 int count = 1; 16 17 start: // label 18 19 // goto end when count exceeds 10 20 if ( count > 10 ) 21 goto end; 22 23 cout << setw( 2 ) << left << count; 24 ++count; 25 26 // goto start on line 17 27 goto start; Notice declaration of label start Note the format of the goto statement. fig20_07.cpp(1 of 2)

  38. 28 29 end: // label 30 31 cout << endl; 32 33 return0; 34 35 } // end main fig20_07.cpp(2 of 2)fig20_07.cppoutput (1 of 1) 1 2 3 4 5 6 7 8 9 10

  39. 20.12 Unions • Union • Memory that contains a variety of objects • Data members share space • Only contains one data member at a time • Conserves storage • Only the last data member defined can be accessed • Declaration same as class or struct union Number { int x; float y; } ; Union myObject;

  40. 20.12 Unions • Union operations • Assignment to union of same type: = • Taking address: & • Accessing union members: . • Accessing members using pointers: ->

  41. 20.12 Unions • Anonymous unions • No type name • Does not create a type; creates an unnamed object • Contains only public data members • Data members accessed like normal variables • Use name, no . or -> required • If declared globally, must be static • Example union { int integer1; double double1; char *charPtr; }; // end anonymous unioninteger1 = 3;

  42. 1 // Fig. 20.8: fig20_08.cpp 2 // An example of a union. 3 #include <iostream> 4 5 using std::cout; 6 using std::endl; 7 8 // define union Number 9 union Number { 10 int integer1; 11 double double1; 12 13 }; // end union Number 14 15 int main() 16 { 17 Number value; // union variable 18 19 value.integer1 = 100; // assign 100 to member integer1 20 21 cout << "Put a value in the integer member\n" 22 << "and print both members.\nint: " 23 << value.integer1 << "\ndouble: " << value.double1 24 << endl; 25 Create a named union with two data members. They share the same memory. This will print the integer 100 as a double. The program output is implementation dependent, but will show how ints and doubles are represented differently. fig20_08.cpp(1 of 2)

  43. 26 value.double1 = 100.0; // assign 100.0 to member double1 27 28 cout << "Put a value in the floating member\n" 29 << "and print both members.\nint: " 30 << value.integer1 << "\ndouble: " << value.double1 31 << endl; 32 33 return0; 34 35 } // end main fig20_08.cpp(2 of 2)fig20_08.cppoutput (1 of 1) Put a value in the integer member and print both members. int: 100 double: -9.25596e+061 Put a value in the floating member and print both members. int: 0 double: 100

  44. 1 // Fig. 20.9: fig20_09.cpp 2 // Using an anonymous union. 3 #include <iostream> 4 5 using std::cout; 6 using std::endl; 7 8 int main() 9 { 10 // declare an anonymous union 11 // members integer1, double1 and charPtr share the same space 12 union { 13 int integer1; 14 double double1; 15 char *charPtr; 16 17 }; // end anonymous union 18 19 // declare local variables 20 int integer2 = 1; 21 double double2 = 3.3; 22 char *char2Ptr = "Anonymous"; 23 Create an anonymous union. The data members can be accessed without using a union name. fig20_09.cpp(1 of 2)

  45. 24 // assign value to each union member 25 // successively and print each 26 cout << integer2 << ' '; 27 integer1 = 2; 28 cout << integer1 << endl; 29 30 cout << double2 << ' '; 31 double1 = 4.4; 32 cout << double1 << endl; 33 34 cout << char2Ptr << ' '; 35 charPtr = "union"; 36 cout << charPtr << endl; 37 38 return0; 39 40 } // end main fig20_09.cpp(2 of 2)fig20_09.cppoutput (1 of 1) 1 2 3.3 4.4 Anonymous union

  46. 20.13 Linkage Specifications • Can call compiled C functions from C++ program • However, C does not encode function names like C++ • Leads to problems linking • Linkage specifications • To link properly, tell compiler that function compiled in C • For single functions extern "C" function prototype • For multiple functions extern "C" { function prototypes }

More Related