Reading Assignment Main Program Revisited

void main( int argc , char * argv[] )

K.N. King Chapter 3, 22 argc is the number of command line arguments that have been passed to the main program

K.N. King Sections 13.7 argv is a pointer to an array of strings which are the arguments to the program – argv[ 0 ] is the name that was used to invoke the program. – argv[ 1 ] to argv[ argc ] are the arguments that were passed to the program. – argv[ argc + 1 ] is always NULL

myMain fee fie foo fum myMain fee argc 4 argv fie foo fum

305 306

Example of Argument Processing main( int argc , char argv[] ) { HOW TO Access Environment Information /* Argument Processing */ #include ¡ stdlib.h ¢ for (argc--, argv++; argc > 0; argc--, argv++) { char * getenv ( const char * name ) ; /* process options marked with - */ if (**argv == ’-’) { /* A flag argument */ /* Process all flags in this arg, e.g. -AbDf */

In the Unix Shell you can set environment variables that can be used to while (*++(*argv)) { switch (**argv) { communicate information to programs. Execute the Unix command case ’x’: /* process one flag */ printenv ...... to see what your current environment variables are. break;

default: The getenv function can be used by a program to retrieve the current value of fprintf(stderr, "Unknown flag: ’%’; ", **argv); environment variables from Unix. exit(1); The argument name is the name of an an environment variable, getenv } } returns a pointer to a string containing the value currently assigned to name } and NULL if name is not defined. else /* Process everyting else */ Example: Define TMPDIR=/bigSpace/tmp in environment. process( *argv ); /* Do something to argument */ } } 307 308

Input and Output in C The three are automatically ready to use when a program starts execution. #include £ stdio.h ¤

A stream is any source of input or any destination for output. By convention, standard error is used for printing error messages. These messages can be redirected to a destination that is different than standard

A file pointer ( of type FILE * ) is the standard way to refer to streams in C output. programs.

stdio.h defines three standard streams File Pointer Stream Default Meaning

stdin Standard Input Keyboard input

stdout Standard Output Terminal Screen

stderr Standard Error Terminal Screen The command that invokes a program may redirect the meaning of the standard streams to be a file, a device or another program.

Programs are usually written to work on the standard streams. If a program needs more sources or destinations it can create them as it’s executing.

309 310

Text and Binary Files Character Input (Text Files)

stdio.h supports two kinds of files. int fgetc(FILE * stream ) Read one character from stream

int getc(FILE * stream ) Inline version of fgetc Text Files generally contain characters and are usually easily readable or printable. Text files are viewed as a sequence of lines where lines are int getchar( void ) getc(stdin) separated by the NEWLINE character ( ’\n’). char *fgets( char * S , int N , FILE * stream ) Reads at most N - 1 characters into array S Stops on newline. S is null terminated

Binary files contain raw data in the encoded in the internal representation used by the hardware. int ungetc( int C, FILE * stream ) Push character c back onto stream

Character input functions return the special value EOF on end of file or error. Binary files can be used to store arrays, structures and other more WARNING: getc, fgetc and getchar return int not char . complicated data structures. String input functions return NULL on end of file or error.

Generally binary input and output is much more efficient than text input and output since no conversion to/from the binary internal representation is required.

311 312 Character Input Examples int ch; HOW TO Handle Errors and End of File

FILE * fp; Every call on an input function must check for possible end of file or ... error. while ((ch = getc(fp)) != EOF) {

... WARNING: The value of EOF returned by fgetc, getc and getchar is NOT a } valid char value. Always read characters into an int variable, check for EOF and then assign fgets(str, sizeof(str), fp); /* reads a line from fp */ the input to a char variable. fgets(str, sizeof(str), stdin);

The function /* read a line from standard input */ int feof( FILE * stream ) #include returns true if an end of file has been detected while reading stream. Note ... that this function does not return true until an attempt has been made to read while (isdigit(ch = getc(fp))) { past the end of file. ... } ungetc(ch, fp); /* puts back last value of ch */

313 314

Character Output (Text Files) Formatted Output int fputc( int C , FILE * stream ) writes character C on stream

A format string is used to specify the exact layout of each line of printed int putc( int C , FILE STAR stream ) inline version of fputc output. int putchar( int C ) putc(C , stdout)

The format string may contain text which is output literally int fputs( const char * S, FILE * stream) writes string S on stream

int puts( const char * S) fputs( S , stdout) The format string contains format control characters which cause data values to be printed. Output functions return EOF on error.

Embed ASCII control characters (e.g. \n (newline) , \t (tab) and \f Examples: (pagefeed)) in format string for line and page control FILE * fp ;

WARNING: Be Careful to exactly match format string with argument list. ... Mismatches cause crashes. putchar( ch);/*writes ch to stdout */

putc( ch, fp ) ; /* writes ch to fp */ Sink for output can be standard stream, file or string puts( "Hello world!" ) ; /* writes to stdout */ fputs( "Hello world!" , fp ) ; /* writes to fp */

315 316 printf function Format Control Characters %C printf(const char * format , expressionList ) %-C %widthC expressionList is a list of expressions separated by commas %.precC format is a string that specifies formating for printed output C is any format control character Expressions in the expression list are matched in order with format control A preceding - sign causes the field to be left justified characters in format width and prec are integer constants. width specifies the printed width of the field in characters. prec specifies number of digits after decimal point for floating point WARNING: most versions of C do NOT check that you’ve got this right. Be numbers especially careful about char vs. string and different sizes of integers and reals. width or precision can be * which causes value to be taken from next argument

317 318

Output Format Control Characters Examples of formatted output

c single character p void *, pointer printf("CSC209S Assignment %\n", aNumb );

sstring f real, normal notation sprintf( buffer, "(%s%c%s)", d integer, signed decimal e real, scientific notation left_op, operator, right_op ); i integer, signed decimal E real, scientific notation u integer, unsigned decimal g real, shorter of e, f, notation fprintf(myFile, "%-d %s %e\n", o integer, unsigned octal G real, shorter of E, f, notation count, name, result );

x integer, unsigned printf("Pointer value is %p (%x)\n", p, p ) ; X integer, unsigned hexadecimal

printf("%.*f", 4, x); printf("%.*f", WIDTH, x); printf("%*.4f", 12, x);

319 320 fprintf & sprintf HOW TO Use Files in C fprintf(FILE * stream,const char * format, expressionList)

InaCprogram,afileisahandle that is used to access some external source sprintf(char * S,const char * format, expressionList) or destination for data.

The FILE * is a pointer to a control block that specifies the type of a format and expressionList same as printf. stream, how to access the stream and the current location in the stream for fprintf writes output to the designated file input or output. sprintf writes output to the designated string

The system establishes default streams for stdin, stdout and stderr. These WARNING: Be Careful to always give a file as first argument to fprintf can be overridden via redirection at the Unix command level. and a string as first argument to sprintf.

Make sure that string for sprintf is large enough to hold any possible The fopen function is used to set up an association between an external file result including a trailing null character. and a stream in the program.

The fclose function is used to terminate the association set up by fopen.

321 322

File Open File Close

FILE * fopen( const char * filename, const char * mode ) ; int fclose( FILE * stream )

Opens named file and returns stream pointer or NULL if open fails. Flush any unwritten data to output stream

Files must be opened before they are used for reading or writing. Discard any unread input in input stream Modes include: Deallocates buffer, closes stream. ”r” open for reading

”w” create text file for writing, discard previous contents File should not be used after it is closed.

”a” open for append or create Returns zero if successful; otherwise returns EOF ”r+” open for update (read & write)

”w+” create text file for update

”a+” open or create for append & update

WARNING: Always check that fopen has returned a non-NULL pointer.

323 324 scanf - formatted input scanf function

User supplies format string, as in printf. int scanf(char *format,varAddressList ) Format string specifies order and format of input items.

User provides addresses of variables in which to store input items. format is a format string specifying the expected input format

scanf attempts to read from its input source and match the input stream varAddressList is a list of addresses of variables. against the format string. Successful matches cause values to be assigned to Use either pointers to allocated memory or & variable to generate the address the variables. of local variables.

scanf returns number of variables assigned to, which may be less than the Always check number of assignments done by scanf number of items requested. Always provide a variable ADDRESS for each data item in the format list

325 326

scanf format string scanf conversion charactersa

One more consecutive white-space in a scanf format string match zero or Char Type Variable

more white-space in the input stream. d decimal integer int *

Ordinary characters are expected to match the characters in the input stream i integer (any) int *

Conversion items beginning with % cause data values to be read and o octal integer int * assigned to the next unassigned variable. u unsigned integer unsigned *

An assignment suppression character * after the % causes a data item to be x hex integer int * read by suppresses assignment to the variable. Use this to skip over c character (no ws skip) char * unwanted input. sstring char *

scanf automatically skips over white-space (blank, tab, newline, carriage e float float * return, etc.) in its input f float float *

% can be followed by an integer constant width specifier that controls the g float float * number of input characters read. e.g %1s to read 1 character at a time. aSee King pages 493-494 for a discussion of conversion modifiers.

327 328 scanf examples fscanf and sscanf int fscanf( FILE * stream, char * format , varAddressList ) int i, j ; int sscanf( char * source, char * format, varAddressList ) long k ; double X ; char ch, str[100]; fscanf like scanf except input comes from designated file int nScanned ; sscanf like scanf except input comes from character string nScanned = scanf("%d%i" , & i , & j ); Example: fscanf(inFile , ”%s” , str ); /* read string from file */ nScanned = scanf("%s is %c" , str , & ch ); sscanf(str , ”%d%d” , &i , &j ); /* extract two int from str */ nScanned = scanf("%*d%d" , & i); nScanned = scanf("%le%ld", & X , & k );

329 330

HOW TO Use sscanf and ssprintf Block Input and Output

sprintf can be used in a program to build up complicated character strings. size t fread( void * ptr , size t size , size t nmemb , FILE * stream ) – More efficient than using several strcpy/strcat operations. size tfwrite(const void * ptr , size t size , size t nmemb , FILE * stream )

– Provides access to all of the builtin conversion routines from internal representation to characters. fread reads an array from a stream to memory (ptr) in a single operation

scanf can be used in a program to scan strings and extract information. fwrite copies an array from memory (ptr) to a stream in a single operation – Provides access to the internal conversion routines.

– Can read input with fgets and then try alternative analysis with different scanf calls. ptr is the address of the data to transfer Allows you to validate input without crashing the program. size is the size of each element of an array in bytes

WARNING: make sure string argument to sprintf is long enough to hold any nmemb is the number of array elements to write/read possible output. return value of fread is the number of elements read

return value of fwrite is the number of elements written

Good Technique: check return value against nmemb

331 332 HOW TO Use fread & fwrite WARNING: reading and writing any data structure containing pointers (including char * ) will NOT produce a correct result.

Use fread and fwrite to move blocks of binary information between memory

and disk files. Example Test case Write 100,000 random double numbers to a file.

fread and fwrite are much more efficient than fprintf and fscanf for moving fwrite was about 150 times faster then fprintf. large amounts of data to/from disk. Read 100,000 random double numbers from a file.

The function setvbuf can be used to disable buffering when reading and fread was about 40 times faster than fscanf. writing binary information. This may improve speed. Binary file was 800,000 bytes, text file was 1,300,000 bytes.

Yo u c a n s e t size to total number of bytes to transfer and nmemb to one. This may be faster.

333 334

Example of Binary Input/Output Seek & Tell struct dStruct { long ftell( FILE * stream ) double xCoord, yCoord, zCoord ; int fseek( FILE * stream , long offset , int origin ) long redColor, greenColor, blueColor ; }; ftell returns the current position in the file stream struct dStruct data[ 10000 ] ; FILE * dataFile ; fseek sets the file position for stream. ... Position is set offset bytes from origin assert( ( dataFile = fopen( "myFile", "w"))); origin is one of: fwrite( & data[ 0 ] , sizeof( struct dStruct ) , 10000 , dataFile ); SEEK_SET - start of file fclose( dataFile ); SEEK_CUR - current position ... SEEK_END - end of file assert( ( dataFile = fopen( "myFile", "r"))); Use SEEK_SET with value from ftell fread( & data[ 0 ] , sizeof( struct dStruct ) * 10000 , Use fseek( file , 0L , SEEK CUR ) to reset internal file pointers between 1 , dataFile ); read and write operations on the same file. fclose( dataFile );

335 336 Reading Assignment

Processes program text before compiler

Implements K.N. King Chapter 14 Source Include mechanism Conditional compilation Section 26.1 Macro Definition and Use

337 338

Source inclusion Example Interface File

Used to decompose large programs into manageable pieces /* File house.h - Interface to house.c */

Most common usage is: /* Hide real representation inside house.c */ foo.h - interface file #define HOUSE HEIGHT 2.0 foo.c - implementation #define HOUSE WIDTH 3.0 foo.o - compiled implementation #define ATTIC HEIGHT 0.7

Interface file contains: ¥ ¥ ¥ function headers extern void DrawHouse(double x , double y) ; shared definitions extern void DrawOutline(double x , double y) ; structs, constants,types, macros extern void DrawWindows(double x , double y) ; Avoid shared variables extern void DrawDoor(double x , double y) ; extern void DrawBox(double x , double y , double width , double height) ;

Programs that use foo include foo.h to get interface extern void DrawTriangle(double x , double y , double base , double height) ; and get linked with foo.o to get the implementation extern void DrawCenteredCircle(double x , double y , double r) ; ¥ ¥ ¥

339 340 #include Macros

#include "fileName" A macro is a piece of text that is used repeatedly in a program. #include

Use macros for: defining literal constants defining short pieces of ugly code

fileName is the name of the file to include. hiding details from the user Compiler searches through a standard list of directories looking for it.

Usually start with current directory. Macros affect the source program text just before the program is compiled.

The second form specifies a system interface file. The compilers search starts in the directory /usr/include

Good Technique: Use only the first form of include. The compiler will still find system files, but you can customize include files if you have to.

341 342

Macro Definition Simple Macro Examples

#define macroName text #define BUFSIZE ( 1024 ) #define NULL ( (void * )0)

macroName is the name of the macro #define TRUE ( 1 ) Good Technique: use UPPERCASE NAMES for macros to make them stand #define FALSE ( 0 ) out a program that uses them

The text (if any) on the same line following the macro name becomes the #define TWO PI (2*3.14159) definition of the macro. #define RESET i=j=k=0 ; Use the backslash character ( \ ) at the end of a line to extend long ¦ § #define POLYX ( x * (x * (3.14 * x + 2.78) + 1.35) - 2.16 ) definitions.

Examples: #define CLEARA int i ; for (i=0;i< N ; ) \ ¦ #define A SIZE ( 15 ) A[i++] = 0 ; § #define PROMPT (”Hi:” )

343 344 Examples Macro with Parameters

Macro Parameters #define macroName( macroParmList ) text

Macros can be defined with simple text parameters that are substituted as directed in the body of the macro macroParmList is a list of identifiers separated by commas

Parameters are identifiers listed in parentheses after the macro name Examples:

Use this form for declarations or code fragments with substitutable parts #define SCALE(x) ((x)*10)

Parameter substitution is text substitution #define MIN(x,y) ( (x) < (y) ? (x) : (y) ) #define POLY(x) ( (x)*((x)*(3.14*(x)+2.78)+1.35)-2.16 ) #define FILLARRAY( arr , val , n) \ int i; for (i=0 ; i < (n) ; ) arr[i++] = val; ¦ §

Examples of use: j = SCALE( i + 1 ) ; if (MIN(i, j ) == 0 ) ... y = POLY( y+7.0 ) ; FILLARRAY( myData , 100 , 3.14 ) ;

345 346

HOW TO Use Macros Macro Use Use macros for program parameterization and as an abstraction tool.

For macros without parameters, just write name of macro in program, C Don’t use it to make programs unreadable or obscure. preprocessor substitutes macro body for name Make body of macro a complete expression or statement

For macros with parameters, follow macro name with list of macro parameters Macros with expression parameters should be designed to work with any enclosed in parentheses. The text of each parameter is substituted into the valid expression passed as an argument. macro body Good Technique: Wrap parameter names in parentheses to avoid

Examples: unexpected expansions and to force error message for invalid parameters

Good Technique: Macros that look like statements should behave like char buf1[ BUFSIZE ] ; statements. Wrap body in and . Do not put ; at end. ¦ § int allDone = FALSE ;

float circumference = TWO PI * r ; The truly paranoid will use each macro parameter exactly once. i = MAX( 1 , i ) ; SWAP( A[k] , A[k+1] ); STOPHERE ;

347 348 More Macro Examples Conditional Compilation

#define DATARRAY(name,size) float name[size] Used to selectively include or exclude parts of a program #define MAX( a, b ) ((a) > (b) ? (a) : (b) )

Used for: #define SWAP( x, y ) int t =(x); x = (y); y = t ¨ © #define CRASH_AND_BURN( why ) \ Optional code (e.g. debugging) fprintf(stderr, ”Bailing out of program due to error %s\n”, why ); \ Machine customization ¨ abort(); \ Operating system customization ©

Select based on: #define MALLOC( size, type , pointer ) \ defined and undefined macro names void * mTemp ; \ ¨ compiler flags -Dname , -Dname=value , -Uname mTemp = malloc( (size) ) ; \ compile time expressions, can use most C operators assert (mTemp); \ pointer = ( type ) mTemp ; \ Conditionals may be nested ©

Note use of ( ) around expressions and around statements. © ¨ mTemp is used in MALLOC to achieve the one-touch property.

349 350

Preprocessor Constant Expressions #if head #if constant-expression

The conditional expression that the preprocessor can evaluate are made up of #ifdef identifier – Integer constants defined using #define . #ifndef identifier – Integer constants defined using the compiler option -Dname=constant

– use of the defined( identifier ) function which has the value one if the identifier has The three forms of if head listed above are used at the start of a preprocessor been defined in the preprocessor at that point. conditional statement. – Almost all C arithmetic and logical operators. Logical expressions can be used to define complicated conditions. the first form is true if the constant (i.e. compile time) expression evaluates to non-zero. – Symbols predefined by the compiler, e.g. i486 , GNUC Generally these symbols identify the hardware, the compiler and the operating This expression can include use of the defined(identifier) predicate

system. Second form is true if identifier has been defined using #define or by the Use the command gcc -dM -E to see your definitions. compiler -D option.

Third form is true if identifier has not been defined using #define or it has been undefined using the compiler -U option.

351 352 #if examples

Preprocessor Conditional Statement #if X==3 if-head int data3[ 100 ] ; text #else #elif constant-expression int data2[ 50 ], data1[ 200 ] ; text #endif #ifdef DEBUG #else fprintf(stderr, ”Made it as far as Checkpoint Charlie\n”); text #endif #endif #ifndef ONCE #define ONCE text is any program text. It may be arbitrarily long. It may contain nested ... conditionals. #endif #if defined(UNIX) || defined( unix ) If if-head evaluates to true, text is included in the program #include < stdio.h> The elif part may be repeated as many times as required. The else part is #elif defined(VMS) #include < VMSstdio.h> optional. If it appears, then the text following the #else is included in the #else program if none of the preceding if or elifs have evaluated to true. #include ”D:/SYS/INCLUDE/STDIO.H” #endif 353 354

HOW TO USE #if et.al. Functions with a Variable Number of Arguments

KISS There is a mechanism in C that allows you to write your own functions that take a variable number of arguments like printf and scanf.

Use conditional compilation sparingly to customize your program for different

environments. The include file stdarg.h defines three macros void va start( va list ap , parmN ) ;

Use indentation and paragraphing to indicate matching #if , #else and #endif. type-name va arg( va list ap, type-name ) ;

Complicated #if structures are a symptom of bad program design. void va end( va list ap ) ; that can be used to access variable length argument lists in a safe and As with any use of conditionals, make sure all cases are covered and each logical expression does what you expect. portable way.

A function that takes a variable number of arguments must have at least one KISS named argument. An ellipsis ( ...) is used to tell the compiler that the function takes an arbitrary number of arguments. Example int doList( int first , . . . ) ;

355 356 HOW TO Use Variable Length Argument Lists

Declare a variable of type va list to hold an index into the variable length argument list while it is being processed. Example va list ap ;

The variable argument list comes after the last named parameter. Call va start to initialize the argument pointer ap to the first variable argument va start( ap, first ) ;

The function va arg is used to fetch a variable argument and advance to the next argument in the list. argVal = va arg( ap , type-name ) ; where type-name is the type of the variable ( argVal ) being assigned to.

Call the function va end to clean up after argument processing. va end( ap ) ;

You can cycle through the argument list more than once by calling va start to reinitialize the argument pointer. You can use more than one argument pointer on the same list. 357