C Program Design Supplements 主講人:虞台文
Content Who takes the return value of main() ? Using Command-Line arguments Variable-Length Argument Lists Program Termination by exit and atexit Unconditional Branching with goto C Preprocessor
C Program Design Supplements Who takes the return value of main() ?
main() int main( void ) { /* declaration of variable */ /* operations */ return result; /* who takes the result? */ } int main( void ) { /* declaration of variable */ /* operations */ return result; /* who takes the result? */ }
Example: Unix grep Ah Love! could you and I with Fate conspire To grasp this sorry Scheme of Things entire, Would not we shatter it to bits -- and then Re-mould it nearer to the Heart's Desire! Ah Love! could you and I with Fate conspire To grasp this sorry Scheme of Things entire, Would not we shatter it to bits -- and then Re-mould it nearer to the Heart's Desire! grepExample.txt Ah Love! could you and I with Fate conspire To grasp this sorry Scheme of Things entire, Would not we shatter it to bits -- and then Re-mould it nearer to the Heart's Desire! Ah Love! could you and I with Fate conspire To grasp this sorry Scheme of Things entire, Would not we shatter it to bits -- and then Re-mould it nearer to the Heart's Desire! grep "ould" grepExample.txt Ah Love! could you and I with Fate conspire Would not we shatter it to bits -- and then Re-mould it nearer to the Heart's Desire! Ah Love! could you and I with Fate conspire Would not we shatter it to bits -- and then Re-mould it nearer to the Heart's Desire!
Example: Unix grep Ah Love! could you and I with Fate conspire To grasp this sorry Scheme of Things entire, Would not we shatter it to bits -- and then Re-mould it nearer to the Heart's Desire! Ah Love! could you and I with Fate conspire To grasp this sorry Scheme of Things entire, Would not we shatter it to bits -- and then Re-mould it nearer to the Heart's Desire! grepExample.txt Ah Love! could you and I with Fate conspire To grasp this sorry Scheme of Things entire, Would not we shatter it to bits -- and then Re-mould it nearer to the Heart's Desire! Ah Love! could you and I with Fate conspire To grasp this sorry Scheme of Things entire, Would not we shatter it to bits -- and then Re-mould it nearer to the Heart's Desire! grep "ould" grepExample.txt Ah Love! could you and I with Fate conspire Would not we shatter it to bits -- and then Re-mould it nearer to the Heart's Desire! Ah Love! could you and I with Fate conspire Would not we shatter it to bits -- and then Re-mould it nearer to the Heart's Desire!
Pseudo Code The Idea to Fulfill the Task count = 0; while (there's another line) if (the line contains the pattern) print it count++; return count;
Pseudo Code The Idea to Fulfill the Task count = 0; while (there's another line) if (the line contains the pattern) print it count++; return count; How? Define functions to mind the detail. How? Define functions to mind the detail.
Pseudo Code The Idea to Fulfill the Task count = 0; while (there's another line) if (the line contains the pattern) print it count++; return count; Pseudo Code The Idea to Fulfill the Task int getline(char line[], int max) int strindex(char source[], char searchfor[])
Example: MyGrep #include #define MAXLINE 1000 /* maximum input line length */ int getline(char line[], int max); int strindex(char source[], char searchfor[]); char pattern[] = "ould"; /* pattern to search for */ /* find all lines matching pattern */ int main( void ) { char line[MAXLINE]; int count = 0; while (getline(line, MAXLINE) > 0) if (strindex(line, pattern) >= 0) { printf("%s", line); count++; } return count; } #include <stdio.h> #define MAXLINE 1000 /* maximum input line length */ int getline(char line[], int max); int strindex(char source[], char searchfor[]); char pattern[] = "ould"; /* pattern to search for */ /* find all lines matching pattern */ int main( void ) { char line[MAXLINE]; int count = 0; while (getline(line, MAXLINE) > 0) if (strindex(line, pattern) >= 0) { printf("%s", line); count++; } return count; } return information to OS
Example: MyGrep #include #define MAXLINE 1000 /* maximum input line length */ int getline(char line[], int max); int strindex(char source[], char searchfor[]); char pattern[] = "ould"; /* pattern to search for */ /* find all lines matching pattern */ main() { char line[MAXLINE]; int count = 0; while (getline(line, MAXLINE) > 0) if (strindex(line, pattern) >= 0) { printf("%s", line); found++; } return count; } #include <stdio.h> #define MAXLINE 1000 /* maximum input line length */ int getline(char line[], int max); int strindex(char source[], char searchfor[]); char pattern[] = "ould"; /* pattern to search for */ /* find all lines matching pattern */ main() { char line[MAXLINE]; int count = 0; while (getline(line, MAXLINE) > 0) if (strindex(line, pattern) >= 0) { printf("%s", line); found++; } return count; } while (there's another line) if (the line contains the pattern) print it forward references return information to OS
Batch Files
Example: MyGrep Ah Love! could you and I with Fate conspire To grasp this sorry Scheme of Things entire, Would not we shatter it to bits -- and then Re-mould it nearer to the Heart's Desire! Ah Love! could you and I with Fate conspire To grasp this sorry Scheme of Things entire, Would not we shatter it to bits -- and then Re-mould it nearer to the Heart's Desire!
練習: 1. 完成以上程式,並測試之。 2. 撰寫一程式讀取使用者從標準輸入裝置中輸 入之字元直到發生 EOF 止,該程式會將所讀 取到的字元總數回傳給作業系統後結束執行。 3. 撰寫一批次檔驗證你能正確收到上題程式之 回傳資料,並做適當顯示。
C Program Design Supplements Using Command-Line arguments
Pass arguments to main on DOS or UNIX int main( int argc, char *argv[] ) argument count argument vector argc: 3 argv[ 0 ]: "mycopy" argv[ 1 ]: "input" argv[ 2 ]: "output" Example: >mycopy input output
Example // mycopy.c #include int main( int argc, char *argv[] ) { FILE *inFilePtr; /* input file pointer */ FILE *outFilePtr; /* output file pointer */ int c; /* define c to hold characters input by user */ /* check number of command-line arguments */ if ( argc != 3 ){ printf( "Usage: mycopy infile outfile\n" ); return 0; } /* if input file can be opened */ if ( ( inFilePtr = fopen( argv[ 1 ], "r" ) ) != NULL ) { /* if output file can be opened */ if ( ( outFilePtr = fopen( argv[ 2 ], "w" ) ) != NULL ) { /* read and output characters */ while ( ( c = fgetc( inFilePtr ) ) != EOF ) { fputc( c, outFilePtr ); } /* end while */ } /* end if */ else { /* output file could not be opened */ printf( "File \"%s\" could not be opened\n", argv[ 2 ] ); } /* end else */ } else { /* input file could not be opened */ printf( "File \"%s\" could not be opened\n", argv[ 1 ] ); } /* end else */ return 0; /* indicates successful termination */ } /* end main */ // mycopy.c #include int main( int argc, char *argv[] ) { FILE *inFilePtr; /* input file pointer */ FILE *outFilePtr; /* output file pointer */ int c; /* define c to hold characters input by user */ /* check number of command-line arguments */ if ( argc != 3 ){ printf( "Usage: mycopy infile outfile\n" ); return 0; } /* if input file can be opened */ if ( ( inFilePtr = fopen( argv[ 1 ], "r" ) ) != NULL ) { /* if output file can be opened */ if ( ( outFilePtr = fopen( argv[ 2 ], "w" ) ) != NULL ) { /* read and output characters */ while ( ( c = fgetc( inFilePtr ) ) != EOF ) { fputc( c, outFilePtr ); } /* end while */ } /* end if */ else { /* output file could not be opened */ printf( "File \"%s\" could not be opened\n", argv[ 2 ] ); } /* end else */ } else { /* input file could not be opened */ printf( "File \"%s\" could not be opened\n", argv[ 1 ] ); } /* end else */ return 0; /* indicates successful termination */ } /* end main */
C Program Design Supplements Variable-Length Argument Lists
Examples printf int printf(const char *format,...); scanf int scanf(const char *format,...);
Variable-Length Argument List Type and Macros stdarg.h
#include void sum(char *, int,...); int main(void) { sum(" =%d.\n",3,10,15,13); sum(" =%d\n",5,11,12,13,14,15); return 0; } void sum(char *string, int num_args,...) { int sum=0; int loop; va_list ap; va_start(ap,num_args); for( loop=0; loop < num_args; loop++ ) sum+=va_arg(ap,int); printf(string,sum); va_end(ap); } #include void sum(char *, int,...); int main(void) { sum(" =%d.\n",3,10,15,13); sum(" =%d\n",5,11,12,13,14,15); return 0; } void sum(char *string, int num_args,...) { int sum=0; int loop; va_list ap; va_start(ap,num_args); for( loop=0; loop < num_args; loop++ ) sum+=va_arg(ap,int); printf(string,sum); va_end(ap); } Example
C Program Design Supplements Program Termination by exit and atexit
exit & atexit Function exit – Forces a program to terminate – Parameters – symbolic constants EXIT_SUCCESS or EXIT_FAILURE – Returns an implementation-defined value – Example: exit( EXIT_SUCCESS ); Function atexit atexit( functionToRun ); – Registers functionToRun to execute upon successful program termination atexit itself does not terminate the program – Register up to 32 functions (multiple atexit() statements) Functions called in reverse register order – Called function cannot take arguments or return values exit atexit
Example #include void print( void ); /* prototype */ int main( void ) { int answer; /* user's menu choice */ atexit( print ); /* register function print */ printf( "Enter 1 to terminate program with function exit" "\nEnter 2 to terminate program normally\n" ); scanf( "%d", &answer ); /* call exit if answer is 1 */ if ( answer == 1 ) { printf( "\nTerminating program with function exit\n" ); exit( EXIT_SUCCESS ); } /* end if */ printf( "\nTerminating program by reaching the end of main\n" ); return 0; /* indicates successful termination */ } /* end main */ /* display message before termination */ void print( void ) { printf( "Executing function print at program " "termination\nProgram terminated\n" ); } /* end function print */ #include <stdio.h> #include <stdlib.h> void print( void ); /* prototype */ int main( void ) { int answer; /* user's menu choice */ atexit( print ); /* register function print */ printf( "Enter 1 to terminate program with function exit" "\nEnter 2 to terminate program normally\n" ); scanf( "%d", &answer ); /* call exit if answer is 1 */ if ( answer == 1 ) { printf( "\nTerminating program with function exit\n" ); exit( EXIT_SUCCESS ); } /* end if */ printf( "\nTerminating program by reaching the end of main\n" ); return 0; /* indicates successful termination */ } /* end main */ /* display message before termination */ void print( void ) { printf( "Executing function print at program " "termination\nProgram terminated\n" ); } /* end function print */
Example #include void print( void ); /* prototype */ int main( void ) { int answer; /* user's menu choice */ atexit( print ); /* register function print */ printf( "Enter 1 to terminate program with function exit" "\nEnter 2 to terminate program normally\n" ); scanf( "%d", &answer ); /* call exit if answer is 1 */ if ( answer == 1 ) { printf( "\nTerminating program with function exit\n" ); exit( EXIT_SUCCESS ); } /* end if */ printf( "\nTerminating program by reaching the end of main\n" ); return 0; /* indicates successful termination */ } /* end main */ /* display message before termination */ void print( void ) { printf( "Executing function print at program " "termination\nProgram terminated\n" ); } /* end function print */ #include void print( void ); /* prototype */ int main( void ) { int answer; /* user's menu choice */ atexit( print ); /* register function print */ printf( "Enter 1 to terminate program with function exit" "\nEnter 2 to terminate program normally\n" ); scanf( "%d", &answer ); /* call exit if answer is 1 */ if ( answer == 1 ) { printf( "\nTerminating program with function exit\n" ); exit( EXIT_SUCCESS ); } /* end if */ printf( "\nTerminating program by reaching the end of main\n" ); return 0; /* indicates successful termination */ } /* end main */ /* display message before termination */ void print( void ) { printf( "Executing function print at program " "termination\nProgram terminated\n" ); } /* end function print */
C Program Design Supplements Unconditional Branching with goto
Unstructured programming – Use when performance crucial – break to exit loop instead of waiting until condition becomes false goto statement – Changes flow control to first statement after specified label – A label is an identifier followed by a colon (i.e. start: ) – Quick escape from deeply nested loop goto start;
Example #include int main( void ) { int count = 1; /* initialize count */ start: /* label */ if ( count > 10 ) { goto end; } /* end if */ printf( "%d ", count ); count++; goto start; /* goto start on line 9 */ end: /* label */ putchar( '\n' ); return 0; /* indicates successful termination */ } /* end main */ #include int main( void ) { int count = 1; /* initialize count */ start: /* label */ if ( count > 10 ) { goto end; } /* end if */ printf( "%d ", count ); count++; goto start; /* goto start on line 9 */ end: /* label */ putchar( '\n' ); return 0; /* indicates successful termination */ } /* end main */
C Program Design Supplements C Preprocessor
Preprocessing – Occurs before a program is compiled – Inclusion of other files – Definition of symbolic constants and macros – Conditional compilation of program code – Conditional execution of preprocessor directives Format of preprocessor directives – Lines begin with # – Only whitespace characters before directives on a line
Preprocessor Directives #include #define – Symbolic Constants – Macros Conditional Compilation #error and #pragma # and ## Operators Line Numbers Predefined Symbolic Constants Assertions
#include Copy of a specified file included in place of the directive #include – Searches standard library for file – Use for standard library files #include "filename" – Searches current directory, then standard library – Use for user-defined files Used for: – Programs with multiple source files to be compiled together – Header file – has common declarations and definitions (classes, structures, function prototypes)
#define : Symbolic Constants #define identifier replacement-text Example: When program compiled, all occurrences of symbolic constant replaced with replacement text. #define PI area = PI * r * r; area = * r * r;
#define : Symbolic Constants Example: #define PI area = PI * r * r; area = * r * r; Using meaningful names for symbolic constants By convention, using only uppercase letters and underscores.
#define : Macro Examples: #define max(a, b) a > b ? a : b x = max(y+7, 9); x = y+7 > 9 ? y+7 : 9; Compiler performs text substitution
#define : Macro Examples: #define max(a, b) a > b ? a : b x = max(y+7, 9); x = y+7 > 9 ? y+7 : 9; Compiler performs text substitution Any problems?
#define : Macro Examples: #define max(a, b) a > b ? a : b x = 10; y = 20; z = 11 + max(x, y) + 9; z = 40?
#define : Macro Examples: #define max(a, b) a > b ? a : b x = 10; y = 20; z = 11 + max(x, y) + 9; z = 40? z = 11 + x > y ? x : y + 9; z = 10 solution?
#define : Macro Examples: #define max(a, b) a > b ? a : b #define max(a, b) ((a) > (b) ? (a) : (b))
#define : Macro More Examples: #define PI #define CIRCLE_AREA(x) (PI * (x) * (x)) #define RECTANGLE_AREA( x, y ) ((x) * (y))
#define : Macro More Examples: #define max(a, b) ((a) > (b) ? (a) ? (b)) #define max3(a, b, c) {\ ((a) >= (b) ? max(a, c)\ : max(b, c)\ )\ } #define max4(a, b, c, d) {\ ((a) >= (b) ? max3(a, c, d)\ : max3(b, c, d)\ )\ }
#undef Undefines a symbolic constant or macro If a symbolic constant or macro has been undefined it can later be redefined