You are on page 1of 225

[Ronald ^Iteock
Reigafe Manual Writers

CAMBRIDGE UNIVERSITY PRESS

CAMBRIDGE NEW YORK PORT CHESTER MELBOURNE SYDNEY

CAMBRIDGE UNIVERSITY PRESS Cambridge. Cape Town. Cambridge CB2 8RU. Madrid. First published 1992 Reprinted (with corrections and in a larger format) 1993 Reprinted 1998 Re-issued in this digitally printed version (with corrections) 2008 A catalogue record for this publication is available from the British Library ISBN 978-0-521-46821-3 paperback . UK Published in the United States of America by Cambridge University Press. New York. Melbourne. Subject to statutory exception and to the provisions of relevant collective licensing agreements. no reproduction of any part may take place without the written permission of Cambridge University Press.cambridge. Sao Paulo Cambridge University Press The Edinburgh Building.org/9780521468213 © Cambridge University Press 1992 This publication is in copyright. New York www.cambridge. Singapore.org Information on this title: www.

for his enthusiasm and indispensable help with production.Acknowledgements l^y warmest thanks to the following people without whom the job of writing this book would have been lonely and terrifying: Paul Burden. . for patiently steering my rambling thoughts from nonsense to sense during many telephone conversations. Paul Shearing. Andrew. Mike Ingham. and making it worth while to continue instead of throwing it all in the bin. for the same thing. my elder son. for help with just about everything.

.

. CONSTANTS LITERAL CONSTANTS STRING LITERALS NAMED CONSTANTS ENUMERATIONS EXPRESSIONS STATEMENTS AND PROGRAM DECLARATIONS DECLARATION VS DEFINITION FUNCTION OLD-STYLE OPERATORS ARITHMETIC DEFINITION C PROTOTYPES HEADER FILES OPERATORS 30 31 32 33 33 33 34 34 35 36 37 37 37 s% 70 70 71 72 73 74 76 77 78 79 STORAGE CLASS OUTSIDE DECLARATIONS BLOCK DECLARATIONS DECLARATIONS PARAMETER NAME SPACE 38 V£f 38 38 39 39 39 JOINTERS. STRINGS POINTERS * OPERATOR & OPERATOR DECLARING POINTERS PARAMETERS QUICKSORT AGAIN POINTER ARITHMETIC PARLOUR TRICK POINTERS TO FUNCTIONS LOGICAL OPERATORS BITWISE OPERATORS ASSIGNMENT OPERATORS OPERATORS INCREMENTING REFERENCE 40 42 43 43 44 SEQUENCE OPERATOR OPERATORS 80 80 80 81 82 83 84 86 88 vu . ARRAYS.PREFACE ri OTHER OPERATORS SUMMARY 45 46 47 48 48 48 48 48 49 51 52 53 53 54 55 56 58 59 ^INTRODUCTION CONCEPTION REALIZATION DISSECTION 1 2 4 6 10 11 12 - PRECEDENCE & ASSOCIATIVITY MIXED TYPES PROMOTION & DEMOTION CAST PARAMETERS LITERAL CONSTANTS ACTION OF OPERATORS EXERCISES CONCEPTS DECISIONS I F . .ELSE LOOPS CHARACTERS ARRAYS MATRIX MULTIPLICATION HOOKE'S LAW FUNCTIONS CALL BY VALUE RATE OF INTEREST SCOPE OF VARIABLES RECURSION L ^ (jONTROL TESTED LOOPS COUNTED LOOP ESCAPE AREA OF A POLYGON SELECTION STATEMENT ROMAN NUMBERS SWITCH JUMP CABLES QUICKSORT 12 14 15 16 17 18 20 21 22 23 24 b ) 27 28 29 IF 60 62 64 65 66 67 68 68 69 69 EXERCISES s—•>. ORGANIZATION PROCESSING PREPROCESSOR SIMPLE MACROS MACROS WITH ARGUMENTS NESTED MACROS STRING ARGUMENTS HEADER FILES FUNCTION PROTOTYPES CONDITIONAL SYNTAX PREPROCESSING SUMMARY EXERCISES COMPONENTS NOTATION CHARACTERS NAMES SCALAR TYPES ON YOUR M A C H I N E .

OUTPUT ONE CHARACTER GET PUT UNGET PRINT FORMAT SCAN FORMAT EASIER INPUT STREAMS A D FILES N OPENING CLOSING REWINDING REMOVING RENAMING ERRORS CATS TEMPORARY FILES BINARY I/O RANDOM ACCESS DATABASE EXERCISES STRUCTURES. FILES LOW LEVEL I/O SINGLE CHARACTER I/O FILE MANAGEMENT RANDOM ACCESS STRING I/O FORMATS FOR I/O TEMPORARY BUFFERING PROCESS CONTROL TERMINATION LOCALE ERROR RECOVERY SIGNALS. UNIONS INTRODUCING STRUCTURES USAGE O F S T R U C T U R E S ACCESS OPERATORS STYLE O F DECLARATION BOOKLIST UNIONS BIT FIELDS SYNTAX TYPE OR SHAPE ALIAS DECLARATORS TYPE-NAME DECLARATION STACKS REVERSE POLISH NOTATION POLISH EXERCISES 107 108 108 109 109 110 112 114 116 116 117 117 117 118 118 119 120 121 122 123 Yte 125 126 128 129 130 131 132 133 134 134 134 135 135 136 138 139 141 142 SUMMARIES OPERATOR SUMMARY SYNTAX SUMMARY LIBRARY SUMMARY BIBLIOGRAPHY 209 L NDEX 210 VIU .COMPLEX DECLARATIONS STRINGS STRING ARRAYS STRING POINTERS PRINTING STRINGS RAGGED ARRAYS COMMAND LINE PARAMETER COUNTING STRING UTILITIES READ FROM KEYBOARD WHAT KIND OF CHARACTER? HOW LONG IS A STRING? COPYING STRINGS COMPARING STRINGS BACKSLANG EXERCISES 90 92 93 93 94 94 95 96 98 98 100 100 101 102 104 106 DYNAMIC STORAGE 143 144 146 148 149 150 154 156 158 161 162 163 164 164 164 165 166 167 168 170 170 171 171 173 174 175 176 176 177 179 180 181 182 182 183 184 185 186 187 187 188 189 190 191 192 195 196 197 204 MEMORY ALLOCATION STACKS POLISH AGAIN SIMPLE CHAINING SHORTEST ROUTE INTRODUCING RINGS ROSES BINARY TREES MONKEY PUZZLE EXERCISES LIBRARY INPUT. EXCEPTIONS VARIABLE ARGUMENT LIST MEMORY ALLOCATION STRING TO NUMBER MATHEMATICS ARITHMETICAL TRIGONOMETRICAL HYPERBOLICS RANDOM NUMBERS MODULAR DIVISION LOGARITHMS. OUTPUT. EXPONENTIALS CHARACTERS STRINGS STRING LENGTH COPY & CONCATENATE STRING COMPARISON STRING SEARCH MISCELLANEOUS STRINGS SORT. SEARCH DATE AND TIME FILES 4JNPUT.

UK. binary trees. TJfhe hand-written format of this book has evolved over several years. not only for writing computer systems but also for developing applications. and since. and over six previous books on computers and programming languages. • • I/or a formal appreciation of C a its p>ower. cliches. came out in 1978 and remained the most authoritative and best book on the subject until their second edition. appeared in 1988. It is now one of the most widely used programming languages. linked lists. Having learned to handle the car safely you would not willingly return to the family saloon. The pages contain the kind of diagram an able lecturer draws on the blackboard and annotates with encircled notes. describing ANSI standard C. the availability and use of C has increased exponentially. QE1GATE Surrey. parsing of algebraic expressions. Written text has been kept short and succinct. its advantages and disadvantages *=* see the references given in the Bibliography. IX hope the result looks friendly. doubly linked rings. n are many books on C but not so many on ANSI standard C which is the version described here. In all that time. As an informal appreciation: all those I know who program in C find the language likeable and enjoy its power. manipulation of strings. Programming C is like driving a fast and powerful car. making this a useful reference book on C to illustrate a few essential programming techniques such as symbol state tables. The first book on C. by Kernighan and Ritchie.I j h e original C programming language was devised by Dennis Ritchie. February 1992 IX . I have tried to avoid adverbs. ^fhis book attempts three things: • to serve as a text book for introductory courses on C aimed both at those who already know a computer language and at those entirely new to computing to summarize and present the syntax and grammar of C by diagrams and tables. jargon and unnecessarily formal language.

.

TJfhe chapter explains principles of running a C program on the computer. Check the manuals for your own installation. out to a complete novice it can be difficult to grasp. statement by statement. The concept is second nature to anyone who has programmed anything on any computer in any language. The explanation is sketchy because each implementation of C has different rules for doing so. l/inally the program is dissected. . So a simple program is written in English and then translated into C.ijfhe introduction starts with the concept of a stored program.

N and the monthly installment read from box M Work out (| 12 x value in box M x value in box N ]) to tell tell the client how much will have to be repaid.1 ) ) ([ £5000 in this case ]) represents the principal represents the rate of interest (J 0. R. any whole number of years. Tjfhis program is good for any size of loan.5% ]) represents the number of years (J 5 in this case}) Tjfo work this out the friendly bank manager might use the following 'program' of instructions: 1\ Get math tables or calculator ready 45 Draw boxes to receive values for P.155 is the absolute rate in the case of 15. the friendly bank manager works out your monthly repayment. M $\ ^ smaller box for whoLe\ number r Ask the client to state the three values: Principal (P).R ) N 12 ( ( 1 + R ) N . R. Also a box for the absolute rate. M. Rate percent (Rpct). N ]) fk ^ Confirm to the client the values in boxes P.000 at 15. Rpct. N respectively (£ don't change anything in boxes P. ILLUSTRATING C . R. Rpct. Simply follow instructions 1 to 8 in sequence. R. any rate of interest. For Rpct use the value to be found in box Rpct (J don't rub out the content of box Rpct ]) Write in box M the result of the compound interest formula.5% compound interest over 5 years.THE COHCEPT OF A STORED PROGRAM l\f you ask to borrow £5. N the values to be found in boxes P. N. and a box for the repayment. Use for the terms P. from the compound interest formula: M 'here: P R N = P * R ~ ( i 4. Number of years (N) Write these values in their respective boxes Write in box R the result of Rpct/l00.

but first you must translate it into a language the computer can understand. printf ("\nPayments will total i%1. TJfhe C program is thoroughly dissected in following pages. M.2f over %i years". R = Rpct M = P * R * pow (1 + R. main program ends i j h e above is a program.1 ) ) . This particular program comprises: • • a set of directives to a preprocessor^ each directive begins # a function called main() with one parameter named void. <s>%ll. &N ) . Rpct. is indicated by numbers 1 to 8. int N. No. •include <stdio. &P. Rate%.h> int main (void) main program starts f float P. P. M.2f %% costs i%l. scanf ("%f %f % i " . Here is a translation into the language called C. R. i : INTRODUCTION . 12*M*N ) . 0. and the C program above.4 \ computer can be made to execute such a program. printf ( "\nEnter: Principal. N) . printf ("\ni%l.h> •include <math. TJfhe correspondence between the English program opposite.2f". Rpct. N). N ) / ( 12 * ( pow (l+R. &Rpct. of yrsAn" ) . 4 \ function comprises: • a header conveying the function's name (£ main }) followed by • a block 4 \ block { enclosed in braces } comprises: • a set of declarations (? 'drawing' the little boxes ]) • a set of statements (£telling the processor what to do ]) Ijjach declaration and each statement is terminated with a semicolon.2f.

Rpct. If these are inadequate. Rpct. In this case you do not have to learn much about Unix or DOS. You may be lucky and have an integrated development environment fllDE]) such as that which comes with Turbo C or Microsoft C. Be sensible with spacing.C being an extension of the name proper.M. flo at P. don't type main as MAIN. discover if it is feasible to use your favourite word processor. Store what you type in a file. you have to have some understanding of the operating system^ typical ones being Unix and DOS. To separate tokens. When typing.R.]) ILLUSTRATING C . Unfortunately not all computer installations go about running C programs the same way. /split token^ floatP.MAKING A PROGRAM RUN TJhe program on the previous page should work on any computer that understands C. JType. You control Turbo C with mouse and menus. Rpct. the following essential steps must be taken before you can run the C program on the previous page. corresponding upper and lower case letters are distinct in the C language (£ except in a few special cases]). giving the file a name such as WOTCOST. the . don't split adjacent tokens and don't join adjacent tokens if both are words or letters. it signifies a file containing a C program in character form. tokens joined Apart from that you may cram tokens together or spread them out >s* over several lines if you like: float P. M. ^ float P R Rpct m. M.intK N. Regardless of environment. use any combination of whitespace keys: return _ space ^ ^ r o r e .C (£The . R.C is added automatically in some environments. it really is easy to learn how. R. Type the program at the keyboard using the editing facilities available.

A good IDE displays the statements in which the errors were discovered.^Jp Compile the program <$& which involves translating your C program into a code the computer can understand and obey directly.OBJ ({ compiled from WOTCOST. The compiler reports any errors encountered. tab or new line.00. In a Unix environment.EXE (J linked f r o m WOTCOST. This step may be initiated by selecting Complie from a screen menu. No.OBJ J . The program may still have logical errors but at least it should compile. It all depends on your environment.out. Ijxecution. This 'file' is typically the screen. Payments will total £7546. £5000.out. In other environments you must link the program to functions in the standard libraries (| pow. printf. of yrs.C file and recompile as often as necessary to correct the errors discovered by the compiler. Enter Principal.@15. and locates the cursor at the point where the correction should be made. Ijink. press Return. The resulting file might have the name WOTCOST.37 The program computes and sends results to the standard output file (J named std. Run the executable program by selecting Run from a menu or enterng the appropriate command from the keyboard. Edit the . In many environments a simple C program may be compiled and linked all in one go (J type a. In a DOS environment it might have the name WOTCOST. The screen now displays: Enter three items separated space. scanf are functions written in C too J) . C J . The file of object code has a name related to the name of the original file. End by pressing Return. l : INTRODUCTION .c (J Unix]) and pressing the Return key. if you compiled wotcoshc your object code would be stored in a. or typing a command such as cc wotcost. Rate%.out |).5% cost. > Wun. You have now created a new file containing object code. and away we go! ]) . • Ijdit.

i ~ ^ ~ ^ ^ ~ ^ " ~ — ~ . Rpct. tell the preprocessor the name of its header File.h> ^ S ^ £ ! ^ ' ™ ^ ^ L ^^comment int main (void) <^^jieacieTj^^ float P. Other types are introduced later. 44 ny text between /* and */ is treated as commentary. No.2f%% costs i%l. N) / ( l 2 * ( p o w ( i + R.2f. Such commentary is allowed wherever whitespace is allowed. return 0.^ — ^ — ^ •include <math.2f over %i years". The standard libraries of C contain many useful functions. such as those above. of yrsAn"). M are of type float (J short for floating point number]) and the variable named N is of type int (£ short for integer ]) .2f". These two statements declare that the variables named P. ILLUSTRATING C .5 are of a different type from variables that hold only whole numbers. Precisely one must be named main so the processor knows where to begin.Rpct. scanf ("%f %f % i " . &P.OF A C PROGRAM. <s>%11. P. R. PIECE BY PIECE l#lere is the compound interest program again *=* with a title added for identification. Rpct.1 ) ) . /* WOTCOST. The int and void are explained later. The declarations and statements of the functions follow immediately. jf 'little boxes' depicted earlier are called variables. and is similarly ignored by the processor.h ((mathematical^. M = P * R * p o w ( l + R. There is no semicolon between header and block.M.h>( character on the line]) introduces an instruction to 1 the preprocessor which deals with organizational *-— •. Computes the cost of a loan */ •include <stdio. M.h (^standard input and output]) and math. 12*M*N ) . loan * / f#inciud^<stdioir>l 'l? he • (J which must be the first non-blank [•include <math. R.matters such as including standard files. to make such a function available to your program. Rate%. ariables that hold decimal numbers like 15. ^ C program comprises a set of functions. printf ("\nPayments will total £%1. In this case the header files are stdio. int N. must all precede the first statement. N) . they are enclosed in braces.N). just accept them for now. printf ("\ni%1. &N ) . constituting a block. int main (void) int N. >/* WOTCOST. The header files tell the linker where to find the functions invoked in your program.h> ^ r £ . &Rpct. R = Rpct / 100. printf ("\nEnter: Principal.

\n is called an escape sequence. t's no good pressing the Return key instead of typing \n. reproduced on output page ^ h i s is an -—. \^/hen printing. it has no semicolon after it. In some environments the processor includes standard input and output automatically ^without your having to write #include <stdio.honouring spaces. one per line. comment. \ a for ring the bell (or beep) and others. one to several lines. On meeting a back-slash the processor looks at the next character for guidance: n says start a new line. Statements may be typed several to a line.Ijjach declaration and each statement is terminated by a semicolon. Pressing Return would start a new line on the screen. To the C compiler a space. & N scanf C the Reids ' expected frorn^ the keyboard t TJhere is more about scanf() overleaf. 1— • invocation of printf(). scanf ("%f %f % i f \ & P. the processor watches for back-slash. most examples in this book use scanf(). One whitespace is as good as another. or any number or combination of such things between statements *£* or between the tokens that make up a statement & are simply whitespace. but not when between quotation marks as we see here. There is also \t for Tab.h> ^ Printf C " 'the f\ stands for formatted ') v" ). Tab. a much-used library function for printing. r characters to be sent to the standard output stream \ \. & Rpct. new line. You don't want a new line in the program^ you want your program to generate one when it obeys printf()«l) yfhis is an invocation of the scanf ( ) function for input. significant spaces. Safer methods or input are discussed later. 4f ou have freedom of layout. \ f for form feed. For brevity. A directive is neither a declaration nor a statement. comma List'of addresses variables to which values l : INTRODUCTION . messing up the syntax and layout of your program.

h functions. &Rpct. The second value from the keyboard is similarly stored in Rpct. the processor reads and ignores the excess. of which there are many others in C.' I T/hese statements specify the necessary arithmetic: Rpct/100 means divide the value found in Rpct by 100. The terms l + R and N are arguments $ actual arguments )) for the function pow(). 8 ILLUSTRATING C .. V / h y the V in &P.' or 'pointee of. The / . &N ? Just accept it for now.. In some books on computing the terms argument and parameter are used interchangeably. R=Rpct/l00.. from the keyboard buffer.. \^/hat happens if you type something wrong? Like: where the 15000 is acceptable as 15000.. separated by whitespace. but the second item involves an illegal sign.N)-l)).mean respectively: divide by. one for each of that function's parameters (J dummy parameters D. I f the attempt succeeds. I f you type fewer than three values the processor stays with the instruction until you have pressed Return after entering the third. exp().' 'the value pointed to by. M=P*R*pow(l+R. TJfhe processor now tries to interpret the first item as a floating point number (J % f ] ) . add to.N)/(l2*pow(l+R. The math library ({ #include <rnath. * . Then the processor tries to interpret the third item from the keyboard as a whole number (£ %i}) and stores this in variable N. as you will discover. the processor sends the value to the address of variable P (£ & P}) « » in other words stores the value in P. the third is not a whole number. I f you type more.' or 'pointer to. . They are called operators. TJf he answer is that things go horribly wrong.N) is a Function which returns the value of (l+R) raised to the power N. multiply by. pow(l+R.... In a practical program you would not use scanf(). I f you prefer to use logs you could write exp (log (1 + R) *N) instead. subtract from. lies in the effective use of: & * 'the address of.h> ]) would be needed in either case. The art of C. The processor then tries to copy values.DISSECTIOH OF WOTCOST COHTINUED Tjfo obey the scanf() instruction the processor waits until you have typed something at the keyboard and pressed the return key (£ 'something' means three values in this example ]) . log(X pow() are all math. + .00.

2f as an example.2f. rather than the name of a variable.CM/ f IN. The 8 specifies eight character positions for the complete number. and prints that value in the specified field. f denotes a field suitable for a value of type float >» in other words a number with a fractional part after a decimal point.2f. is return <^|ust accept it for now: the opening int main ( void ) and closing return 0 are described later. You can see this better by rearranging over two lines using whitespace: %.2 specifies a decimal point followed by two decimal places: l%s. lfhis is like the earlier printf ( ) invocation. M. The % denotes a format specification. %.2f: 12 3 4 5 6 7 8 44 single percentage sign introduces a format specification as illustrated. the processor widens the field rightwards until the number just fits. i: INTRODUCTION . converts the resulting value (Jif necessary ]) to a value of type float.2f. %i for which the values stored in variables P.iyears" Rpc?) . This time the value to be printed is given by an expression^ n*l2*M.2f)%% costs i(%.2f over %i years". Rpct. %. The . whenever a number is too wide. > interspersed with Format speciFications For values to\ \be printed " t comma List oF names oF variabLes whose values are) rto be printed in the Format speciFied y u t this time the string contains four Format specifications: %8. a siring between quotes in which \n signifies Start a new Line on the output screen. %8. PJfoc W l ) .^ j%. printf C ^characters to be printed.2f. The processor evaluates the expression. : comma List may contain ^ »» \ ^ expressions as well as printf ( " names oF variabLes printf ("NnPayrnents will total £%. i f h e second (J and subsequent ]) format specification is %.2fJover(%i. N are to be substituted in order. How can the field be zero characters wide if it has a decimal point and two places after? This is a dodge. another printf() invocation with an 'elastic' field.2?\ N * 12 * M >. So how do you tell the processor to print an ordinary percentage sign? The answer is to write %% as demonstrated in the printfO statement above.

I f all else fails.ijrnplement the loans program. This is an exercise in using the tools of your particular C environment. It can take a surprisingly long time to master a new editor and get to grips with the commands of an unfamiliar interface. ILLUSTRATING C . try reading the manual.

functions. TJhis chapter introduces decisions. and you can't define B without assuming something about A. arrays. characters. informally. Complete programs are included to illustrate the aspects introduced . scope of variables. and recursion.\Jne of the few troubles with C is that you can't formally define concept A without assuming something about concept B. loops. TJfhe aim of this chapter is to introduce. enough simple concepts and vocabulary to make subsequent chapters comprehensible. Books on C have a bit in common with the novel Catch 22.

if the value in Profit is not greater than that in Loss the expression is False and takes the value 0.5 > 0. otherwise another.0 takes the value 1 (j true j). true if ( Profit :> Loss ) printf "Hooray!" ) .LOGICAL VALUES IN C THERE ARE NO BOOLEAN VARIABLES i j f . 'ij'hus 9. Profit is greater than Loss (} Profit and Loss being names of variables holding values ]) you may want the program to do one thing. in braces.5 < 0. 9. The expression Profit > Loss is true if the value in Profit is greater than that in Loss. TXhere are no Boolean variables in C <& you have to make do with integers. of declarations (j optional J) followed by statements.0 takes the value 0 (jf False ^>. Statements concerned with the flow of control (J if. a value of zero represents False. do for j ) are based on values of logical expressions: non-zero for true% -zero Tor False. any non-zero vaLue represents true. A few other logical operators are shown here: ££> Operators are defined in Chapter 3 and briefly summarized on page 196. else printf "Bother!" ) . A SELECTION STATEMENT Tjphe if statement may be used to select a course of action according to the logical value ( true or false ) of a parenthesized expression: if ( expression ) statement else statement _ reducing to a value of 'non-zero (true) or zero (false) if ( Profit > Loss ) printf ( "Hooray!" ) . Some of the statements may be if statements /& a nested pattern. Anywhere a statement is allowed a block is also allowed A block comprises an indefinitely long sequence. in your program. c c I Hooray! I i false Bother! Tjhe statement is typically a compound statement or block. true is represented by L Conversely. while. 12 ILLUSTRATING C .

block) p r i n t p ("\ni%. R. Rate%.N). Gallop ( 0 ) .1 ) ) . j confusing) .P.h> #include <math. if ( Lame ) Walk ( 0 )./ else else ).^ . i j n the illustration below. 12*M*N ) . 2 : CONCEPTS 13 . but remember that the processor pays no attention to indentation.^ ^ i f ( . Conversely. Careful indentation shows which 'else' belongs to which 'if. if ( ( P>0 ) && ( Rpct > 0 ) && ( N > 0 ) ) R = Rpct / 100. ( OK ) else r if ( SoSo ) ^ Trot ( 0 ) . &Rpct.2f%% costs i%. of y r s A n " ) .h> int main (void) < T ^ 6 the initiaL >int ' means the Pro9ram returns an { ^ ^ * integer to its environment as a signat of success 4 \ ° r faUure. The program does the same job as the introductory example but first checks that all items of data are positive. c0 .M. Rpct.l y e careful when nesting 'if' statements. int N. Try to employ ^ the pattern resulting from 'else i f rather than 'if i f which leaves 'elses dangling in the brain. / * WOTCOST with data check * / #include <stdio. <a%. &P. (jomplicated logic based on 'if else' can be clumsy. else if ( Quiet ) . if Lame holds a non-zero value (J true )) then the expression !Lame takes the value 0 (Jfalse^).Rpct. Ijjere is a program that uses a block in the ' i f statement as discussed opposite. paying due resped to parentheses. the operator ! means not. A sequence of 'if i f makes it difficult to match the associated 'elses' that pile up at the end.^ . N) / ( I 2 * ( p o w ( l + R. return 0 . M . else Walk ( 0 ). we meet more elegant methods of control later. ^^SS2£^ M = P * R * p o w ( i + R. Canter ( 0 ). &N ) . 2 f.2f". printf ("\nEnter: Principal. Ijjach 'else' refers to the closest preceding ' i f that does not already have an 'else'. Careless indentation can present a misleading picture.2f over %i years". Thus if variable Lame holds the value 0 \ false j) then the expression JLarne takes the value 1 (J true )).'Quiet ) f ). ^ printf ("\nPayments will total %1. (beLow) indicates successJ float P. r e t u r n 0 . N) . No. Canter ( 0 else Gallop if ( !Lame ) if ( !SoSo ) ^ . Trot ( 0 ). scanf ("%f %f % i " . else printf ( "Non-positive Data" ) .

can specify an infinite loop by omitting the second expression (jf implying 1 = true j) and get out of the loop with break. expression . Then j is incremented by 1 ({ ++j is short for j=j+l J) to become 1. /* Count characters until new line */ #include <stdio. count ) . Ijp this loop. j has a test for continuation d[ j<3 ]) and stands at zero. statement \fou. This one is a 'counted' loop. before any others statement ^body ' of ^ (typically an \ Loop. different kinds of loop. *\ [Evaluated after \ [typically a. you specify in advance how many times to go round. for ( expression . l^ater we meet 'tested' loop structures. • do statement while ( expression ) ILLUSTRATING C . if ( Ch==\n' ) break. for ( j . wishing you a merry Christmas. so round we go. The test (J j<3 D is again satisfied. at which stage the test is no longer satisfied.IHTRODUCIHG THE for LOOP THE MOST VERSATILE OF LOOP STRUCTURES 4i|l real programs have Loops. return 0. so round we go for another merry Christmas. printf ("\nAnd a happy New Year!' ) . ) char Ch. we drop out of the loop with New Year greetings. the while loop and d o loop: while ( expression ) statement printf ("\nEntry has % lectors". else ++count. Tjhere are. j ) printf ("\nWe wish you a merry Christmas"). r f j .h> int main ( void ) int count = 0. /* Humbug */ #include <stdio. That is a bop. each execution of] J compound d the body -.h> int main ( void ) { int j . This process continues until j reaches 3.. / increment. When a program has finished computing one person's salary it works through the same set of instructions to compute the next person's salary. we don't offer any more merry Christmases. C Ch = getc ( stdin ) . for C . however. and so on through the payroll. expression ) keyword) evaluated once only. Zero satisfies the test. .

stdout).INTRODUCING CHARACTER CONSTANTS "STRINGS" COME LATER gfrevious examples illustrated type int (J integer ]) and float (J floatingpoint number^ one that has a decimal point Jjl. and for output of a single character to the screen use putc(Ch. digit or symbol. 9 T 1 'i' I' i I I ' + 1 gives + 1 gives + ( A . j = l.A 'r j ' J' ) gives I etc. stdout ) . putc ( Ch. char Ch. The parameters stdin and stdout indicate standard input and output streams defined by the system as depicted below. ) keyboard buffer gets stored nominated character variable putc (Ch.h > int main ( void ) char Ch. the following relationships ( not defined in ANSI C ) also hold: I.a + ( a .V .h. Another type is char. int i. . /* Echo input in CAPITALS (ASCII only) */ Ch = getc (stdin) #include < stdio. 2: CONCEPTS 15 . For input of a single character from the keyboard use getc(stdin). A character is a letter. return 0. Both functions are defined in stdio. ^character both alphabets (Lower & upper casejj are stored in ascending order V 3 ( character J '2 —^-~—^-x digits are stored in ascending order digits are stored contiguously etc. for ( . 3 l 1 ^—v^- k i 1 'A'l v^ "\x-—v^" "V N^ i \+fhat can we assume about the relationship of characters? Some aspects depend on the character set employed. stdout) (the character sto> in variable Ch is on the screen*/ = getc ( stdin ) . if ( Ch == \ n ' ) break. 1 ASCII alphabets (not EBCDIC)\ are stored contiguously * these relationships hold for EBCDIC Letters also I j h e previous examples featured scanf() and printf() for formatted items. In ANSI C: s^f 1 a 'A ' '0 ' < < < V 'B' < < < 'c' 'C' '2' J etc. k = 'A'. etc. if (( Ch >= V ) && ( Ch <= 'z' Ch = Ch . ) gives I ^^:. etc. short for character.' a ' + 'A1. dig . l\f you work exclusively in the ASCII character set.

1. 6}. { l . 0. 0. f l .5. 4.5. '. 2 } . 34 } . 1. f l . You may also declare arrays of such boxes (J arrays of elements j). 3}. 1. int M[0] M[l] M[2] M[4] V izer J float Wow [ 3 ] = {36. { l . 1 1 1 1 [l] 1 2 3 4 5 [2] 0 1 3 6 10 ^ \ u l t i dimensional arrays may be initialized using nested braces: int C o e f f s [ 5 ] [ 3 ] = { { l . you may ignore the inner braces: int Coeffs [ ] f 3 ] = { 1. 5. 18. 2. float and char. 4. 6. and include all of them. ! char Letter [ 14]. l\f the size is declared you may supply fewer initializing values. int M [ 6 ] . 5 not necessaryju is necessary ) *f 0 is necessary 16 ILLUSTRATING C . char M[5f 4\n array may be initialized as shown for Wow[ ] above. the processor pads out with zeros. If you initialize all the elements you may leave the brackets empty and let the processor do the counting: V implied by the initializer Letter! 0] Letter! l] Letter! 2] Letter! 3] Letter! 4] Letter! 5] Letter! 6] Letter! 7] Letter! 8] Letter! 9] Letter[l0] Letterfll] Letter[l2] Letter[l3] float Wow [] = { 36. float M [ 5 ] = { 1. 2. 0. 1. 2. \ 3. 18. 10 } . 1. l } . 1. int [0] int Coef f s [ 5 ] [ 3 ] 7 Coeffs [ ] P1 i [ [2] [3] TJfhe array is stored by rows. 0. \ implies { 1.AN 'OBJECT' COMPRISING 'ELEMENTS' TJne little boxes illustrated earlier are individual boxes for values of type int. l } . Here is a two-dimensional QrrQ y . In any one array all elements are of the same type. 0 } may have any number of dimensions. 5. 3. \ missing items imply zero _ you arrange values by rows. 34 }.

40 1.50 30.50 + 10 * 2.00 100 0. ++n ) scanf ( "%f %f %f %f".50 \nd the commissions earned thus: [0] 5*0. ++n ) scanf C "%F %f".50 + 5 * 2.50 2..00 number of rows of B the number of columns of A must be the same as and the result has as many rows as A & as many columns as B ^ _ r e is a program to input data for matrices A and B.20 + 5 * 0.10 [2] 20*0.80 + 2 * 0.20 + 0 * 0.00 = 38.00 [1] 2 5 AM A[ l] A[2] 5 3 20 [2] [3] 0 10 2 5 0 0 0 [0] 1.00 2.50 [2] 20 * 1. matrix C.50 + 5 * 2. for ( n=0.-y ^ C [ j ] [ i ] = 0.00 + 0 * 0.00 0. j .h> float A [3] [ 4 ] . j<3.00 + 10 *0.50 = 7.20 + 2 * 0.20 0.40 + 0 * 1.10 38. There are three sales people selling four products. ++j ) — .50 + 0 * 2. then display their product. &B[n][0].00 10 5 0 v for C j=0.00 33.40 + 2 * 1. C[n][0].10 4.00 2 5 0 0. (enter'B by rows for ( k=0. .00 2. Quantities sold are tabulated in Table A: A PRODUCT \0] [1] [2l [31 [01 5 2 0 10 11 1 3 5 2 5 [2] 20 0 0 0 B PRODUCT 01 1] 2] r 3] r MONEY [1] _ [0] 1.20 2.50 0. n<4. 33.00 = 30. / * MATMUL Matrix multiplication * / #include <stdio. n<3. &A[n][0]. &A[n][3] 3 20 1. multiply them together.80 + 0 * 0. C[3][2] int n.50 6.40 + 0 * 1. ++k ) J J } for ( n=0.80 [l ] 3*0. B[4][2].50 * 4.00 r[0] j his computation is called matrix multiplication and looks best as set out below. k<4.40 liable B shows the price of each product and the commission earned by selling each item.80 5.2f return 0 . n<3. money brought in is calculated thus: [0] 5 * 150 + 2 * 2. i.50 = 6.2f " .50 30. i<2.80 5.50 2.10 38. ++n ) %. k.NESTED LOOPS £|on-mathematicians don'\ go away! This is business. N &A[n][2]. int main ( v o i d ) for ( n=0. C[n][l ] ) printf ("\n%. ++i ) c / .00 5.00 + 5 *0.80 0. ( ^ / 7 ^ r > bu rows 4 orogram displays £ by ^* 2: CONCEPTS 17 . &B[n][l] r^T^l^L for ( i=0. .80 + 0 * 0.00 = 33.50 + 0 * 2.10 [l ] 3 * 1.00 2.80 7.

he published an anagram of 'ut tensio sic vis'. k.l ] . j . 18 ILLUSTRATING C .'o'. ++i) putchar ( Letter [ j ] ). V.ILLUSTRATING NESTED LOOPS AND ARRAYS OF CHARACTERS £ \ school we hung little weights on the end of a spiral spring and measured its extension. made by arranging the letters of that sentence in alphabetical oraer. Run the program to see the anagram he published. R o b e r t Hooke (f 1635 . ^nrence in aipnaoencai order. printf ("NnHooke's anagram is " ) . /S^pH^ mt j .'i'. thus the force )) . for (j = 0. In other words we showed that extension is proportional to the force applied. for ( j = 0 for . ' i ' . . I f the spring extended 12mm on adding a one-gram weight we found it extended a further 12mm on adding the next gram. V .. swop adjacent Letters ^ h i s program illustrates the technique called 'bubble sort1 which is suitable for sorting small lists.1703 D discovered this law and expressed it in Latin as 'ut tensio sic vis' (f as the extension.h> int main (void) x the number of Letters char Letter [14] = f u V ^ V ^ ' .. i . Letter [k] = Tempry. For longer lists there are better methods such as Quicksort & which is explained on Page 62. /* Anagram of Hooke's Law */ •include <stdio. return 0. j<14.'i'. ' s ' } .j /#lere is a program to compile Hooke's anagram. 's'.V. ) if ( Letter [k-l]> Letter [k]) Tempry = Letter [ k . Tempry. Letter I k-l] = Letter [ k ] . To establish ownership before disclosing the secret. Then he tried to patent his discovery.

But this time there is less to do because k does not have to rise so high. Notice that the first two letters to be compared (f n below.n . In the second cycle of j the second lightest letter rises to the second position in the list.0 1 2 3 e . I f these two letters are out or order they are exchanged. 0 e" n m.2f t t (el nfrisen t K^ n t k-^2< 3 4 j s 3 e ' 1 n O K u 3 t t k .^ 3^ k-^4 t . k is decremented by 1 so that it indicates the next letter up. ^ ^ ^ ^—v TJhe outer loop is controlled by j which starts at 0 as depicted in the first row of the table below. j is incremented so that it indicates the second letter in the list. ft * ^ e u *e " n t j—*-l u 2 * 3^ n^ k—*-4 t t %n. That completes the first cycle of j . Then the whole procedure. I f the two are out of order they are exchanged. And so on until k has risen to a position just below j . k is set to the bottom of the list. 4f\gain k is decremented so as to indicate the next letter up.n J t t OK e n 1 . t above ]) they are out of order and therefore exchanged. k-P-2( 3 4 e t 3-^4>'t "unj e ^eVfu 2 3 4 k-*-4 3 = * k-*-4< 3 =2 1 2 t 3. k = 2 U k = 1 j-3^0 ' u 3 . u \ Ho. In this case (J e below. described above. otherwise left alone. ^ t . The lightest letter has now risen to the top. That letter is compared with the letter immediately above it (f Letter [k-l] > Letter [k] ]) . k is set pointing to the bottom letter. ( react by row J ( 2 : CONCEPTS 19 . e above J are in the correct order. e k —>~3^ e* t 4 . To keep the illustration simple we shorten the quotation for uttensiosicvis to utten. Again this letter is compared with the letter above it and an exchange made if the two are out of order. Qtill with j set to zero. lyack to the outer loop. 4\nd so on until the list has been sorted k = 4 k = 3 3-+<t> u " 1 t 2. This letter is compared with the letter immediately above it as before. t 4 0 'e 1 n 2 t (risen to) 3-^ 3J ^U"*s t 7 HoA S k-^4< u \ e n u-\ ^ (risen to\ t^ u 7 A b .l^ere is how the bubble sort works. is started again.

n— ) ^(declarations v = v * x. printf ("\nEnter: P.5 5 (program TJhe home-made function is dissected below: I Costs £125. but instead of using pow( ) from the math library we supply and invoke our own function. / * WOTCOST with home-made Powr() * / #include <stdio.77 per month ) . scanf ("%f %f % i " .2f per month". Powr () main () much as before invoke Powr ( J twice Enter P. Ij4ere is the first example again. int n ) float v .0. the second parameter was constrained to whole numbers by being declared of type int. Powr() block of code for home-made function. would be expressed pow (2. &N ) . } ( program \ i Include math. Powr( ).MORE CONCEPTS ^ IN PARTICULAR THAT OF 'CALL BY VALUE' Tj*he introductory example used a function from the math library called pow() (j short for power)). int main ( v o i d ) float P. 3. write void. M . pow ( (expression: its value ) expression: its ting the value toRvalue being the b raised j~*[ power by which^ to raise yjxample: 2. return ( Y ) .0 ' would be 8. Rate%. R = Rpct/100. float Powr( 20 ILLUSTRATING C . M ) . &RpCt. both of 'floating' type.h header of home-made function. N)/(i2*(Powr(i+R. / l / h e header gives the name of the function ^ being defined and the type of value the function will return. R. in general. In the introductory example. the value returned TJfhe parameters of the library function pow() are. however. Nyrs 5000 15. return 0.0. Rpct. M = P*R*Powr(i+R. n>0.0). printf ( Costs i%1. f o r ( v=1. &p. Nyrs\n" ) . Rate%. int N. I f the function returns no value at all.h> float Powr ( float x. This constraint is essential to what follows.0.

1 and n initialized to 3. In general. N) ^ you substitute appropriate expressions for the dummy parameters x and n. The names of parameters in the header are names of dummy parameters ^ * private to the block that follows the header.= l or —n as previously shown. it works out the value of 1 + R J this might be 1. rloa v . v begins at 1. n>0.flogt Powr ( f\oa\ x.* without confusion with the N declared in main. \ yriis is an instruction (j[ return is a keyword ]) to stop executing statements of the function and offer the value in variable v as the value to be returned by this function. Outside the function any reference to v would be treated as an error. But when the program obeys a statement that invokes the function. n=n-l may be abbreviated to n .0. The accumulating value in v is multiplied by the value found in x (f computed from 1+R in this example ]) on every circuit of the loop. FUHDAMEHTAL TO C-LAHGUAGE \fhen you write a statement that invokes the function (f in this case the relevant part of that statement is Powr(1+R. \ f / h e n the processor comes to obey the statement in which you invoke the function. evaporates. This statement may be abbreviated to v *= x as we shall see. N) the function is incapable of changing the content of variables N or R. Although you invoke the function with Powr (1+R. \ TJhis is the body of the loop. n«n-l ) j \ ^ & r i a b l e v is initialized to 1. for example J). 4 \ function can change the contents of global variables. In this example. f o r ( v=U3. The program then starts obeying the statement {in the function block} with x initialized to 1. The 'return 0 ' at the end of a main() program returns 0 to its environment if execution has been successful. as demonstrated on the next page. I f Powr() were invoked with a value of 3 for n. v = v * x . This concept is known as call by value. int n ) I y*he header also shows how many parameters there are. When the program has finished with the function ({ having returned a value to the invoking statement ]) the variable v. no function in C can change the content of a variable offered as an argument. a local variable. return (v). 2: CONCEPTS 21 . It does not matter if these names coincide with names in main (f or in any other function that might invoke Powr j). n could just as well be N ^ . for example j) and the value of N Q( this might be 3. the body of the loop would be executed 3 times.0 before the loop is executed for the first time. a new variable v is created. | \ ^ r j a b | e v iS private to the function. Here we substitute 1+R for x and substitute N for n. A function can also change values to which pointers point. but this topic is left until later.1. and the type of each. together with its content.

f Formula() nOj ^\need for { ^^^^^\invoke$ Powr() float v .this v is local to Formula( )> v = Powr ( l + R. so we must ask if its absolute value (J value ignoring sign ]) is greater than 0. hence float Formula (void) preferring to parameters.h> float P. \_ computes formula at top of pagef float Absolute ( float P) if ( P >= 0.P .005 (J say )). accept R if Mt is too small it means R was guessed too low. Guess R. But here is a more difficult problem. n>0. global Pf R N. what rate of interest is being charged? N PR(l + R) M = where R« i f h e equation shown above may be solved for R by trial and error. M.l ) ) . given the size of the loan. so multiply the rate by M/Mt to make it smaller and try again. 0 1 . N ) .0. yfjere are some global declarations and three functions: / * WOTRATE: computes rate of loan interest * / •include <stdio. so multiply the rate by M/Mt to make it bigger and try again if Mt is too big it means R was guessed too high. } \ local P 'hides' global f) I more concisely float Absolute ( float P) {return ( P<0. for (v=1.0)?-P: P. else return . The difference may be positive or negative. then: • • • if Mt is the same (f very nearly J as M the guess was correct. < ^ 3 ^ globaUy float Powr (float x. return ( v ) . .. Tjfhis algorithm causes the ratio M/Mt to get closer and closer to l . n=n-l v = v * x. the rate of interest and the term.} ' 22 ILLUSTRATING C .0 ) return P. Make the program continue as long as the difference between M/Mt and 1 is more than 0. no connection with v in Powr( J) return ( P * R * v ) / ( l 2 * ( v .INTRODUCING GLOBAL & LOCAL VARIABLES Tjfhe program in the first example computed the monthly repayment for a loan. int N.005. int n ) float v . . R = 0 . substitute in the formula to compute Mt. a loan of P is to be repayed at M per month over N years.

It then exists only until control reaches return ( v ) . Implications of global declarations are: • • • the processor reserves space for the variables declared. &P.m. and variable v in FormulaO. while ( Absolute ( M /Mt . R. variable v could find itself somewhere else in memory. & > &N )..").m. float Mt.000001). Their contents do not evaporate during the run variables may be referred to by statements in functions provided that: ( i ) any reference Follows a declaration in the same file (f or follows an extern declaration if in a different file <£* see later J (ii)the name referred to is not hidden by a local variable (flike variable P in function Absolute() opposite]). together with its contents. Repayment p. M. 2: CONCEPTS 23 .yrs. printf ("\nRate charged is %5. Declarations that reserve space are called definitions global variables retain the space reserved for them throughout the run. Principal. 3750 Rate Repayment 2 is 16.yrs. No. printf ("\nPrincipal. it is not defined until Powr() is invoked. Puff! Next time Powr() is invoked. Such variables are called automatic to distinguish them from the static variables which retain identity throughout the run. M ^^y do isee flow chart on Page 52 { Mt = Formulae).36 charged A FEW FUNDAMENTALS Xy'ariables P. No. and variable v evaporates. 195.1 ) > 0. At this instant control leaves Powr().2f%\n return 0 .l/inally FuncHon main(): int main (void) >Mt is local to main (). N are declared at File Level or globally which means outside every function.69% p. \ f ariable v in Powr(). have only a transient existence. scanf ("%f %f % i " . Although v is declared in Powr() on the first line after the header. R = R*M/Mt.

It is as though C provided a Fresh copy oF the code oF Function HCF() on each invocation. Remainder becomes 21. But with HCF (1470. In so doing. Find the remainder when 1470 is divided by 693. int m ) this works both when n > m and when m > n f f - signifies TO HOT EQUAL int Remainder.693). Remainder = 693%84 = 21 long HCF(84.21) because Remainder would become zero. In other words 21 is the biggest number that will divide into 1470 and 693 without leaving a remainder in either case. making the Function return 21. The highest common Factor \ also called the greatest common divisor 2) is the product oF these: in this case 3 x 7 = 21. Nice! Jere is a C Function based on Euclid's method: int HCF ( int n. long HCF(l470.84). Remainder = 1470%693 = 84 return WHCF(l470. repeat the process. Remainder = 84%21 = 0 return if he ability oF a Function to invoke a Fresh copy oF itselF is called recursion. To veriFy this.21).2l). substituting the second number For the First and the remainder For the second: 693 % 84 C = v > . so the Function invokes itself as HCF (693.693)) Jong HCF(693. so the hcF is 21. thereFore the Function invokes itselF as HCF (84. else int HCF( int n. m ) return m . 24 ILLUSTRATING C . { return n%m ? HCF ( m. n%m ) : m } l\\ is easy to see what would happen with HCF (84.21 This remainder is still not zero so repeat the process: 84 % 21 c = = ^ 0 This remainder is zero.DEFIHITIOH OF A FUNCTION TO INTRODUCE AN IMPORTANT PROGRAMMING CONCEPT TJfhe highest common Factor (£ hcF ]) oF 1470 and 693 is 21.693) Remainder becomes 84. Remainder ).84). Factorize both numbers to prime Factors: 1470 693 and pair oFF any common Factors » in this case 3 and 7. invokes itseLf iF ( Remainder != 0 ) return HCF ( m. d The % operator gives this remainder !): 1470 % 693 £==£>* 84 Because this remainder is not zero. Euclid's method oF Finding the hcF is more elegant. function HCF Remainder = n % m.

k ) . Mathematicians indicate a factorial by a post-fixed exclamation mark: 5! = 120 It is obvious that the factorial of 5 is 5 times the factorial of 4: 5! = 5 x 4! So what is the factorial of n? Clearly: n! = n x ( n . otherwise factorial n is n times factorial (n-l) •include <stdio. else return n * Factorial ( n-l).h> long int Factorial (long int n ) if (n==l) return 1. return 0 .IJf you find the function opposite confusing. &m ) .l )! If n is 1 then factorial n is 1. printf ("\nlnteger please\n"). which is 4* so return factorial (2) which is 3*(T so return compute— 2 *(£actorial ( i which is 50 return 2: CONCEPTS 25 . But that's too hasty. try out the function by appending a simple main() function: int main ( v o i d ) long int m. here is a simpler example. printf("%li". n is 1. scanf ( " % l i " . k = Factorial ( m ) . the hackneyed factorial: TJhe factorial of 5 is 5 x 4 x 3 x 2 x 1 « 120. What if n is 1? l this to the computer by encoding: 'if n is 1 then factorial. i T rn L rn 9^ 1 so 4 *(£Worial (3). k.

l\

p r o g r a m MATMUL multiplies matrices of fixed size (j 3 rows, 4 columns; 4 rows, 2 columns J). Make the program deal with any specified sizes up to an arbitrary {00 by 100. Read three sizes: the number of rows of A, the number of columns of A (} implying also the number of rows of B ]), the number of columns of B. Read A and B by rows, then print C by rows. For this exercise you have to change each simple reading loop to a nested pair of loops. Similarly the printing loop.

Zjjjter the Hooke's Law program to read and sort a list of numbers | type double J) into numerical order, then display the sorted list. Make the program request the length of list, then ask for the numbers one by one.

[for the math library functions sin(x) and cos(x), the value of x must be expressed in radians. Write functions Sine (a) and Cosine (a) for which the argument, a, must be expressed in degrees of arc. All types are double.

\ffr\\e function Reverse (A, N) to display an array of integers in reverse order. An obvious way to do this is print A[ —N] in a loop until N stores zero. Instead of using a loop, write the function so that it employs recursion.

26

ILLUSTRATING C

Tjfhis chapter defines most of the basic components of C. Their syntax is defined using a pictorial notation. Characters, names and constants (£ the simple building blocks}) are defined first. Important principles of the language are next explained; these include the concept of scalar types', the precedence and associativity of 'operators', the concepts of 'coercion' and 'promotion' in expressions of mixed type. i j h e operators are summarized on a single page for ease or reference. TJhe syntax of expressions and statements is defined in this chapter. Declarations are discussed, but their syntax is not defined because it involves the concept of pointers and dynamic storage. These topics are left to later chapters.

TO DESCRIBE THE WRITTEN FORM (SYNTAX) OF THE BUILDING BLOCKS OF C

I
t

a precise definition of the syntax of ANSI C, see the definitions in NSI X 3.159. These are expressed in BNF (f Backus Naur Form ]).

J appreciate the syntactical form of an entity the practical programmer needs something different; BNF is not a self evident notation. Some books employ railway track diagrams, potentially easier to comprehend than BNF, but the tracks grow too complicated for defining structures in C. So I have devised a pictorial notation from which a programmer should be able to appreciate syntactical forms at a glance. The notation is fairly rigorous but needs a little help from notes here and there. italics integer Italic letters are used to name the entities being defined: digit, token, integer and so on The broad arrow says that the nominated entity 'is defined to be ...' (J in this example 'An integer is defined to be ...' ]) These stand for themselves. Copy them from the diagram just as they are. Do not change case; R and r are not the same letter

Romans, & + ( * / 012 etc.

Vertical bars contain two or wore rows and offer the choice of one row. Vertical bars may be nested

Forward arrow says the item or items beneath may be skipped over; in other words they are optional. In some cases a word is written over the arrow: this defines the implication of skipping the item under the arrow Backward arrow says you may return to go through this part of the diagram again fl typically choosing another item from vertical bars j) This also says you may return, but must insert a comma before the next item; it defines a 'comma list comma list' Notes may be explanatory or definitive. A typical definitive defi note points to expression and says 'must be integral

This symbol is put in front of illustrations; it says 'for example' or 'e.g. '

28

ILLUSTRATING C

Letter digit symbol escape

TXhe diagram says: 'A character is defined as a Letter or digit or symbol or escape'

letter
symbol

\Jpper and lower case letters are distinct in C. Z is not the same letter as z. l^igits 0 to 9 are decimal digits. Octal and hex digits are defined on Page 197.

digit

44 few characters, such as $, £, < > are available s, in most implementations of C. They may be used as character constants and in strings but are not defined by ANSI C. £ ^ o every installation can manage the full range of symbols. The Standard gets round this problem by defining a range of trigraphs. I f you type ??<, for example, the implementation should substitute the code for a left brace. And similarly for the other trigraphs. Substitution is carried out before any other operation on the text. l\n Chapter 1 you saw the escape sequence \ n which is effectively a single character, although compounded of two. It represents the new line character. It is no good pressing Return to get a new line character because that would mess up the layout of the program. You don't a new line in your program \ you want the computer to make a new line when printing results. \ n does the trick. 4p\n escape sequence* is needed whenever the character to be conveyed would upset something, or has no corresponding key on the keyboard « - like 'ring the bell'.

A a B b C c D d E e F f G 9 H h I i J

K k

4 \ n example of 'upsetting something' is a double quote in printf (" "); which would close the quotation prematurely. You can include a double quote in a quotation as the single escape sequence \ " as follows: p r i n t f ( " \ " 0 o h ! \ " I exclaimed.");

L I M m N n 0 o P P Q R r S s T

t
U

u
V v W w X
X

Y y 2 z

3: COMPONENTS

29

If an object that is local to a function has the same name as a global object. structures. float Smith \ Up general. Name space is explained in Chapter 5. they occupy a different name space. enumerations j) have unique names in the same piece of program. DATE . names of tags and Labels^ for example.e.g. Lenth_Of_Wall. i. variables. Names are used to identify other things in C apart f r o m objects such as variables.g. Examples are: LengthOfWall. name Letter Letter digit ^ " ^he diagram shows that a name starts with a letter or underscore. underscores. Length capitalized phrases e. do not clash. unions. NewLength.TJ*he example programs in the first chapter illustrate several names invented by the programmer to identify variables.g. The names used are: keyword auto break case char const continue • • • single letters e. TJfhe names chosen f o r use in the programs o f this book are safe f r o m clashing with keywords or with names o f standard library functions. so Auto and Break are not keywords and may be use as names of variables. N capitalized words e. that the first character may be followed by other letters. functions and objects (J i. the global object becomes hidden from view. There a r e thirty-two keywords in ANSI C as listed here. arrays. int Smith [6 ] . Such names are also called identifiers. digits. Remember that upper and lower case letters a r e distinct. Old_Height default do double else enum extern float X/OKX may not give the same name to an array and to a variable in the same piece of program. i / h e name y o u invent should not clash with a keyword. £ l o t all names behave in this way. for goto if int long register return short signed sizeof static struct switch typedef union unsigned void volatile while ILLUSTRATING C .

signed int long.. the syntax of C allows permutations. initializers are far-reaching and complicated. All are explained in subsequent pages. Tjhe syntax for scalar type is defined as follows: signed unsigned short long char int >\J2oUnngJ implies int • long int • signed char y float • long double • void float long void double Tjfhe diagram is simplified for clarity. declarators. 3 : COMPONENTS 31 . consider a declaration of a simple scalar (f single valued ]) variable. For the moment. j . long signed int. 2.WE MEET AGGREGATES AMD COMPLEX TYPES LATER typical declaration at the beginning of a program is: int main ( void ) { static optional specifier float a[] = { 1.. with optional initializers TJfhe implications of specifiers.5. For example. etc.5 } . the following are all allowed and equivalent: signed long int. 2/ou can define an alias ( synonym ) for a phrase using the typedef facility: yx^i alias typedef typedef Lanky type name long signed int i.

.295 | l | long tg 31 I I I f-( I -2.483.483. subject to certain minimal requirements if the implementation is to comply with ANSI C.7x10 —>.648 -*.768 -*-32.4x10'38 ^ .4x10 ->• +3.65.4x10 "" -^.647 xexponentf gniFicand) Z3T ^ ^ ^ ^ T* .-3.147.4x10 r^XS^~-s > biggest \ \negativej -*.768 . The following implementation is typical.2.0 ->.• 32..967.4.7x10 ->• 0 ->• +1.J 0 4-932 -3.7x10 long double About 19 decimal-digit precision 6Z mwawwxmx 19 i —4932 i i i ""4-932 i i 4-932 i .4x10 ^^-^5|^-w ^>^^^N /^V^^^ / [preciselyJ (smallest) (biggest \ X^zero^J (positive J (positive 32 ILLUSTRATING C .. ^ O.0 -> +3.4x10°" -*.767 ( . 1 63 About 15 decimal-digit precision 1 -308 1 I -308 1 1 308 ~1 0 -1.7x10 51 308 —>.K.147. .+1.^ (2 1 5 -l) unsigned long l \ 0 -*. aecimai-aigit predSiOn l / j ^ ^ ^ ^ ^ J 1 -) -3. unsigned char char m ^ .294.4xl038 double WVZV////Y/W/A .+3..-1.+3. for ASCII character set -128 ->-127 (k^)-^(2j-l)y unsigned int Short int U 15 i 15 | 0 | 1 0 0 -*.767 f 0 .4x10 s-vTiK-v >smattest\ > negative] ->.^ ( 21G-1) | in * 1. .( 2 1 5 ) .K.-3.535 -32.! | | -32. for full PC character set I ^^-^-^-^^^ O.(*T\ X ^ J " } r^y^r^Tft^ A TYPICAL IMPLEMENTATION Tjfhe number and arrangement of binary digits (j[ bits J) representing each scalar typ>e depends on the implementation.

4E-6 0L 1. D. etc. The program on Hooke's anagram illustrates character constants. V . 3. constant. char-const integer digit digit • 0 • 27 • 033 • 0XlB • 0L • 27UL zero 27 decimaL octal for 27 decimal hex for 27 decimaL zero as a long 27 as unsigned Long octal digits: 0. 6. 6. A. see previous constant integer number char-const name page for: named constants & enumerations long unsigned float long double integer.DEFIHITIOHS OF 'LITERAL ' CONSTANTS ^fhe introductory program has the line R = Rpct / 100. i. 1.5F Letter digit symbol escape • 6 « > 7 ^ backslash j « ' / 7 ^ apostrophe "STRINGS" ARE DEFINED IN CHAPTER 6 3 : COMPONENTS 33 . 9. 3. C. E. number. 8. 2. 2. 5.001 23. 5. F Lower synonymous case Letters are as digits Asa etc. B. 7 hex digits: 0. 7. > • >r~^s—^~^—^—v • 0 23456 00. 4. Hamed constants are introduced over the page. The 100 is a Literal. V . These are also Literal constants. 4.

"*^Cra ^^\^i Ok correctly used of its enumeration Ok = a > b ) ? True : False. NAMING CONSTANTS CALLED 'ENUMERATIONS' integral . From there on the preprocessor will substitute 3. Boolean Ok.'= Yes . Foot=i2*Inch f X .HAM ED USING const OR fdeftne \ your program deals with the geometry of circles you may write the value of K as a literal constant: Area = 3. You may nominate Int variables capable of storing int values in the range of the enumeration • enum • enum • enum p~ enum f No. o or ra ~z2z3 error: Yes a COH 34 ILLUSTRATING C . Boolean { False.141593 d / 4. enumeration >enum name expression } name . /* Program 1 with circle *v •include <stdio. Yes < J d probably all -S^Q not nice.141593 for every independent occurrence of PI (f not in comments or where PI is part of a longer token ]). _ _ Imperial {Inch=l. \/r\\e #define with # as the first visible character on the line and no semicolon at the end as shown.141593 j int main ( v o i d ) . Tjfhe traditional way to name a C constant is to write a name (f PI say ]) and tell the preprocessor to substitute a value for it. if ( Ok . True }. I untouched PIPE = 6 . You may not use this kind of constant in 'constant expressions' evaluated at compile time. Ok == 2 * Yes. Ok =E ( a > b ) .h> ~^ int main ( v o i d ) const^Pi = * d * d * / 4: \^Jr give n a name and value as shown here: Tjhe const is a qualifier. Thereafter.) break. ijntegral constants may be named in an enumeration.h> •define PI 3. the processor will not allow you to change the initialized v a l u e r by assignment or any other means. The nominated variable should be initialized in the same declaration. The preprocessor is covered in Chapter 5 /* Program 2 with circles */ •include <stdio. It qualifies the variable declared next on its right. Yes } .

it is defined on Page 135.THIS TERM COVERS A VARIETY OF CONSTRUCTS Impressions are used in earlier examples without formal definition. • . here they are defined syntactically under the names prefix.N) • ( double ) i • x<0 ? . The definition of expression is simple: ^ • * .a + b * c Operators are described individually later in this chapter.x : x . term constant string • 6L • "Ans: % i " <= ss I&& of an I object i name name [ expression ] • Table [3][4] name ( expression ) (type-name) expression • Powr(l+R. postfix and infix* prefix infix / % f+ see pages 39 to 45 & summary on page 46 l\n the following definition of term^ the optional entity called type-name has yet to be introduced. ^ sizeof Table • sizeof(double) »= 1 = expression! expression: expression *~*^— sizeof expression (type-name) (expression) (expression) ^ sizeof(a*b+c) • (y * (a+b) ) 3 : COMPONENTS 35 .

it follows that blocks may be 'nested'. expression. £)elow is the syntax of program: 4f\ program comprises a set of declarations* each of which may declare ject. ) statement for ( expression \ case break. return ]).AND l # l e r e is the syntax of statement. All the declarations in each block must precede the first statement of that block. others are covered in Phnnl-or A Chapter 4. break. default : statement continue. return goto expression . statement block if ( expression ) statement else while ( expression ) statement do statement while ( expression ) . a I^Jecause a statement may be a & x £ and because a Ak%r>f contains at least one statement. Some control statements have already been introduced (J if. a function prototype or a function definition. for. You must a global give precisely one function the name main. program declaration 36 ILLUSTRATING C . nameT fnonrinatesx a label i statement expression. switch ( expression ) statement expression : statement name : statement { declaration statement } • { irrt i * l.

v ^ b j e c t s a r e things which have a name and a type (f or shape ]) and can store d a t a . structures and unions.P . The object is then defined. c j . float x = 3. in general. Invocations f r o m inside functions that precede this definition would be errors. is defined again here. ations o f simple types a r e char Letter[] = { a . introduced earlier. We meet structures and unions in Chapter 8 . TJfhe differences between declaration and definition are semantic rather than syntactic. shown h e r e : float x = 3. more complicated than suggested above. Some examples o f typical declar~~ ~~ int j . the full syntax o f a declaration must wait until later (f Chapter 8 } . 4>\n object declared but not initialized ({ e. Jjfach declaration applies as f a r as the end of the current file (J the scope' of the declaration j). float Absolute ( float P ) { if ( P >= 0. R e f e r r i n g back to the program on Page 22.0 ) return P .45. and are further described in Chapter 5. and statements inside functions that follow this definition. automatically initialized to z e r o at the end of compilation as though you had originally declared int i = 0 . int i ) is. A SEMANTIC DIFFERENCE / h e n an object is initialized (J e. k. But in a block of program within this scope. a contradictory declaration may 'hide' the original H[ the 'visibility' J). and that FormulaO precedes main() in which FormulaO is invoked. b .45 j) the declaration becomes a definition \ any further defining of x would make the processor report an error during compilation or linking. An object must be declared b e f o r e it can be used. SEQUENCE OF DECLARATIONS l/unction Absolute(). The differences are.g.OF 'OBJECTS' AND FUNCTIONS (FOR FULL SYNTAX SEE CHAPTER 8) S u b j e c t s ' (f or 'data objects' )) a r e variables. a r r a y s . Statements inside this function. notice that function Powr() precedes function FormulaO in which P o w r ( ) is invoked. may all invoke Absolute(). enumerations.g. y e c a u s e structures and unions have not yet been i n t r o d u c e d . Scope and visibility are further described below. else return . in f a c t . Absolute ( y ) 3: COMPONENTS 37 .

double OldFun ( a .P . name optional] function declaration is called a prototype \ a concept new to ANSI C.H signifies a header Rbe y . namesof parameters only TJfo keep a program tidy. b. collect all the prototypes in a file and qive the file a name such as MYHDR. prototype. the shape of a function definition was different. At the top of your main program write #include "MYHDR. 4 \ prototype has the same form as the header of a function definition except: • • names of variables are simply comments. y|ach prototype must be placed somewhere before the first invocation of the corresponding function. VITAL TO ANSI C Tf he restriction on sequence of declarations explained above may be removed by employing a Function declaration as well as a function definition. it is not illustrated further in this book.H (j[ where . float Absolute (floaO.H" which has the same effect as copying out all the prototypes ahead of the main program. float Absolute (float P ) .PROTOTYPE DECLARATIOHS. prototypes did not exist in 'old-style' C. Although this syntax is permitted by ANSI C. 38 ILLUSTRATING C . else return . outside all function definitions this statement recognized rfloat float Absolute (float).0) return P. they may be different from those in the definition or omitted altogether every prototype ends with a semicolon. the parameters being declared between the header and its block. Absolute ( 2 * a / b ) f Absolute (float P) =^3c= relative Location of the definition is no longer significant if (P>=0. Furthermore. c ) char c . an obvious place is near the top of the file.

ARITHMETIC, LOGICAL, BITWISE, ASSIGNMENT, INCREMENTING, SEQUENCE _ Page 35 operators are grouped according to their role in the syntax of expressions (J prefix, infix, postfix ]). Here they are classified according to the kind of work they do. TJhe term operand signifies expression, the expression conforming to any special requirements noted (f such as integral value J.

Value of operand unchanged • -pow ( 2 , 16) Value of operand negated

operand

operand

a a a a •

+ / *

b b b b

Sum Difference Quotient Product 'Modulo'; the remainder when i is divided by j

operand

%

operand

a % j

*both integral V

?'non-zero k

<= l^ogical not is a prefix operator

&&

operand

.'Try

I f Try contains a n o n - z e r o value ((true^ then ! T r y indicates a z e r o value ((false]). And vice versa

3: COMPONENTS

39

Ijach comparison made using the following six infix operators takes the result l (f type int D if the comparison proves to be true\ zero if it proves false. • j operand > operand • n > m n >m Greater than d[&>5 gives lj) Greater than or equal to n >« m Less than ({6<5 gives 0% n < m Less than or equal to n <= m = Equal to n == m Not equal to n U= m : : yVuth tables f o r the operators && (f and j) and || fl or J are shown. The symmetry of the tables shows that these operations are commutative. For example, i && j gives the same result as j && i ; operand operand • i && j • i Logical and d 2 && 3 gives 1 ]) Logical or

and

operand t 0 =0
0 0

or

opero ind * 0
1

II
§- 0

=0
1

|^0

1

§= 0

0

1

0

l^itwise operators are vital for screen graphics, for packing and unpacking data, and other devices of the programmer's craft. 4k\ll operands of bitwise operators must be integral. Because computers have different ways of representing negative integers, use bitwise operators only on the unsigned types. unsigned int on your installation may be represented as a 16-bit word. If so, 26 will be stored like this:

11010 (binary)

2 = 26 ( decimal )

_m is stored as sixteen 0's. The biggest number (J 1+2+4+8+16+... +32768 = 65536 J is stored as sixteen l's.

0
€5536

Ioio loioioioioioloioiolololoToToi
ItlllllllllUllllXJlll IX 1 1 1 1 11 LI I

ILLUSTRATING C

operand

operand

X & XII X I XII X A XII

Bitwise and Bitwise or Bitwise exclusive or

Bitwise not

operand

• •

X « N X » N

Shift left N places: right fill with 0's Shift right N places: left fill with 0's

•include <stdio.h> void main (void) f unsigned int ^ Zero = 0 , X = 10, XII = 12; Zero); printf ( " \ n % u " ,
Zero

.fl.O .0.0 .0.0 .0X0^0.0.0.0.0
I i. 1 - 1 . 1 - 1 - 1 . 1 - H i .1

.O.Q\

operand

Zero

A A . i A A A l

^0 1=0 0 |1

printf C"\n%u",
x

X & XII ) ;
. 0 .0 A .0 A .0\

lO . 0 . 0. 0.0. 0.0.010.0

Xii
X & XII

\o.o.o

.o.o.o.o.olo.o.o.o.i

. 1 . oToi

operand 0

10,0,0.0.0.0.0 ,0|0.0,0.0.1 .0.0.01

printf ("\n%u f \
X XII

X | XII );
operand

I 0-0 -0 -0 -0 . 0 . 0 -6 1 0 - 0 - 0 . 0 . | 0 . 0 . 0 . 0.0.0. 0 . 0 I 0 . 0 . O . ~ 1. l

o

XII

Io .o.o . o . o . o . o . o l o . o .o _~. X A XII ) ;
operand

printf ( " \ n % \ n " , X x*1 X
A

l o . 0 . 0 . 0 .o.o.o.o Io.o. o . o . l . 0 . i Io . o . o . o . o . o . o . oIo . o. o . o A - I , o . o I I 0 . 0 . 0 . 0 . 0 . 0 . 0 . 0 I 0 . 0 . 0 . 0 . 0. 1.1 .01
.=0

o

XII

printf ( f \n%u % u f \

3: COMPONENTS

41

*=

i f h e operand on the left of an assignment is typically the name of a variable or array element.

TJfhe term L-vabue (J or Lvalue j) is short for 'left value' and is used in the jargon ^ with blatant disregard for the sanctity of English 4=* to identify items that make sense only on the left of an assignment. In general, [-values are names of storage locations ^ or expressions that point to storage locations <& in which the content may be altered. We meet pointers later.

operand

operand

n = m

Assigns value of right operand to the location identified by the left operand (f 'puts value into n 1 j) Short for n = n = n = n » n = n n n n n + m - m * m / m % m

If

operand

+=
—5S

operand

*

=

n += m n —ss m n *= m n /= m n % = m ^<3^\ ) integral)

operand

&

=

operand

i
i i i • i

4
integrali
L-vaLue J

A

=

&= A -

h

j j j j j

Short for

i i i i

i = * = =

i i i i i

& A 1 « »

j j j j j

l\f you include one of the above assignments as a term in a Larger expression the term contributes the value assigned. Thus in the expression: 4 + ( n = a[i] ) Tjfhe term ( n = a [ i ] ) contributes the value assigned to n. If array element a [ i ] contained 3, this 3 would be assigned to n , and the value of ( n = a [ i ] ) would be 3. Tjfhe value of the whole expression would therefore be 4 + 3 = 7.

42

ILLUSTRATING C

q = 2 * p++. USEFUL IN THE PARAMETERS OF A for LOOP operand operand 3. Tjhe following program demonstrates the difference in result between prefixing and postfixing the operator. twice the incremented value } . Similarly with «-i the decremented value is taken as the value of the term. m Evaluate & discard n=3. the incremented value of i is taken as the value of the term. #include <stdio. the behaviour being different in each case. operand prefix Short for i = i + 1 Short for i = i . 3: COMPONENTS 43 . printf("\n%i P = 6. the original value of i is taken as the value of the term. Similarly for i—-. prlntf ( \n%i r e t u r n 0. value of expression is value of m \typically an I assignment i j h e expression comprising the first operand is evaluated \ any side effects being implemented J) and the value of the expression discarded. operand integral\ ' \ULpostfix Short for i = i + 1 Short for i s i .i i j f you include i++ as a term of a larger expression.Ijncrementing operators are special assignment operators. its value being made the value o f the complete expression. Each may be used as a prefix operator or postfix operator.h> int main ( v o i d ) { P q = 2*++p. Then the second operand is evaluated.i i j f you include ++i as a term of a larger expression.

7/8 | •o CD s. (My terminology.n Member named n of structure identified by s (nominates a structure (points to a structure operand -> operand p->n -rn •n I 2. These topics are introduced later. 1024 operand ^ "V &a L-vaLue The address of a prefix & a (f the address of a J) is 1028 * 1 : operand *p K ^_^—^ ^\£identifies \ pointer \ variableg The 'pointee' o f . . for sake of completeness. n parentheses essential. Here.14 operand operand s. precedence would make * p .718A Member named n of the pointee of p <J[ where p points to a structure ^ NOTE p->n IS SHORT FOR ( * p ) . analogous to 'appointee'} [assume NOTE *&a SAYS THE SAME THING AS a (J *& cancels itself out ]) absolute addresses are seldom of interest.& * TJfhe reference operators are concerned with pointers and structures.n is 2. n imply * ( p . . are definitions in mechanistic terms. so / p *p d[ the pointee of p ^ is 3. n ) 44 ILLUSTRATING C .

sizeof. is for discovering the number of storage units J bytes D occupied by a particular object or by an object of particular typ>e. operand [ s—^~ — N f identifies an {10. exceedingly useful. [prefix operator. parentheses constitute a p>ostfix operator. All three operands are expressions. operand ? operand : operand • max « ? a*b : c * d . 0 ) sizeof sizeof operand (type-name) p.] \never as a sequencer \^ *fvo]d) ^ ' 4%—} with no (parameters > returning \pointer to int ^rackets constitute a postfix operator for subscripting the array identified by the operand.sizeof l/irst the ternary operator. the first of which is integral. sj/nly one of the last two expressions is evaluated. This operator is used for dynamic storage (J Chapter 1 1 . 3 ) . expression) is implied) " double AbsVal ( double x ) { return x < 0 ? -x : x .sizeof a sizeof ( double ) sizeof ( struct s ) an object:* " (variable. .. 20. array. establishing that the operand is a function. 30}. s nominates the type to which the value of the operand is to be converted before use. ~ " • • AbsVal ( d ) DOW ( a . the rcsu» becomes the value of * h e e n h r e expression (f assigned to max in the example above D f returns -x if x is negative^] otherwise returns +x f he 'cast' (} or 'typ>e cast' J) involves a prefix operator: ( type-name ) operand v^—">v "V-N^'* >v*V • AbsVal ( (double) ( 2 * i ) ) N^ \ ^ -^y ^ ^ >s^~ \ ^ -V. structure or union)' sizeoF (char) has the A value l 3 : COMPONENTS 45 ..^—fr function these parentheses^ the compiler treats J ^ {comma as a separator.

0 otherwise • a<b • a<=b 1 if a less than or equal to b . w • p . . .a i short for i = i&m short for i = i|m 0 short for i = iAm short for i = i » m short for i = i « m member w of structure v • v. b. then decrement 46 ILLUSTRATING C . v or *p )). .> w short for ( * p ). . right fill with 0's • m » n m shifted n posns right. . w a postfix • i++ • i— use value of i .PREFIX* WFIX. n stand for expressions which reduce to numerical values (J integral values in the case of m and n ]) p nominates (Jor otherwise indicates ]) a pointer variable nominates a member of a structure or union. . the type of l-value is integral a. 0 otherwise 1 if a grtr than or equal to b . 0 otherwise 1 if a is not equal to b . . 0 otherwise • a!=b • m&&n logical AND logical OR • m||n n-tt> assign value a to object v 1 0 short f o r v = v * a short f o r v = v / a 0 0 • v/=a • i%= m short for i = i%m • v+=a short for v = v + a rolln r\i<t> short for v = v . In the case of i . v. . . then increment use value of i . m. . 0 otherwise 1 if a less than b . . . evaluate and retain b 1 if a greater than b . 0 otherwise • a==b 1 if a equals b . POSTFIX OPERATORS nominate objects that are l-values %e.g. t prefix confirmation negation address of the pointee of (j[ object pointed to by )) ones' complement (J i(300U00 -> 01110011 1) !m —i • • • • • • • a*b a/b m%n a+ b a-b m &n m|n logical N T (J 1 if m is FALSE ]) O increment i before using its value decrement i before using its value < J&& *= » = « = 1 I vn m 0 I <b 1 product n 1 i 0 110 quotient n 1 i 0 I remainder n< n& 0 0 1 0 sum 1 0 t ^ difference t i 00 bitwise AND n <t)i bitwise OR noAn l bitwise EXCLUSIVE OR • m « n m shifted n positions left. left fill type-dependent evaluate and discard a .

OF OPERATORS \fha\ does a + b % c mean? ( a + b ) % c or a + ( b % c ) ? The question can be asked another way: which of + and % takes precedence? The following table shows the precedence of all operators. precedence is relevant where successive operators are found in different rows of the table. V/hat does a/b/c mean? ( a / b ) / c or a / ( b / c ) ? (t Try 8 / 4 / 2 both ways and see the difference j ) This question can be asked another way: When successive operators have equal precedence. The table shows by an arrow the direction of associativity \ left to right or right to left j) at every precedence level. In any one row. those in the top row take precedence over those in the second. associativity is relevant where successive operators are found in the same row of the table. l\n the placing of parentheses. HIGH ( expr ) [ expr ] ! * ~ / % + ++ * < <= all the rest. all operators have equal precedence. infix A & A ternary operator = LOW *= /= %= «= Example: precedence 5 + -3 * 4 > -8 [jjxample: associativity (value is /4 ex *= a *= a *= a *= b b b ( = = = b c c ( = R to L 5 + (-3) * 4 > (-8) \( true A 5 + ((-3) * 4 ) > (-8) (5 + (( -3 ) * 4 )) > (-8) += d /= e += ( d /= e ) c += ( d /= e )) ( c += ( d /= e ))) 3 : COMPONENTS 47 . in which direction are parentheses applied? Left to right or right to left? The required direction is the associativity. and so on.

parameters of different type are coerced in the manner just described. For example. for example. the program coerces values to the type of the receiving object. F (float). the processor 'coerces' values to ( a consistent type. Coercion of parameters works because the processor can see from the prototype declaration what types of arguments the function expects.3 . but in a form suitable for storage as a long double. Do not use casts with literal constants. also involves conversion can be trouble when a 'higher' 2 . # 5 £ SUFFIXES. 48 ILLUSTRATING C . (j|2£^^ A FORM OF ASSIGNMENT ijnvoking a function with parameters is a form of assignment. 1 . U (unsigned) are defined on rage 33 . 'LOWER'TO 'HIGHER'*. U (long or long double). TJfhe converse.1 would be warning. Coercion may cause a short integer to become long (jf 'promotion' J) or a long to become short (J 'demotion j) according to the context of the expression.0 instead of 2. whereas 2. Or you could avoid coercion by writing AbsVal ( (double)-3 ) . NOT CASTS lateral constants not of type int or double would be suffixed to specify type. Thus 2L represents the value 2 in a form suitable for storage as a long int. because 2 is of 'lower' type than d . 0 ) . With i = lost and you would probably receive a collapse on meeting i = 10000. where i is of before assignment is possible. I f you wish to override coercion you may include a cast to specify the precise promotion or demotion required.0L represents the same value. The same effect can be achieved by a cast. VICE VERSA I f h e processor cannot directly obey the statement d = 2. [Jor example. But there value is demoted to a 'lower'. where d is of type double. Some processors would OVERRIDES COERCION /hen assignment involves different types. The expression i = (int) d causes the converse by demotion.3 ) (j where the parameter has been declared of type double )) the -3 would be coerced to type double as though you had written AbsVal ( . you cannot store an int in a location declared double. i = 2 . type int. f d = (double) i'causes a copy of the content of i to be promoted to type double and assigned to d .COERCION & CASTS \f/hen terms of an expression are of different type. the . 0 . The promoted value is then assigned to d . In obeying d = 2 the processor first takes a copy of 2 and promotes the copy to double >5» as though you had written 2. in AbsVal ( .

TJfhe rules obeyed by the processor f o r maintaining the principle of promotion to 'higher' type are as follows: If or each o p e r a n d . if it is: • • • • unsigned short int promote unsigned char promote signed char promote char promote its value to signed int int with zero leFt fill its value to its value to int with sign extended its value to int ( form depends on impLementation ) i j h e n ask if the type of either operand is one of the following: long double? double ? Y Y Y Y Y Y N float ? unsigned long int? long int? unsigned int ? ( p r o d u c e result of type int /jfromote the value of the other operand to the same type. then produce a result of this same type. I n such a case the processor promotes the operand of 'lower' type (jf in this case 4 which is int ]) to the 'higher' type (J in this case that of 3.y[n general.141593/4 is a simple example involving the division operator.141593 which is double j). 3: COMPONENTS 49 . any infix operator can cause type promotion if given operands of different type: 3.

.

Tjfhis chapter describes the control statements of C and their use. for. switch goto . These statements control the sequence of execution within a function. Without them. return. return if. (jontrol statements are classified in this chapter as follows: Tested loops Counted loops Escape Selection Jump while. execution starts at the first statement after the heading of the function and proceeds sequentially to the last. (jontrol statements already introduced are: if. continue. do for break. do. break.

) do statement while ( expression ) . Whatever ihe goal.LOOP UNTIL A CONDITION IS MET while AND do numerical value. It may be x executed again and again until some goal is achieved « * such as the difference between two quantities becoming very small. TJfhe 'while' loop is needed more often than 'do\ but an example in which 'do' is appropriate is given on Page 23. the test for continuation being at the bottom. typically integer orA pointer statement ( expression ) \ true false Tjfhe statement is executed at least once. numerical ) value. . true or false. Escape from an infinite loop using 'break! while ( 1 ) infinite Loop or for ( . expression reduces to zero (J or null ]) then statement is not executed at alL The test for continuation is at the top. it must be expressed as a logical value. on entry to the while loop. ijfested loops are useful when you do not know in advance how many times (f if any D e piece of program is to be executed. typically integer or pointer while true \ expression ( expression ) statement statement I j f . /jt\p infinite loop may be constructed by writing a non-zero constant as the expression (j[ permanently true ]). 52 ILLUSTRATING C .

statement expressions increment \/ an infinite loop by omitting the test. expr) return expression t omit expression if function is defined to return void value of expression is (returned to the invocation las though by assignment \tor all serious programs. For example: for ( a = l . TJfhe statement forming the body of the loop is typically a compound statement. and once only. hence to the next execution of the body > » if the control mechanism so requires. expr. j) while ( expression) for ( expr. expression/. d( You can escape from a complete nest of loops using the 'goto label1 statement but use of 'goto'. and include a 'return 0. except for error recovery. b=l. i GETTIHG OUT OF A LOOP BY break AND continue RETURNING FROM A FUNCTION BY return 'break' takes you out of the present loop altogether.true increment: after executing body for{expression^ expression/ true expressiori2 expression. is frowned upon. thereby implying constantly true. as you can see from the flow chart.PREDETERMINED NUMBER OF TIMES for test: omission implies 1 . declare rnainO' cxs type int. the comma operator to extend any or all expressions. 'continue' takes you to the end or the body of the loop. 4: CONTROL 53 . is executed at least once. The zero signifies normal termination to the computer environment. x>y. expressions^ statement \initiatizer (optional) false Tjfhe initializer.

5 x 4 ) = -6. TJ*he bounded surface must be kept to the left of each arrow: the sides of the figure should not cross each other as in a figure of eight.i ( XiYj . j 2 3 4 same formula may be used for computing the area on the left. the sum of the areas will be the area enclosed. Number of vertices: return 0.2. printf ("\nArea is %. is a program by which to input coordinates of boundary points and compute the area enclosed: /* Area of a polygon * / •include <stdio. & Y[j] ).Yl lyut if the polygon is closed. j + l ). j<n.5*(x[ j ] * y [ ( l + j ) % n ] . Area ).5 x 1 ) = 1. for ( j=0. scanf ("%i". scanf (" %f %f ". j . 5 . &n ) . & x[j]. printf ("\n\nNumber of vertices? : " ) . ++i ) Area += <z). double Area = 0. ++j ) f printf ("Coords of point %i ? : ". y [ 3 0 ] .x [ ( l + j ) % n ] * y [ j ] ) .h> int main ( void ) int n. x [ 3 0 ] .75 4 I 3 jf^ x i > Y i ' d> i 1 i .i C XiYj . But this area turns out to be negative"" Aij . and the triangular areas summed to give the area shown here Xi.2lf .0. Tjfhe expression ( l + j ) % n gives values as shown by the little table Coords Coords Coords Coords of of of of point 1 point 2 point 3 point 54 ILLUSTRATING C .COUNTED LOOPS Consider the diagam on the right: The shaded area is given by Ay where: Aij . as shown on the left.XjYi ) ^ ( 3 x 2 . for ( j = 0.25 ^ 0 1 2 3 A 5 y r i e formula may be applied to sequential sides of a polygon.XjYi ) = -^C 2 X 3 . j < n .

s = ( a + b + c ) / 2. zero signifies false jJ ^ ^ . double s. d . C ? \ n " ) . scanfC"%f ". T. c. &a.5 2 Area i s 7. & Letter). Area = sqrt ( s * ( s . 2 /* Areas of shapes */ #include <stdio.^ ^ . (pointer type).. scanf("%c". Area ) . printf ("\nR.v signifies false true false false expression statementl expression statementl statement2 discussion on nesting and other features of if . C ? R b & d please 3. b. i j h e example illustrates nested if's. Hon-zero signifies} (when expression signifies"Vexecuted when expression true. &d ) . if ( Letter == 'R' ) { printf ("b & d please\n" ) . Area = b * d . Area. T. a. &d ) .h> int main ( v o i d ) double Pi = 3.. scanf("%f %f r\ &b. b & c please\n" scanf("%f %f %f.2f".141593. char Letter. else if ( Letter == 'C' ) { printf ("d please\n" ) .h> #include <math.00 55 . 4 : CONTROL R. &b. return 0 . if ( Ok ) printf ("Area is %6. if present. not always the best way to express program logic.else on pp 1 & 13.a ) * ( s . ^ true ^ ^ ^ y . int Ok = 1.L . Area = Pi * d * d / 4 . else Ok = 0 . else printf ("Try again" ) .if ( expression ) statement! else statement2 (numerical (typically integer or \ /this statement executed \ (this statement. else if ( Letter == 'T' ) { printf ("a.

. else /. 4\ssume Roman numerals to be composed of the following elements. never more than one from each consecutive list: 'thousands ) . Experiment with MCMXCII cxnd you should get 1992.. So add 1 to the value (J 100 + l = 101 )) and move the arrow to state 11. You are in state 00 (f where the arrow is J). Few are asked to input and decode Roman numbers like MCMXCII. look down from symbol X and find 8:15. Begin with a value of zero. This approach is tidier than logic based on if and else.hundreds C=100 CC=200 CCC=300 CD=400 D=500 DC=600 DCC=700 DCCC=800 X=10 XX=20 XXX=30 XL=40 L=50 LX=60 LXX=70 LXXX=80 XC=90 M=1000 MM=2000 MMM=3000 etc.TABLE-CONTROLLED LOGIC. So add 8 to the value (| 101 + 8 = 109 ]) and move the arrow to state 15. Look down from symbol C and find 100:03 which says 'Add 100 to the value and change state to 03. Finally. AVOIDING CLUMSINESS OF if. Tjfhe logic of the program is contained in the\ following [starting \ state J SYMBOL symbol-state table: M 1000: 00 800: 05 D C 03 02 04 04 05 L 50:07 50:07 50:07 50:07 50:07 50:07 30:10 X 10:06 10:06 10:06 10:06 10:06 10:06 10:09 10:08 10:09 10: 10 8:15 V 5:12 5:12 5:12 5:12 5:12 5:12 5:12 5:12 5:12 5:12 5:12 3:15 1 1 1 1 1 1 1 1 I s s r s 5 S S S 11 11 11 11 11 11 11 11 error \ t£>00 ^-^ 0i 02 03 04 05 06 08 09 10 11 12 13 500: 01 100: 100: 100: 300: 05 100: 100: LU < 80:10 14 15 1 r 11 1 2 11 1 s 11 1:14 l : 13 l : 14 l : 15 TJfake the Roman number QX as an example. so QX decodes as 109. 56 ILLUSTRATING C .programmers spend a lot of time writing input routines. but this presents no particular difficulty if you use a symbol-state table. TJfhere are no more Roman digits. a row of empty cells. Experiment with MDDI and you should encounter an empty cell which means an error of formation.ero and move the arrow to 03. I I I I was common.' So add 100 to z. Now look down from symbol I and find 1:11. 1=1 11=2 111=3 IV=4 V=5 VI=6 VII=7 VIII=8 IX=9 IJn fact the Romans felt less constrained. Some monuments have inscriptions of numbers starting with more than twenty Cs.

1006. 512. 512. 113. 0. ^ — x ^—v^-i } select next row of table) • " • ^ — ^ . 0. 815. 50001. 5007. 0. 111. 512. 0. 0. 0. divide by 100 and use the quotient as the contribution to the final value and the remainder to give the next state. 0. V. 0. 0. int Column. 0. 0.1992 i n Arabics ) End of run —N^^^^^^^—. Ill. 0. 114. 0. HI. 0. 111. 0. 0. 0. 0. 1010. return 0 . 114. 111. 0. 0. 10004. 0. Column < 7 && Ch Symbol [Column ] . 0. 0. 512. 0. 0. 0. Thus 50001 gives a contribution of 5000i / 100 = 500 (f integer division D and a new state of 50001 % i00 = l (J remainder when 50001 is divided by 100 ]). 111. 5007. 0. 3010. while ( (Ch = getcharO) != \ n&& Entry ) stops Looping if Entry picks) . 0. 111. /* Roman Numerals */ •include <stdio. 1006. as < accumulate Number ) — ^ Row = Entry % 100. 512. 10002. 1006. 111. 1006^ 1006. 512. ++Column) enter *. 0. 0. ^ ^ . 0. 0. 1008. 0. 0. 512. 0. ijfwo pieces of information are packed into each element of the table.if he program to implement this method of decoding is short and simple because the logic**the difficult p a r t • » is embodied in the table. 5007. 5007. ^^ ^ —t Number += Entry / 100. 1009. 1009.h> char Symbol [ ] = f long Table [16] [8] = i { ( { f f f f f ( f { f { { { { 100000.>^^><^y Entry = Table [Row] |[Column]. char Ch. 0. 0. 512. 0. 0. 0. printf ("\nEnd of run). 5007. 0. 30005. 0. 'I' }. To unravel. 10004. L • A . 0. } } . Number = 0 . 0. 0. 512. 512. 8010. 0. 0. 0. 10005. 0. Row = 0 . int main ( void ) r i long Entry = 1. v» . 5007. The array has to be declared as 'long' on installations that offer only 1 bits f o r an 6 'int'. 111. 0. Number) 9 printf ("ViError"). 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 • f • f f ! .^ s—^^—s •c ir (Entry.N ^ up zero (false) *** "^s^^—V^ "N^ V ^ ^^~X !* for ( Column = 0. 0. 0. 0. 512. /r~ L *\ r*~~ Enter a number MCMXCII . 80005. printf ("=%i in Arabics". 111.——^^ } 4 : CONTROL 57 . 10003. 315. 0. printf ("\nEnter a number\n"). 0. . 1006. 115. 0. 111.

Area = b * d. (Undefined J ^ * " * * ^behaviour if there is neither) < match nor default) }'break statement typically terminates each case printf ("How may legs did it have?"). If there is no match. & Legs ). expression more than] default per switch - vay involve constants y evaluated at compile time. « 'Unique value essential after] {every case in the same block Statement <^d^xecuted if no match. break. \case expression matches^ [ value of the switch j . break. intf (case default printf ("Could be dangerous"). l -r' 'L' case T: case t: 58 ILLUSTRATING C . break. & d ).SELECTION STATEMENT switch ( expression ) statement ^^ typically a { block } . The Areas program could be improved using rswitch' in place o f ' i f ' a s shown below: [switch ( Letter ) f case 'R': case V : printf ("b & d please\n"). & b. break. " • ise f particular) case 4 iniP ("Probably a mouse"). break. J y'""" ~~***^~ "V^ "V" "V ~**~~ breaks take you here TJhe switch statement is useful wherever the logic demands selection of one case from a group of several. switch ( Legs ) case 8: printf ("A spider. Control f jumps to the statement following the matching^ value. ^ ^ ^ i terminates . no K case 3 • case 5: case l: printf (Thai's odd!11). b r e a k . scanf ("%lf %lf'. containing case labels and\ \ a single default: label integral value ( coerced if necessary to int or unsigned int ) is compared with the value of 4^ each case expression in the block. case 2: printf ("A double-glazing sales person11). perhaps?"). control jumps tqj the statement following default: xase expressionjy > statement /this statement is next to be) executed if value of the . ^ ^ i ^ / prii \ order % case 6 •intf V ^ > / multiple i printf (Definitely a bug"). scanf("%i".

("\nTen maids a-milking. "). The outer switch is given a case for each state (J row ]) of the table. d . t ) r d [ j + l ] ) ."). n ." ) . 59 . / * 1 days of Christmas * / 2 int main( void ) { int i . control simply falls through to the next as illustrated by the following program which displays all twelve verses of a tedious Christmas carol. char Ord[] = { s. switch ( i ) case case case case case case case case case case case printf case printf printf printf 10 printf 9: printf 8: printf 7: printf 6: printf 5: printf 4: printf 3: printf 2: ( "\nAnd a l: printf 12 11: ("\nTwelve drummers drumming."). Rested switch statements are useful for implementing the logic contained in symbol-state tables."). i return 0 . RECOVERIHG FROM CHAOS 4p\n error mess. if ( i « i ) printf C"\nA " ) . ("\nEight ladies dancing. O r d [ j ] . The logic in each of these cases comprises an inner switch having a case for each symbol (j[ column j) of the table. ("\n'leven pipers piping. t . f\nFive 6O-OLD rings.")."). ("\nThree French hens. i ."). d .l\f you omit 'break' after the statements belonging to one particular case. ("\nTwo-oo turtle doves. h j . condition may be drastic enough to warrant a jump out of the ^—^—^—^_ ^ a label marking a ^statement in the same\ goto (matching ) ^ name M !^iJ 4: CONTROL : statement of labels do not clash with names of other entities. t. printf ("day of Christmas my true love sent to me."). ("\nFour calling birds. ("\nNine lords a-leaping."). ("\nSix geese a-laying."). ("\nSeven swans a-swimming. ("part ri-i-idge in a pear treeee. printf ("%i%c%c " ."). r."). j .").

4f\ vector "v is written as: v = where v#. V2 a #.^v. This expression represents the product of the length of one vector and the projected length of the other upon it.33. it connects the tip of cT to the tip of IT: a= = If . Another way to look at it is: Jw| Iv| CO38 Tjhe vector (j( or cross ]) product.241T T T Tjake a vector. 2 are its projections in the directions depicted. i.LOTS OF LOOPS: THIS PROGRAM IS FOR THE READER WHO HAS A LITTLE MATHEMATICS ij*he power cables a and b look as if they are running uncomfortably close to one another.53 Jo a unit vector.72?- j * + 0. is a vector normal to a and b: a x b = J 8 8 IT* 8t parallel is length is //(24) 2 + (-22)2 + (8) 2 = 33. connecting any point on o to any point on IT. What is the closest distance between them? f his would be an awkward problem without vector algebra: here are enough of the principles to solve it. a x b. is given by w^v^ + wivi + W2V2. The length (J modulus ^ of v" is: Ivl = l^ivide "v by_Jts own length and y o u have a unit long vector in the same w* -* Vi -* V + o > direction as v: lvl 171 ^ ^ Ivl Ijfhe scalar (J or dot j) product.1 above.53 0. ^ . vi.5f . In the sketch . c . It is a vector having a direction normal both to 'v and to w r r t Tjfhat's a1 we need of vector algebra for this problem.it ILLUSTRATING C . Here one. ~v x w is given by this determinant. ~a and £T can be expressed: 4)r+ (l6-8)j*+ a = (9-4/T+ (16-8J (l7-10)jT = 5f+8j^+ i t -6)r+ (ii-3)r+ (i5-5)iT = 4r+ 8T t 7 ijheir cross product. "c^ connecting any point on ^T to any point on ID is -f.

j . printf ( "\nCable %c\n". m=3-m ) . asq=0.66) + (-2) x (0.y. Clearance = (csq > 0) ? sqrt( csq ) : 0. if C'(j%3)) printf ( "End % i : x. return 0.52 approximately I j f the cables run parallel.z coords: 10 Clearance between A & B 8 10 16 17 3 5 11 15 is 3. c[3]. / * Power cables. csq=0. b[j] = Coord [9 + j ] . Coord [12].y. & Coord [ j ] ) . are they too close? * / #include <stdio. = a[2] * b[0] . j < 3 . ^x_^-^ W ^~^ alternating) for { a[j] = Coord [3 + j ] .z coords: 6 End 2: x. csq.a[0] * b[2]. scanf ("%Lf".(project this onto the unit vector to give the shortest distance between the cables: d = (t)x(0.y.h> ^s-^~^~~^~\ #include <math.Coord [3 + j ] .24) = 3.z coords: 9 Cable B End 1: x. csq /= sqrt tusq).0) ? -csq: } else ^^^paralLei) '<^rm^cablesj' for ( j = 0. j<3. z coords: " .2Lf\n". Clearance). usq=0.z coords: 4 End 2: x.b[l] * a[2]. k=l. usq^ += u[j] * u[j]: if (usq > 0. = a[0] * b[l] . special action is needed as shown in the 'else' clause in the program.0.0.72) + (-5) x (-0.0) ^ r ^ r . += c[j] * u [ j ] . ++j) { asq += a [ j ] * a [ j ] . Cable[] = {'A'.0.h> -*^jf^"e need sqrtj int main ( void ) ^^^-—r-* int char double double for ( j = 0. printf ("\nClearance between A & B is %. csq += c[j] * c [ j ] . c [ j ] = Coord [9 + j ] . Cable [k=l-k] ) .Coord [ j ] . m=2.521 -= Proj * Proj / asq. Cable A End 1: x. Proj=0.y. Clearance=0. Proj += a[j] * c [ j ] . j < 3 .0.0. u[3]. 'B'}. b[3]. a[3].b[0] * (j = 0. ClearanceJ^(csq < 0. u[0] u[l] u[2] for = a[l] * b[2] .3 non-parallel for ( j = 0. y.Coord [6 + j ] .0. 4: CONTROL 61 . j <12.

So swop the two letters icated. nor have those to the right of i . move j another step towards i : C B L I G N M H ow j indicates a bigger letter than i does. arrows. In other words the letter indicated has found its resting place. starting out in each case in the manner described in detail above. j indicates a 'bigger' letter than i does. move j another step towards i . So swop letters. TJake some letters to sort: G B L I C N M H an arrow at either end of the list and prepare to move j towards i . however. C B G I L N M H 62 ILLUSTRATING C . But having 'sorted' one letter. direction and condition exactly as before: C 4|nd so B on G I L N M H > swopping as necessary. C. A. and split the group into two. R. The letters to the left of i have not. The version described here is a bit different from the original but serves to explain the essential principles of the method. Hoare.AN INGENIOUS ALGORITHM Tjfhe sorting method called Quicksort was devised by Prof. I f j indicates a smaller letter than i does. it remains only to sort each sub-group. G B L I C N M H ow j indicates a smaller letter than i does. and swop the arrows i and j as well: C B L I G N M H 5 ^— t i (jontinue moving j towards i <j[ which now means stepping rightwards instead of leftwards ]). unttl j reaches i : 6 I L N M H C B 4\t which stage it is true to say that every letter to the left of i is at least as small as the letter indicated: every letter to the right of i is at least as big. been sorted.

Temp. Way = l .-*f 7]. Pointers[i] = Pointers [ j ] . 4: CONTROL 63 . Type some letters & press Return/ GBLICNMH &1 til 3--*H BCGHILMN _ i the program as shown above. ++n ) Pointers [ n ] = n . Pointers [ j ] = Temp. !Way . Last). ( Letters [ n ] = getcharO ) != V . Way = ! Way. void Qsort ( int i . here we use integers to introduce the concept. k. for ( k = 0 . n .Way. home-made pointers */ •include <stdio. for ( n=0. k < n . if (Way == Letters [ Pointers [ i ] ] > Letters [ Pointers [ j ] ] ) f Temp = Pointers [ i ] . printf ("\nType some letters and press ReturnW). Qsort ( i + 1 . return 0 .h> char Letters [ 100 ] . Qsort ( 0 . ++k ) printf r % c " . Try 'ut tensio sic vis/ /* QSORT: Quicksort. ( before ) I sorting \ 7^ 3^ M C5] 2 ' M G* C7] 5 - &] L3] w 14- Si-71 otherwise return without doing anything int First =j Last = j . i . then rearrange the pointers. while ( i != j ) Temp. C language has special facilities for handling pointers but these must wait until Chapter 10. <^^g^t>al arrays int Pointers [ 100 ] . econdLy sort these '"X- statement goes: JV-'> JV+1* JV-' -S^ \ ^ -s thirdly sort these int main ( v o i d ) int n . Qsort (First. Letters [Pointers [ k ] ] ) .i ) .4 \ tidy way to sort is to point to the entities (j( such as personnel records j) to be sorted. int j ) if ( i < j ) 4--->M 5--*C5] 6 --K6] M 7 .l ) .

The digits for base 32 should be: 0123456789ABCDEF6HIJKLMNOPQRSTUV (f only as far as F for base 16 etc. These a r e : [0] to deal with the leading + or . use the program on Page 63. converting it to a decimal integer (} of type long D .sign. For example. then add the current digit. [ 3 ] to deal with any other character (J an error J). [ 2 ] to deal with a space character. Write a recursive bubble sort function.We-program 'Areas of shapes' using the logic of a switch statement in place of if. The 'case' associated with valid digits should multiply the accumulating result by the number base. 64 ILLUSTRATING C . Make it treat subsequent entries as numbers expressed to that base.else. Hint: Store these as characters in an array. or row. . Let the program treat the first number it reads as a number base. Write a test-bed program to read octal numbers from the keyboard and display their decimal equivalents on the screen. You should find the result simpler and tidier than the program on page 55. then calls itself to deal with those above and those below.. ]). To test it. to read an octal number from the keyboard. Your state table should have four columns. first replacing the Quicksort function.then. Simply 'bubble' one number to the top of the list. then call the bubble function recursively to deal with the list below. add the array subscript to the accumulation. i^/rite a function. TJhe Quicksort algorithm 'sorts' a single item. using a symbol-state table.. [ l ] to deal with any digit from 0 to 7.. . when accumulating a number. Allow a preceding + or . The value in each cell should comprise a label (f for use in an associated 'switch' statement ]) and the number of the next 'state'. You can apply similar logic to the bubble sort described on Page 19. Ijjxtend your octal number program by making it read numbers to any base from 2 to 32. 8. the program should read -74 and get the result -50.

a linker. TJfhe preprocessor is described in detail. the composition of a macro. the use of directives. a compiler. Qtorage class is explained. . and whether objects and their contents evaporate or not when control moves on. and the use of macros for textual substitution and conditional preprocessing. The significance of storage class specifiers in different contexts (£ outside and inside function definitions ]) is carefully explained TJhe chapter ends with an explanation of name spacer the contexts in which different entities given the same name would clash. 4 \ C program is turned into an executable program by a processor comprising a preprocessor. the use of storage class specifiers to establish the scope of an object or function.TMfhis chapter describes Hie organization of a C program in terms of translation units and files. its logical passes.

substitutes pieces of text. The linkage of variables depends on their 'storage class'. For each 'text file' o f C language the compiler generates a corresponding 'object file' o f executable code. l / h e linker deals with cross references. TJ*he final result is an 'executable file. a subject described in detail below. int MyFun ( float f ) •include <math.LINKER 4 \ C program may be all in one file or shared among several. the logical process or preparation is best described in terms o f multiple passes made by three distinct parts of the processor.' 66 ILLUSTRATING C . it simplifies and rationalizes spacing. TJfhe compiler translates C language into code the computer can obey directly. removes comments.PREPROCESSOR . At the end of this stage. int main ( void ) { declarations statements /J program of i (two translation j > units. preprocessor compiler linker TJhe C preprocessor resembles a word processor.COMPILER . links all invocations to the functions invoked.14 #include <math.h> int MyFun ( float ) . j . #define PI 3. extern int i . copies nominated files into the program. cross refers local and global variables. I t copies the executable code of invoked library routines into the program. declarations and function definitions. int YrFun ( double ) .h> int i = 0. Cross references between functions and between files are left open at this stage. The contents of each file is called a translation unit and comprises a set of directives. MYFILEl / \and MYFILE2 ) f declarations statements int YrFun ( double d ) declarations statements MYFILEl MYFILE2 Although some modern processors prepare a C program f o r execution in a single 'pass'. translation units contain nothing but C language.

punctuator [] token keyword name constant string operator punctuator • • • • • if A_4 01 "abc 11 += trigraph / » ) J < > # \ A [ ] 1 { } TJ*he C processor does the following things. punctuator is defined below. For example. A directive begins with # as the first non-blank character on a new line. I t obeys each directive in turn. I t replaces each comment by a single space. I t concatenates adjacent strings. These are the indivisible atoms of a C program. I t rearranges white space such that each token is minimally separated f r o m its neighbours. \ n (j[ as seen in ' \ n ' or in printf C'\nFinish") j). The need f o r \ in this context is explained later. thereby 'splicing' successive lines. I t replaces escape sequences in character constants and quoted strings with equivalent single codes. Macros are described in subsequent pages. Escape sequences a r e summarized on Page 197. (J Trigraphs enable users of equipment based on a seven-bit character code to implement ANSI C. effectively in the order below: listed It replaces each trigraph with code for the single character it represents. All forms of token except punctuator have been introduced in other contexts.^) VJherever \ is followed by a new Mind the\ Mind therapist line the preprocessor removes rapist both the \ and the new-line character. Thus ??< is everywhere replaced by a left brace. The directives (j[ all defined below j) a r e concerned with textual substitution by macro.SIX LOGICAL 'PASSES Tjfhe preprocessor works with tokens. removing any space between them and removing redundant quotation marks: "inks Pi" "rates" t ^ > "Methinks Pirates" 5: ORGANIZATION 67 . gets replaced with the code for new-line generation.

("%fM.# define #undef 4 \ name in association with a useful value. I n general. replaced by 3. This expression returns the absolute (i. Put parentheses around the text and around every argument within it.( i + + ) : (i++ ) ) causing i to be incremented twice on each execution. i j n this program (J which reads the radius of a circle from the keyboard and displays its area on screen ]) PI is a constant used in much the same way as an initialized variable. it terminates at the end of the line.14 not if part of a longer token such as PIPE 7 J H not inside quoted strings such as "Ratio P i " not in comments (jf all of which have been removed at this stage J). #define ABS(x) These are names in parentheses following the macro's name and the opening parenthesis. ( i++ is equivalent to i = i + 1 ). V f h y all the parentheses? Wouldn't ( x < 0 ) ? . #define PI 3. the preprocessor meets #define PI 3.x : x suffice? No. From that point onwards no further substitutions are made f o r PI. ^ . The cursor jumps to the next line and you continue typing. &r ) . y / a t c h out f o r side effects! ABS ( i++ ) would expand into (( j++ ) < 0 ? .14 #define XXX return 0 . j) are substituted for each single occurrence of XXX. is called a macro.( a ): ( a )). G8 ILLUSTRATING C . or useful piece of program. £^ the same holds f o r '#define X X return 0. positive ) value of the number held in variable a. except that three X tokens (J return and 0 and .e. Try with ABS(3-7) which would become ( 3-7 ) < 0 ? -3-7 : 3-7 and return -\0 instead of 4. Before the compiler ever sees PI. ("%f". but the preprocessor 'splices' what you type to the previous line as illustrated earlier. (J So what if the cursor reaches the edge of the screen before you have finished typing the text f o r substitution? Press \ followed immediately by Return. no space here 2f our macro may have arguments. Here is a fourth exception.14 f o r each occurrence of except in the following circumstances: r ° #define PI 3.14 to be substituted f o r each occurrence of PI throughout the file *& except f o r the three circumstances noted. : (x)) 4f\fter the definition of ABS(X) the preprocessor might meet a term in an expression such as ABS(a) for which it would substitute: (( a ) <0 ? . however. the text for substitution may be of any length. ]) 4\s explained above. substitution ceases when the preprocessor meets #undef PI. P I * r * r ) .14 and substitutes 3.14 causes 3. int main ( void ) f j — 'replaced by re urn float scanf printf XX X ^ r r.

the preprocessor subsequently met OYEZ ( Aster. the preprocessor takes the argument literally. removed. For the setting shown.(B)) ( A B S ( ( A ) . But be careful! My system goes berserk if it meets leading or trailing \ or unbalanced " ({ \Cat. the preprocessor re-scans to satisfy unmatched names (J notice that ABS precedes NEAR_EQL but TOL follows ]). if NEAR_EQL is to be used in main ( ) then ABS. I f #define OYEZ(A.' But here we are in dangerous territory. #define TOL 0. Cat\. operators: # # # 'string-izer' paster l\f # is placed in front of an argument inside the substitution text. concatenates arguments. In this example. NEAR_EQL ( 1. printf ("Cat" V Adjacent strings are always concatenated.00i TJfhe NEAR_EQL macro returns 1 (fr true )) if its arguments have nearly equal values. subsequently met PLURAL (Cat) it would expand it to ).RE-SCAHS FOR UNMATCHED NAMES Macros may invoke each other: #define ABS (X ) ( ( X ) < 0 ? -( X ) : ( X ) ) #define NEAR_EQL((A). all participant macros must be defined ahead of any context wanting to use it. Tjfhe \ and " in the actual argument are replaced by \ \ and \ " respectively. if the preprocessor •define PLURAL(P) printf ( #P"s" ) . However. TOL and NEAR_EQL must all be defined ahead of the definition of main ( ). enclosing it in quotes. and so should be treated literally. otherwise 0 (j[ false J). Ij^ that invoke one another may be arranged in any order.2345. see Kernighan & Ritchie and the manuals for your particular system (| or experiment boldly )) „ 5: ORGANIZATION 69 . if one macro involves others. and contiguous »" so the effect of PLURAL ( Cat ) would be printf ("Cats"). PLURAL ( Cat\nip ) is replaced by printf ("Cat\nip") without an accident over the \n. C"at * TJfhe preprocessor's 'operator'.2349 ) would return \(^true J . ##. The criterion for 'nearly' is set by the value associated with TOL. 1. B) printf ( "A##B" ) .( B ) ) > ( T O L ) ? 0 : 1 ) . ix ) it would substitute 'printf ("Asterix"). For example.

H #define int Print int Post #define int Pick PI 3.h.h > standard header file named stdio. the #include line tells the preprocessor to replace that line with the entire contents of the file nominated. yf tidiest way to show prototypes is to make a header file for them and include that header file (J #include "MYHEAD. In the case of printf() it is stdioJi. 4\ of • • • • header file is typically an ordinary text file that contains a selection the following in any order* definitions of constants (J #define PI 3.H int main ( void ) { __ i^n general. 4/ou may start a program as below. Then you need not worry whether the processor meets an invocation before having compiled the function invoked.h.H ]) are useful for keeping a program tidy as it grows. double. its #include "MYHEAD.14 CMYHI ( char c. Its first line then gets replaced by the contents of the #include < stdio. ABS(X) ((X)<0 ? -(X) : (X)) ( void ) . But what if the processor met k = Pick() before having seen and compiled the definition? The answer is that you should already have shown the processor a prototype of Pick(): a prototype contains all information necessary for compiling the invocation k = Pick().H" second line gets replaced by the contents of the header file named MYHEAD. D #include lines nominating similar files (j[ #include "YRHEAD.m a d e header files (j( such as MYHEAD. Similarly. The processor knows these facts if it has already met your definition of Pick() and compiled it. float. int i float. and the limitations of allowable syntax in names of files. Defining PI once only is better than defining it separately in each rile. See local manuals for the precise implications of <name> and "name". ^ organization of files and directories. are available at every C installation. depends on your implementation. and what type each argument should take. etc ^ the function should return.H" J) Standard header files. Name it MYHEAD.14 1) definitions of macros (jj[ #define ABS(x) ((x) < 0 ? . j j e . ) you have to know which standard header file contains its prototype.# include /jjere is a home-made header file. an ANSI C processor will compile an invocation (Jf such as k = Pick ( ) ^ only if it knows what type of value (f int.( x ) : (x)) ^ function prototypes (f int Pick ( v o i d ) . To make printf() available. The usual place is ahead of all functions defined in the file. More imoortantly.H" j). if the name is in quotes it means the header file is in the same directory as the program being processed or in some other nominated directory. When your program invokes a standard function ( for example printf ( " H i " ) . If the name is in pointed brackets it means the file may be found in the usual directory for standard header files. double ). ILLUSTRATING C . such as stdioh and math. place #include <stdio.h> somewhere ahead of the function in which printf ( " H i " ) occurs.

#if expression sequence of lines *#elif expression \ sequence of lines #else none ort more #elif sequences none or sequence of lines one #else #endif sequence ijfhe preprocessor will deal with no more than one sequence of lines.e. expressions and lines to achieve conditional preprocessing.H here. In every case the preprocessor ends by jumping to the line after the obligatory #endif. True signifies that the processor has already met the definition of name in the forni: # define name text ^ * TJfhe preprocessor coerces all its Boolean values to long int (j( lL. and that's the first sequence encountered whose associated expression evaluates as non-zero ({true]).'defined e) •define Pi 3. Logical OR A* #if (. 5: ORGANIZATION 71 . don't include sizeof or a cast or an enumerated constant. If all the #if and #elif expressions evaluate as zero (j[ false 2) the preprocessor deals with the sequence following #else £ ^ but in the absence of an #else sequence the preprocessor does nothing. 4*\nsi C offers two directives. TJhe composition of expression is restricted to simple constants.141593 r ^ ~ ^ ^ •define e 2. It has the form: defined ( name ) defined name or #if . which you may use in place of #if in macros such as those illustrated above: #ifdef name is short for #if defined name #ifndef name is short for #if .'defined MYTAG #define MYTAG put contents of MYHEAD.718 \ set both #endif leither unset 44n expression may involve the special 'operator' exclusive to the preprocessor. #elif means 'else if'. 01 )).'defined Pi) || (. f diagram shows the required arrangement of directives. #ifdef and #ifndef.H" #define YRTAG #endif and takes the value lL ({i. unity expressed as a long int p if true. they will be processed only once #endif #if .'defined name TJfhere are no corresponding short cuts to use with #elif. 01 if false.'defined YRTAG •include "YRHEAD.l/ou can make the preprocessor deal with some sequences of lines in your input file and ignore others according to the conditions encountered during processing & such as including a file only if it is not already included.

'defined MyTag #define MyTag • #elif . #define name replacement • #define PI 3. Each directive must be on a line of its own (j( possibly extended by \ ]) preceding the program it is to modify. integer J • #if .h > • #line 22 MYFILE (diagnosticsj •define name( name ) replacement #undef name pff something currently definea % •include •include #line " file 4r^ ftLe name as ^-^ ^ allowed by .14 • #define FAHR(cels) \ C ( ) (9Mcels)/(5)) • #undef FAHR • #include "MYFILHED" • #include < stdio.PREPROCESSOR Tjfhe following diagram summarizes the syntax of a preprocessor directive. < file > (operating system) * ^ file* constant number —^——^-^ #if expression -^preface conditional.the parameter being replaced by the actual argument 72 ILLUSTRATING C .'defined HerTag #define HerTag • #ifdef YourTag #undef YourTag • #ifndef MyTag #define MyTag • #endif #elif #ifdef #ifndef #endif expression preface name >orefacey name preface where replacement token ( replacement ) f 'string-izer' fa parameter name preceded by # is expanded to] >a quoted string .

its precise behaviour depends on the installation. so auto declarations are seldom used tj^eans auto. whether a global object is global to one file or all files. const static means it is constant. plus a hint to the processor that it may store the variable in a fast register (J at the cost of being refused access to it via an address j). specifier or both: float f. TThe significance of each storage class specifier depends on the context or the declaration. 'static' means the object and its contents are to be preserved when control leaves the current block ijfells the processor to look for a full definition elsewhere outside the current block or current file -5* and extend its scope to the current block or file. and optionally supply an initial value. and so on. much simplified: m . auto int i = 6* int float int k 88 j. const qualifier 4\ny declaration qualified by const volatile should be initialized « because the processor refuses to permit a auto specifier subsequent assignment to the object. S t o r a g e class specifiers say whether an object should be remembered or allowed to evaporate when control leaves the current function. const float pi = 3. a . j . register static extern 1. Such definitions may be preceded by a qualifier or storage class int i = 6. Qutside all functions: 'static' means the object or function can be accessed within the current file only Cstatic) \*J^S~^ (ex\ern U^ # block. so consult local manuals about its b purpose and possible usefulness. 5: ORGANIZATION 73 . whether a function is accessible from all files or just one.1416. b. Objects declared inside blocks are auto by default. Here is a summary. c P. 3 . register either directly or indirectly. extern jfhe volatile qualifier has to do with 'optimizing compilers'.THE BEHAVIOUR OF OBJECTS IN DIFFERENT CONTEXTS TJfhe simple declarations illustrated earlier declare the type of a variable._eans the object evaporates when control leaves the current block. This subject is covered in detail in following pages.

This assumes the object is not hidden: visibility' is explained later. v^/bjects declared outside function definitions are maintained throughout the program's run. file TJfhe scope of an object defined without a specifier runs from the point of declaration to the end of the same file. • I f the linker finds a unique definition of the item it treats all tentative definitions as redundant declarations int i. by extern declaration. There may be any number of tentative definitions throughout the program provided their types do not clash. An 'extern i ' in another file would not be associated with this static declaration. An 'extern i r in the same file would refer to the same i . ILLUSTRATING C 74 . int • I f the linker finds no unique definition it treats all tentative definitions as a single definition initialized to zero (| or zeros j). extra scope of i \ f h e scope of an object specified as static runs from the point of declaration to the end of the same file. \^ extern int i . nle-3 1 int i = 0. Tjfhe 'scope' of an object is the region of program in which statements may refer to that object or change the contents of that object. Each extra scope runs from the point of extern declaration to the end of that file. file TJfhe scope of such an object may be extended to other files. In an outside declaration 'static' means private to the current file. r^—•• i. fibe-t lj\n outside declaration without an initializer is a tentative definition. They are said to be 'global/ Global objects provide a useful medium of communication between functions. or another region of the same file.RELEVANT SPECIFIERS: static & extern S^/utside' means outside all function definitions.

ijn a prototype declaration the 'extern' is implied by default. J rf^global^n int i = 3 . It is unnecessary to write a prototype following a definition. Global i becomes 'invisible' in the scope of local i . l\n a deeper nested block you can hide the current scope of local i with an even more local i ^ a n d so on to any depth. together with corresponding access functions.0 \^Z picks upj e x t e r n int i . its scope running from the closing brace to the end of the file. whose definition is elsewhere. 4 \ block instead of a semicolon denotes a full definition of Func(). where no other functions can see them. df In this example we use 'extern' to make global i hide local i in the same block. Encapsulation is a vital principle of OOP (object-oriented programming). The prototype declaration declares that statements between here and the end of the file may invoke Func(). int FuncC void ) .44lthough cxn object may be 'in scope' it may nevertheless be hidden by the scope of a local declaration inside a block. extern implied by default jemicolon denotes a prototype "declaration. would be enough. In the example here. scope of Func() (the scope cannot be extended to other files) —i 75 5: ORGANIZATION . ^^flo^cL { ^T (hides global7) float i = 0. This feature is useful for 'encapsulating' information. not in the scope of Func() ^-^» --^__^-—>—-""—^- int Func ( void ) { block scope of not in the scope of Func() Func() (the scope can be extended to other files by extern^ TJfhe scope of a function may be kept private to the file in which it is defined by declaring the definition static. picks 'up) global if ^-^^^ picks up\ y i = i ^^rjy not in scope of Func() extern int Func ( void ) .

> /initialization o f auto objects. extern int i = 6 . U 'dynamic'. . f extern int Func ( void ) . > 44 register variable behaves as an auto ' variable except that 0) you hint that storage in a fast register would be appropriate. f int i = 2 * j + k. extern 44n auto object. is —. If the linker finds no such definition of Func() in the current file it assumes the definition is to be found in another file (J disregarding any declared static ]).static int F u n c ( v o i d ) . evaporates together with its contents when control leaves the current block. If the linker finds the outside declaration 'int i = 6 . It says that statements in the same block may invoke Func(). ' l\f the linker finds a unique definition program. it assumes exists elsewhere ^ in another file belonging to the would be a valid definition of i .—. static. { register i . f static int i = 2 * sizeof ( int). therefore it may involve only constants and sizeof. ^. and (ii) whether the processor takes the hint or not. 76 ILLUSTRATING C . { extern int i = 7 . looking and behaving like assignment. / 4\n extern declaration in a block makes the linker look first at outside definitions in the current file.—. (J 'int i=6f another file would own file. TJfhe initializer of a static object is evaluated at compile time. You cannot declare a function static if the prototype declaration is in a block. register. is a prototype declaration. they don't evaporate. ANSI C forbids taking a register variables address. j) no outside definition of i in the current file. but 'static int i f in be ignored because that particular i is exclusive to its l^ecause extern says that the object or function is defined outside the current block fli whether in the same file or another ]) it follows that an object declared 'extern int i ' will not evaporate when control leaves the current block. ' it takes this to be the i referred to by extern. If it finds an outside definition d( beginning* int Func(void) {'or'static int Func( void){']) it takes this to be the FuncQ referred to by extern. The same would apply if the linker found a static definition like 'static int i = 6 . _—- { Objects declared static are maintained throughout > the program's run. { int Func (void). auto. whether declared auto explicitly or by default. • f static int i .RELEVAHT SPECIFIERS. ijf ou cannot initialize an object declared extern anywhere. { extern int i . whose definition is outside (J in the same or another file \ The linker looks iextern by default first in the current file. or register variables.

3. int Func( register int i ) J f int Func (int i . int j . 4 \ parameter of a function may be a function. ^ object i and its contents evaporate. z*r. — ->^ _jt^ / When Func() is subsequently invoked FuncO is subsequently invc from elsewhere (J[ say as x = Func ( 2 * 3 ) .parameters are intrinsically auto objects: don't specify auto. /. Lookup (sqrt. j) object i gets initialized to 6. (Switch(B. ANSI C forbids taking the address of a register variable using & i o r by indirect means. in* i. j 5: ORGANIZATION 77 .h> double Lookup ( double LibFun ( ) . and the statements of block are obeyed When control leaves the function. 6 ) . static or extern. •* (names of }< math. ^Yj match •jl l/r f exchange elements >. For full understanding you * need to know about pointers (J next chapter j) but here is an example of a function that swops array elements: void Switch ( int A []. A [ i 1 = A [j ] . z * r ) . ^ .718 ) . int k ) 5 Q n a call such as: — s s = Func(x*p. For full understanding you need to know about pointers (J next chapter )) but here is an example: int Func ( float MyFun() ) [short for (* MyFun ) •include < stdio. y*q. i processor may take the hint and store variable i in a fast register rather than a memory location. 2. Whether it does so or not.h > \ function as parameter of a function •include <math. Lookup ( log. You may assume all are evaluated before entry to Func().THE ONLY ALLOWABLE SPECIFIER IS register int Func (int i ) { C^block} } \ Qbject i is private to { block }. \ 3 & 6 of array B [ ] ) ( as follows: \ } A [j 1 Temp .3 functions i printf (M\n%f %f". 1 ). y*q. double Argument ) return LibFun ( Argument ) . 6 int Func ( float MyArray [ ] ) Or> short for (* MyArray )j ( 4 1 parameter of a function may be I an array. int j ) v /—>H int Temp = A [ i ] . you may not assume the order of evaluation of x*p.h > int main ( void ) .

float f } .INTERACTION. There is no interaction between names of labels and names of any other entities in the same function. Tags share name space and so struct Tag3 f char c. enum Tag { Red. float Sam [ 6 ] . or at the same level of nesting in any one block. TThere is no interaction between names of tags and names of other entities. unions \ At any one level all these share the same — & name space. enumeration constants. float f } . int Sim. 4\n example of hidden names on Page 75 shows how you can 'unhide' a name at outer level using extern. Green } . float Sim[4] = f l . V a g s are names used to identify different enumerations. Furthermore. int Sam = 0. Yello. 4f\ keyword (f such as float J) can be replaced by the text of a macro. and entities yet to be introduced (f viz. 4 \ goto statement specifies a name to match that of a Label within the same function. union must be uniquely named. int Hid « 3. if (Chaos) goto Labi. struct T a g l } . CLASH & HIDING OF NAMES #define pi 3. structures. defined types. Pstruct OneStruct {int i. enum Tag2 f Red. functions. Otherwise keywords may be used only as keywords. outside declarations. Labi: printf("Bad d a t a " ) . int Sam ( v o i d ) . should be mutually distinct. # arrays. Green. TJhe members of any one structure or struct TwoStructftnti. float g } . int MyFun ( void float H i d [ 3 ] = { l . In any one function all labels must be unique. names must be unique among variables. but there is no interaction between identically named members of different structures or unions. mutually distinct £jut you may use the same name at a different level of a block. But you may hide one tag with another at different level in the manner already illustrated these names for variables. unions. thereby hiding the entity at the outer level.14 TJfhe name of a macro in a #define directive gets substituted for identical tokens *z* to the end of the file or corresponding #undef. 78 ILLUSTRATING C . structures and struct Taglfint i. The only tokens immune to replacement are those in comments and quoted strings. you may not give a variable the same name as an array. 3 . Sim }. 7 } .

but you can make them point to functions as welL The chapter shows the correspondence between pointers to arrays and pointers to functions. the art of C is handling pointers. Strings are simply character arrays designed to hold words and sentences. [yecause C works on the principle of 'call by value1 you cannot return values from functions by altering the values stored in their parameters. This is a property of pointer arithmetic* the subject next described in this chapter. This concept may appear tricky at first. TJo manipulate strings you need only simple pointers. f/ you add 2 to a pointer into an array. regardless of the length of element. C programmers follow certain conventions in the structure of strings. likewise the next which analyses the structure of complex declarations. the pointer then points to the element two further along. These conventions are described. You may care to skip this topic on first reading. Pointers are closely associated with arrays* and arrays with strings. Complex declarations are easy to understand once you have felt the need to set up a data structure in which pointers point to other pointers. But you can use pointers as parameters and make functions alter the contents of the objects they point to. * and &. . with which to declare and manipulate pointers. 4*\ost pointers point to objects. The chapter spends some time on this concept. i j h e chapter begins by explaining the concept of a pointer and defines two operators. The second half of this chapter explains strings and their use.Tjfhis is probably the most important chapter in the book. but glorious when you can handle it confidently.

Letters[Pointers[k] ]). pointer and pointee are linked by address. k < 8 .234) to the variabte x thus means assigning 2. * p denotes the pointee of p. If you find the concepts confusing.e.-Af7] H Of p names a pointer variable.345 to the pointee of p (overwriting what p formerly pointed to) * p = 2.34-5 80 ILLUSTRATING C . Pointers Letters Q w Ul EJ Ds] [?] 14~ B 0. The following statement causes the letters to be printed in order: for ( k = 0 . *p 1. 1. Page 63.234 Ijerminology: When a job is advertised. On the same linguistic principle.THE SPIRIT OF C TJfhe idea behind pointers was introduced in the context of sorting. the one who appoints is called the appointed The successful applicant is called the appointee. persevere! They Decome beautifully clear when the penny drops. ljjehind the scenes.345. ++k ) printf ("\n%c". 732G N M 5. *p denotes the object currently pointed to by p. TJhe term * p (J the pointee of p ^ may be used like the name of a variable: means assign the pointee of p (i. Z. let the object indicated by the pointer be called the pointee.AX2J L I C y u t this is too clumsy for C which has special variables and operators for handling pointers.

int * ptrcon.! or 'the value oF pointers to. (Qualifiers apply to the nearest rightwards entity. to say 'the address oF. int * const const coptr = & x . their pointees being of type char. Here is the picture that says it all: instead oF x can write *q\ 7 float x. y. coptr is a constant (| initialized D pointer with an integer pointee. STRINGS 81 .. the pointee oF p is oF type FLoat TJhe first declaration establishes x and y as variables of type float in the usual way. pv[ 0 ] to pv[ 5 ] (f all pointers D. In other words p and q are intended for pointing to variables of type float. * q .. 6: POINTERS. TJfhe above declares an array of six elements. The second declares 'pointer variables named p and q. float * p .345 you can access the content of x via the pointer variable as TJfhere is no further need to depict absolute addresses.Tjfhe address of an object is denoted by the object's name. of which the pointees are of type float. Tjfo declare a 'pointer variable you tell the processor what type oF object you intend to point to. 2. char char * pv [ 6 ] . ARRAYS. the pointee of ptrcon is a constant integer. preceded by ampersand.! the address oF x is denoted &x to x by assigning & x (jf you need not know it's 1024 J) to c^ thus: = &x.

B ) . \^thatofv[m] v[m] = v [ n j . a copy of the contents of B into j . /jjere is a block of 'in-line' code to exchange the values held in a pair of variables. No good! The trick is to employ pointers as parameters and swop their pointees. 82 ILLUSTRATING C . char j ) TJhis one is no good.Temp !/«—v^— ( in-line code\ void Swap ( char i. ^*tTr~ r T^rh/pe of Temp to ^match char * Temp = v [ m ] . the first nominating the array and the other two the subscripts.g. And suppose you invoked this function as: Swap ( A. then return. This function (J which exchanges elements of an array of pointers to char ]) might be invoked as: void Swop ( int * j . v [ n ] = Temp. int * j ) void Exch ( char * v [ ] . & B ) . 3 stored in B. It would then swop the contents of i and j . ^Juppose your program had 2 stored in A. *y"he above function may be invoked with addresses of array elements as arguments (j[ e. The function manipulates copies only. Tjfhe processor enters the function assigning the address of A to iff which makes i point to A j and the address of B t o j (f which makes j p>oint to B j) The pointees of i and j are then exchanged. Swop ( & p [ i ] . TJhe processor would enter the function. assigning a copy of the contents of A into i . int n ) . & p [ j ] ) D or you may write a swopping function that has three parameters. int m . Parameters in C are called by value.USING POINTERS TO COMMUNICATE WITH FUNCTIONS VIA THEIR PARAMETERS 4 j \ common requirement in programming is the exchange of values held in a pair of variables or array elements. lj*he function on the right may be invoked as: Swop ( & A. i and j . leaving the contents of A and B undisturbed. (ijow about a Function for swopping values? 1 int Temp 1 - s 1- j =.

j ) .h > void Qsort(char * [ ] . Letters [ 100 ]. for (i=<0. int) prototypes void Exch(char * [ ] . i < n . Qsort (p. int main( void ) { int i . chars on pv [ n ] = & Letters [ n ] . Last = j . This arrangement keeps the sorting algorithm separate from the details of comparing and swopping. STRINGS 83 . return 0. i . POINTERS AS PARAMETERS re is the sorting function from Page 63 re-written with (i) prototypes to allow functions to be assembled in any order^ (ii) an array of pointers (f a pointer vector \ instead of making do with integers. char * pv [ {00 ]. Qsort ( pv. Comp () would be more compLicated if it compared words rather than Letters 6: POINTERS. Last). (iv) a function for comparing entities.. Letters [i] ••- A c [2] #[3] • - [41 •- E D B = ABCDE int First = i . #include < stdio. *p[j] ) ) append function Exch () shown at the foot of the opposite page j +« (!Way . n-1). Temp = i .Comp ( Exch ( p. n. char ) . int. while ( i != j ) ^^eTooTofthis page for Comp if ( Way .PROTOTYPES. Return. i + l . j Way = !Way. int Comp ( char a. ++i) printf C"%c". int Comp ( char. Way= 1.Way). ++n ) { j stops reading} Letters [ n ] = c. By writing replacement Comp ( ) and Exch() functions you may use Usort (i unchanged except for the type declaration ^ to sort objects of any type.l ) . p[i]. Qsort (p. i « j . int). ARRAYS. First. Temp. int. char b ) return a > b . * p v r i ] ) . (c = qetchar() ) != V T . printf ( "\nType some letters & press Return\n") for ( n = 0 . POINTERS. i . c. (iii) a function for exchanging the contents of array elements. 0.

printf ( " \ n % .45.23. & a [ 0 ] ) . 4. the '3' signifies the third element. however. 3. ^ than that! Instead of a [ 3 ] you may write * ( a + 3 ) (J the 3rd element beyond the pointee of a J . * ( a + 3 ) ) . printf ( " \ n % u % u " . & a [ l ] . the elements behaving like variables. & a [ l ] . To locate a [ 3 ] or b [ 3 ] the processor compensates f o r length. printf ( " \ n % i " . or with pointers. 11. * ( b + 3 ) ) \ZJn a typical installation an element of a [ ] (J type float D would be twice as long as an element o f b [ ] (f type int j). In one case the '3' signifies three times the length o f a float.67 Ijfip array is treated as a named 'pointer constant' pointing to the initial array ebement. Behind the scenes. 23 2 •34 3 . 4jt follows that instead of writing a[0] you may write * a (J' the pointee of a ]). 13 } . printf ( " \ n % i " . 12. the processor takes care o f types and their lengths. 84 ILLUSTRATING C . printf ( " \ n % i " .34. 2. printf ( " \ n % i " . b [ 3 ] ) .5G 5 . & a [ 0 ] ) .&a[0] yields 1 whatever the type o f a. \ ^ / h e n y o u work with a r r a y subscripts. in the other it signifies three times the length of an int.45 4 . Here is a fresh way to depict arrays: float a [ ] = { 1. TJhe same applies to * ( a + 3 ) and * ( b + 3 ) . 2 f " .56 } . whatever the types o f a and b. int b [ ] = f 10. sizeof ( float ) ) . a[i] ).AND A FRESH LOOK AT ARRAYS were introduced earlier as named patterns of subscripted elements. 2 f " . & a [ l ] . subscripts of arrays are handled as pointers. Similarly * ( b + 3 ) f o r b [ 3 ] . printf ( " \ n % .

) /or objects^ 6: POINTERS. positive or negative: float * q .2f ". NULL./£\ corresponding example using pointers in place of array subscripts would involve the terms & * a and & * ( a + l ) . Header file <stddef. Tjhe number of elements in an array may be found from: sizeof arrauname f sizeof ( type ) * ^ ? \ X ^ ^ ~ ^ — More neatly: ^ ^ sizeof arrayname t sizeof arrayncuve I' 0'] ^ - - - -^ rparentheses essential For types. The result is integral and it could be large. printf ("\n%. q [ . ^-A I 1. a [ 5 ] .2f". ign: (array a I'] is on p = a. 3 is a simple example or an integral expression _he constant 0 (J zero )) may be assigned to a pointer-variable to signify that it is unset. I^Jut the converse is meaningless: Constants.h> offers a zero constant. 6 7 Ijiointers into the same array may be compared using >. N g e subscripts are allowed provided they remain in bounds. . p ends up pointing to a non-existent element. printf ("\n%. for indicating unset pointers. * ( p + l ) ) .23 2 . 4fou may subtract (f never add j) pointers that point into the same array. ==. being independent of the length of type a. / which cancels itself out. by definition. >=. 5 6 5 . & * ( a + l)is the same thing as a+L It follows that & * ( a + l ) . * p ) . At that stage * p would be undefined.& * a is the same thing as 1.h> offers the special type. 4 5 4 .2 ] ) . for T^a. But the '&*' says 'the address of the pointee of . != etc. are constant: 4 f ou may apply integral offsets to pointers. prtdiff__t for declaring variables in which to store such differences. 3 4 3 . ARRAYS.~p<<rr5T++p) f printf ( '%. Inception: The pointer is allowed to point just one increment beyond the last element.2f". j u may assign the value of a pointer-constant to a pointer-variable of compatible type: float * p . So & * a is the same thing as a . STRINGS 85 . q = p + 3. In the following example. The header file <stdio.

consider each number as a polynomial in \0. mentally shunting it leftwards past the top number. Furthermore these terms are the only terms in the same power of \0 (j( but not forgetting the carry from above ]). carrying all the working in a cool head. then start writing down the answer. TJhe trick is mentally to reverse the bottom number. At each shunt multiply only the digits lying beneath one another. #define OP 35 \ As set opposite. giving a product as long as 10 digits. 4 x lo 3 -f6 x id1 + 7 x JO1 + 8 * iO l ma 5x 9 = 45 5 x 10° 6*9 = 9 x 10° + 135- Tjhe program opposite automates the method or multiplication described above. When fed up with it. the program can multiply terms as long as 35 digits. J use the program type two numbers separated by an asterisk and terminated by an equals sign. digit by digit. 4675*389= 1818575 11111111111111111111*20000000000000000000=] 2222222222222222222200000000000000000000 7x3= Zl i j h e program offers another go. hold down Ctrl and press C (J or whatever it is you do on your particular implementation to abort a run ]). Write down the last digit of this sum and carry the rest into the next shunt. In every shunted position the products of terms lying one above the other yield the same power of 10. 86 ILLUSTRATING C . The entire process is depicted down the right of the page. summing the products. Write down a long multiplication such as this. from right to left. TJfo see how it works. Then press Return.g. It can cope with any reasonable length of multiplication by adjusting the constant OP \e.MORE ARRAYS: MORE FUNCTIOHS WITH POINTERS AS PARAMETERS T^naze your friends.

r sum += a [ m ] c [ n-k ] = sum % 10 sum /= 10. ^gp^f ignore non-digit return — r . — if ( m <= i && ( k . int a [OP]. ^^/--~v->^ if (sum) ^^*^(Final carry c[++n ] = sum. ( Ch = getchar() ) != Xit. j . ' * ' ) . return subscript oF Last digit Tjfhe function for reading the operands terminates on the character you specify as the second parameter. char). for ( k = n.h > •define OP 10 int Read_Op (int *. j = Read_Op ( b. 6: POINTERS. n. < ^ K not zero while ( n + 1 ) ^^*printf ( " % i " . m>=0. m. sum = 0. b[OP]. •^pointer S to int] int Read_Op ( int * p ./* Any-length rnulhplicohon */ •include < stdio.] ) . int main ( void ) long in* sum. — k ) for ( m = k. else — r . thus if the function reads a seven digit number (J 0 through 6 jj) the function returns 6. k.V . return 0. for ( r = 0 . c[OP + OP] int i. n =i + j . STRINGS 87 . The function returns the subscript of the final digit. ++r ) ^ ^ if ( Ch >= '0' && Ch <= '9' N p [ r ] = Ch . i = Read_Op ( a. ARRAYS. k>=0. while ( i ) { prototype of Read-operand Function printf C " \ n " ) . c [ n . ' = ' ) . Ch. It reads the digits into the array pointed to by the first parameter. char Xit ) int r.

double Argument ) return LibFun ( Argument ) . 16 ). see the depictions opposite. return 0.h > ^^^dou^^ #include < math. 'LibFun is a pointer to a function returning a double. Lookup ( sqrt.718 ) ) . you follow the same pattern as for numerical parameters. With parentheses as shown it reads: 'LibFun is a pointer to a function that returns a double. () binds tighter than * ) TJfhe parentheses around * LibFun are needed because ( ) binds tighter than *. #include < stdio.YOU MAY CARE TO SKIP THIS ON FIRST READING TJhe demonstration program on Page 77 is reproduced below. When you invoke Lookup ( ) you provide the name of an available function as an argument in place of the dummy parameter. in our case LibFun j 1 LibFun is a pointer pointing to . In essence..999896 7 'necessary parentheses..' fou may find the concept easier from a different point of view: double ( * LibFun X ) The full declaration *I9H1 Igllllj This shape signifies a pointee (fsomething pointed to]) This part of a pointee identifies the pointer of the pointee. ijfhe program shows that one function d[ Lookup() D may have another function (f LibFun ( ) {) as a parameter. y u t 'double LibFun()' is actually an allowable shorthand form of: double * LibFun )\ (() signifies 'function * (which has unspecified (arguments) returning . Without parentheses this parameter would parse as double * ( LibFun ( ) ) which says 'Function returning pointer to a double'. an array name is a constant pointer to the beginning of that array. The concept of array names is similar.000000 0.' ( ) This shape declares a function that returns a double. int main ( void ) f printf ("\n%f %f".' double I £}o a function name (J sqrt or log in the program above J) is Q constant pointer./) 1 4.. Lookup ( log.h > ^^^-^^^^^^^-^-^ double Lookup ( double LibFun ( ). 2. 88 ILLUSTRATING C .

log and anti-log. fl FUNCTIOH& Ij4ere is a demonstration program to take the concept a step further.1155 3. P names an array of pointers (j[ function names J) to library functions. int i . for E n t e r a 4.v a l u e : 1. This nominates an array element The pointee of any element P [ i ] is double ! P [1 ( ) . Given a number. 7 ^-^L double library ' _ he data structure is depicted _ p functions h here. &v ) . #include < math. ARRAYS.8708 1.h>. log/exp } . Implied parentheses are shown <3ahere. printf ("\nEnter a + value: " ) . STRINGS 89 . . double ( * P [ ] ) ' ( ) = { sqrt. These are library functions with prototypes in <math. the program prints its square root.2528 33. a function that returns a double. etc declaration analysed below array initialized with function pointers ( i. each of which points to a function (? having unspecified parameters j) that returns a double' 6: POINTERS. function names ) double r.5 return 0.\x\\ f ( double d ) .h > int main ( void ) contains prototypes Rouble sqrt (double ) . scanf ( " % l f " . . P is an array of pointers.h . v .e. TJhe complicated declaration may be analysed in the manner shown opposite: double ( * P [ ] ) ( ) double ( • ( P [ ] ) ) ( ) Mind the precedence! [ ] binds tighter than *. #include < stdio.

analysed as a 'parse tree': double ( * double functions which return doubles zre is a data structure involving arrays of pointers to arrays: P X _ * i L U L<t>1 [11 [21 •- Wl [11 [21 [31 [41 [5] 0 0 [31 [41 151 0 0 0 0 [<Pl [11 [2] 'irregular' A "tree' <t> 0 999 ijfhe demonstration program opposite shows how such a structure may be set up. Here it is again. 90 ILLUSTRATING C . The structure may be described by analogy with a tree having a root. Tjfhe program shows how to access a particular leaf from each junction on the path from the root.YOU MAY CARE TO SKIP OH FIRST READING Jj± complex declaration is illustrated on the previous page. branches and leaves. then by linking pointers to addresses. Notice how the expressions for access suggest and reflect the array declarations. first by declaring the arrays.

C * ( *o[6] ) [] ) [ ] . both v and r [ l ] point to the same place. 6: POINTERS. printf ("\n%i". arrays of int l\n the expressions for access to the same leaf (J which mirror the declarations of pointer vectors j) climb back from leaf to root by replacing each local array name with the pointee from the previous level. ("\n%i". s [ 0 ] = &w. v [2 .. ( *s[4] ) [ ] .#include < stdich > int main ( void ) f J/3 implied by \initializer. r [ 0 ] = &u. Follow this on the diagram apposite: printf printf printf printf ("\n%i". int int int int u [ 6 ] . printf ("\n%i". a[H] = & r . arrays of pointers to. v [2] ( * r [ l ] ) [2] C * ( *a[a] ) [1] ) [ 2 ] ( * C* C* p ) [0]) change subscripts access any other Leaf |ere is a 'parse tree' for the declaration of p: inf ( » ( * ( » p is an unadorned pointer to. an array of pointers r p ) [ ] ) [ ] ) [ ]. ("\n%i". to.. printf ("\n%i". STRINGS 91 . w [ 2 ] .. ("\n%i". 0. o [ l ] = &s. 999 }. v [ ] = { 0.. Pr . r [ l ] = &v. so replace v with the pointee of r [ l ] . ri printf ("\n% return 0. (*r[8])ri. For example. ARRAYS. ( * ( * ( *p ) N ) [] ) []. sizes of ait arrays must [be specified or implied by ] initializer p = &a. * r f l ] ) [2 ( * ( * a[ 0 ] [ [l] ) [2] ( * ( *p ) 10} ) [ l ] ) [ 2 ] )..

g ) } . ijfo initialize a string. The same result would be got f r o m char D i s c o [ 7 ] = "Pop 20". 'p1. V . Use the escape sequence \0 to represent the internal code of zero. Advantages of this approach are demonstrated at length later. the computer would store them as binary numbers. a likely result being the loss of the z e r o marker. \fhat character do we use for the marker? Disco [41 [51 TJfo appreciate the problem. Disco \fhen working with character arrays it is useful to append an extra element to mark the end of the array.THE USUAL FORM OF A CHARACTER ARRAY Ij4ere is an array of characters initialized from a list of character constants: char Disco [ ] = { P . Disco 4HP array of characters terminated by a zero marker is called a string d or string array D. Disco\\0] = "Pop 20" would create a string with zeros in the extra elements: [01 Ei] C21 [3] C41 LSI Z6J 171 [8] LSI Disco P 2 [0 | \0 92 ILLUSTRATING C . not '0' (j[ which has an ASCII code of 48 D but an internal code of zero. 2 . Y. Many implementations represent characters by their ASCII codes. ' '. consider how characters are represented inside the computer. counted to 7\ automatical! [spaces are4 V significant \0 appendedJ • automatically* TJhe z e r o marker is included in the count. '\0* } . C offers the following short cut: J char Disco [ ] = "Pop A 20" . ]) i j h e answer is to use zero for the marker. $ I have shown ASCII codes as decimal numbers. char Disco [ ] = { 'P\ V . [02 Cl] [21 [31 . o . But char Disco[6] = "Pop 20" is an error. p .

AHY STRIHG IS CONSTANT char * p . Gig = Disco. [flf LU [2] T3] [4] [si re] [ T | 0 IP 1 )2 Ifl l\0l (j^rograms which manipulate strings typically declare a set of string arrays. ' A ' Disco [ l ] += 'A' . where the string currently in each array may grow to a length of 80 characters $ and its terminating '\0' J. each of adequate length. f [•Jut you /ray change the contents of elements in the array provided you do not try to extend it. D i s c o [a] = T .POIHTER IS A CONSTANT. L01 111 121 m 141 151 161 T\0 |P /Teservecf^area of lnemory POINTERS VARIABLE.g. Disco [ 0 3 Ci] 121 L*>1 LA] LSI 163 T 0 P 2 0 T U M 6: POINTERS. ARRAYS. t<t>i r n m [3: u i Disco Jpointer i >pcnncer constant) an > string array] PIOIP | ^ * If ou may not assign to a constant: Disco = p . STRING IS MALLEABLE char Disco [ ] = "Pop 20" . Gig[2] = ' 0 ' to change " TUNE" to " TONE" J) the outcome would be undefined. t[8l]. * Gig = " TUNE" .V . * c j . Disco [ 2 ] +« 'A' . ^ L y u t you may freely assign pointers ({including pointers to constant strings]) to pointer variables: p = Gig. STRINGS \0J 93 .V . An example is : char r[8l]. s[8l]. string pointers p and a can point only to characters they point nowhere at present Gig is initiaLized to a constant string 4i|though you may find it possibbe to alter a string constant (j( e.

"Too many sides". array private to ErrCode |glr|e|o|t|e|r| |t|h|o|n| 0n0 94 |n|i|z|e|d| |clo|d|e|NP| ILLUSTRATING C . There should be a zero marker at the end of the string.call to the printfO function (J defined in <stdio. p. %f. Mess[n] ) .. "Unrecognized code" int s = sizeof Mess / sizeof Mess[0] ..1. There is also %s for the substitution of a string defined by its pointer: printf ( "%s TO %s". printf ( p ) .) or error messages em addressed to the user of your program: int ErrCode ( int n ) static char *Mess[] = Bug . n .h> J) takes the form: prHf ( siring TJhe string contains as many descriptors as there are expressions following.. "Tuesday". % i : %s! . printf ( Gig ) . Yprintf would look for an extra ^argument to match each % NO NEED FOR EVERY ROW TO BE THE SAME LENGTH /It is sometimes useful to store a set of constant strings such as names of days of the week ( "Monday". Gig ) . n = ( n > s | | n < o ) ? 0 : n . But wherever a string is demanded. %c. So far we have met % i . printf C^-rror No. you may provide either a literal string or a pointer to a string. 4Jjl examples of printf have so far shown string as a literal string (j in other words in quotes ]). r CAREFUL' ^ if Gig or p contained %. return 0 . "Should be greater than 1 .

STRINGS 95 . and setting up a pointer vector ^ terminated by NULL ^? as depicted below: /MIMIC Caps tabs argc [T] argv [ T ] jl is a program that lists the arguments corresponding to its command-line parameters. Irish? No. char * argv [ ] ) while ( — argc ) printf ("%s\n".CATERING FOR OPTIONS WHEN YOU RUN THE PROGRAM ijfhe way to set a C program running depends on the implementation. char * argv [ ] ) Tjfhe processor parses the command line into strings. I can't. then press Return. MIMIC ^J^Tl command) 4 \ program may be written that demands (Jf or will accept as an option ]) extra information in the command line: ^-^^^-~\ MIMIC Caps tabs command) line TJfhe manual that explains how to use such a program might define the allowable command line by a syntax diagram like this: MIMIC I v -CAPS L/C-J WABS-^ T| r ijfhe options are automatically handed to function main() provided that you give main() two parameters: the first is of type int. change --argc to* I argc— and change \^^rgyto*a MIMIC Irish? No. ARRAYS.h > int main ( int argc. Typically you type a command nominating the file in which the executable program is stored. the second is an array of pointers to char. excluding the name of the program file: # include < stdio. the pointee or the augmented argc fto list the full command] \line. recording their number (j( at least one )) in argc. I can't. Conventionally these are called argc and a r g v [ ] respectively: int main ( int argc. * ++ argv ) . 6: POINTERS.

j any number of these between va_start() and va_end(). ' the ellipsis denotes an {^unspecified number of) ^^^\arguments_^^01^ xamples of invocations (J each with a different number of arguments ]) are: printf ( "\nThere are %i lumps weighing %f grams". The header file <stdarg. name of the argumentpointer name of Last fixed parameter in the (declaration of this function j^Iace this below your last use of v a _ a r g ( ) va_arg ( ap. lgo\x can write functions such as this. (%i says the < first argument \will be an int parameters for the two extra arguments expecti printf ( "\nAnswer is % i " . —^v l/irst declare a pointer to the list of extra arguments f this ahead of your first use of v a _ a r g ( ) a special pointer type va_start ( ap..h > va_list ap. Each invocation of v a _ a r g ( ) returns the next extra argument and treats it as having the type you specify. in which there is at least one fixed argument followed by an unspecified number of extra arguments. The tools are described below: •include < stdarg. n. . count ) . n ) .. ) . int ) . 96 ILLUSTRATING C .h> defines a tool kit for retrieving the extra arguments.%<smm Tjfhe printf() function is defined in Chapter 7 as follows: int printf ( const char *. w ) .

each occurrence of % in the string signifies the expectation of a corresponding extra argument in the list that follows. return 0. ^ (2. 1. Count ) . make ap point to the first extra argument ( after count ) ypick up each extra argument in turn . STRINGS 97 . two and one extra arguments respectively. Tjphere are three distinct ways of telling the function how may extra arguments to expect: • • As in the example above. printf ("\n%f". For example. ARRAYS. ya_Ust double Sum=0 j ^ ^ O ^ va_list ap. Furthermore.treating it as a double* ' Ijijere is a test-bed for the function. l.. 3. ?• rs AdecLare ap as pointer to. Mean(l.) tells what type the expected argument should be. %f. (\n%f. and that is to convey the number of extra arguments you supply: 2prototypes of va__arg () etc. n < Count. ++ n ) Sum += va_arg ( ap. There is no equivalent of the 'argc' and 'argv parameters of function main(). 6. use one of the fixed parameters as a counter. Mean (4. 1. double ) . or Use the idea found in printf(). #include < stdarg.h > #include < stdio. the style code ( % i . terminate the argument list with -1 and watch for this signal when reading them with va_arg(). Mean (2. va_start ( ap./jjere is a function to compute the arithmetic mean of its extra parameters. int main ( void ) argument for fixed parameter printf ("\n\n%f". va_end Cap). and what the type of each will be.5. %s etc. return Sum / Count. ) f . et aL The last fixed parameter is a string. or Let the final extra argument act as a marker. You can handle a range of distinct types with a switch statement having a different v a _ a r g ( ) for each case. if all arguments should be positive numbers.6) ) . y y now you should have spotted a fundamental weakness in the argument-retrieval scheme: you have to tell the function how many extra arguments to expect. for ( n = 0. It has only one Fixed parameter. . • 6: POINTERS.7) ) . printf ("\n%f". scanf ( ) .h > double Mean ( int Count.2. It is tested on four..

Irrt ) . the second nominates the termination function. new line. For example: int Punctuators ( char t ) { return ( t . set of functions which nevertheless covers most of what one needs. I n other words it gets the next line of input: int Lines ( char t ) return (t=='\n'). 4 ) . then to t f h read read and ignore any remaining characters in that string * e.5 Tjhis is a function f o r reading strings typed at the keyboard.Ti i 4gp example of a call is: KeyString ( ps.V ) + ( t « f ' ) + ( t . in * ^String ( char * .f). i j h e third function ( below ) terminates the item on reading new line only.V ) + (t-f.H 3 I . others are different (f particularly the one f o r reading strings from the keyboard ]) . semicolon. I si\g>T7 XT1 ignore leadina spaces. int Spaces ( char t ) return (t==' ' ) + (t==An'). Spaces. in 12] 1 \fh\ch serves to read and . InK). Janette 3.. J 98 ILLUSTRATING C . then to g e d up to four characters into the array pointed to by ps. The ANSI C library offers about thirty string-handling functions that cover everything one would want to do. 'tte' in Janette J) . 7 v:.A SET OF FUHCTIOHS FOR MANIPULATING STRINGS 4j\ of programming is concerned with strings... the third specifies the rnaximum number of characters to be stored in the receiving array ( the 'significant1 characters ]) . Some resemble functions in the library.rm T?. cjtrings typed at the keyboard may be terminated in the usual way \\ whitespace J or by any other characters you care to List Name a function and list your selection.g. zjhe above causes termination on tab. jf first parameter of KeyString ( ) points to the array into which the string from the keyboard buffer is to go.. but smaller. The function below terminates the item on reading a space or new line only. Here we develop a similar. space.

This function is useful specified truncation in /* TEST BED FOR KeyString */ #include < stdio. char String [ 81 ] . s = p + length . 5 ) . int (*) (char). *p = \0./ * READ NEXT STRING FROM KEYS * / int KeyString ( char * p . } return 0 append KeyString(). N ~ ^J short for (*TermFunc)) constant in stdio. With DOS systems you hold down Ctrl and press Z. getc( stdin ) ) && c != EOF) while ( ! TermFunc ( if C D < s ) return EOF signal *p++ = c. • y is a little test bed for demonstrating the KeyStringO function. int Punctuators ( char ) . Tjhe screen responds: I Note. Finish with EOF. stdin ) .h signals end of file getc( stdin ) ) && c != EOF) c ungetc( c. EOF is what you get if you read when there is nothing more on the input stream to be read. and) call to KeyString Tjfype other sentences. printf ("%s\n". Punctuators. while ( 1 ) i= KeyString ( String. int TermFunc ( c h a r ) . run it and type:. and press Return. To try the test bed. return 0 if OK . while ( TermFunc ( ^ ^ ^ ^ — . ARRAYS. int length ) inr c \ char * s .h > int KeyString ( char*. 6: POINTERS.h > (f in several processors it takes the value -1 J). int main ( void ) { int i . if ( length < 1 return 1. if C i == EOF ) break. return (c == EOF) ? EOF : 0. int ) . EOF is a constant defined in < stdio. STRINGS 99 . Consult your particular manual on what to press. to input for next getc(') to read] TJfwo features of this function need clarification: • ungetcC) causes the nominated character to be 'pushed back' on the nominated stream (J in this case stdin ]) to be picked up by the next getc().1. String ) . With every processor there is a way of sending EOF from the keyboard.

P . excluding the \0 element. . int StringLen ( char * P i } char * c L . A NOT FOR EBCDIC: Returns 1 if c is a capital. . ^ ^ t ILLUSTRATING C . return 101 [101 /* ANY CODE: Returns i if c is a digit. ^ p » v . For IsVowelO a static array is initialized at compile time and scanned on each call. . LENGTH EXCLUDING THE NULL 7J0 compute the length of a string. The length of string. char * p . c is a letter. ^r^^^jtort for*p /* \p while ( * p && ( * p != c ) ) ++I e[A[a|r[irololU|uMl == c . = TJhe next two functions work for any code. otherwise 0 * / int IsCap ( char c ) f return c >= 'A' && c <= 'Z' . stopping when its pointee is \0 (jf false ]) . while ( * P ++^ » return p I \original) ++ adds / i y to p after\ ^ the test r p ih 111 131 CA3 l«l ^^ b c |\d | ""V—V—N. otherwise £i * / A NOT FOR EBCDIC: Returns •* int IsLetter ( char c ) Ir return IsCap(c) || ( c :>= 'a' && c < V ). otherwise 0 * / int IsDigit ( char c ) return o . otherwise 0 * / N int IsVowel ( char c ) static char v [ ] = "EeAaliOoUu". Then increment the pointer. EBCDIC code would require some complication.ijfhe following two functions work for ASCII code in which letters are numbered contiguously. take a copy of its pointer. is 1 less than the difference between the augmented and original pointers. c o V . /* A Y CODE: Returns 1 if c is a vowel.

t—i 111 [21 C3l 141 E5] [61 [71 [83 IC jpjx | Y | Z ! W 1 \ 0 ] M Span. p( ^ t03 EH P I void StrCopy ( char * p. L. simply copy pointers thus: q = p . L. stopping when the pointee of p is '\0'. But sometimes copying pointers will not do. R ) . to another location. void Middle ( char * n. COPY A PART. char * right ) leff[ •—1— \a i blc if ( * left ) f while new * new ++ = * left ++ ) right [ r?step back) {over \0J new ]d e f 19 Ml 0 n i b c d e f ) g |\<z>| while ( * new ++ = * right ++ ) i 6: POINTERS. char * q ) /j)pd here is an even more terse version: while Tjfhe next function copies part of a string. — — while ( Span . ++ p . A typical call is Concat (N. copy the pointee of p to the pointee of q. s—start else * n « \0 } . . You give the position of the starting character and the number of characters to be copied to the new location.Start.) n 0—»»)x \y\i * (n + Span ) = * ( p + Start + Span ) . element by element. To do this. you have to copy a string. int Start. ARRAYS. if (Start >=0 && Start <L && Span>0 ) if ( Start + Span > L ) ^Z^fif Span overlaps^end'ofA Span = L . R ) . COPY & CONCATENATE 4|f you want <\ to point to the string pointed to by p. char * q ) | while ( * q = * p ) ++ cj. the only overlapping allowed is Concat (L. " • ~n void StringCopy ( char * p. char * left. STRINGS . int Span ) int L = StringLen ( p ) .3 Tjfhe final copying utility copies two strings. * ( n + Span) = \ i ' . locating them end to end as a new string. char * p.COPY ALL. Either original string may be empty. void Concat c char ( * new. then increment both and p.

q. TJhe above would set Ok to 1 if the string pointed to by ps is to be placed above "Wilkins" in a sorted list like a telephone directory. Equiv ). It. Tl V ILLUSTRATING C . is "Twine" equal to "twine" ? And do we want to test for equality or for relative ordering ? The function Compare ( ) offers parameters by which to specify both such requirements.ONE WITH ANOTHER OR PART OF ANOTHER \fhen comparing strings. enum Logic f eq. char Uc: Cchar c. Also.a : c . Equiv } . Equiv ) . le } . One "Buzz9 tr to precede "Buzzltf" but the criterion is the character. according to their is less than a full would expect first non-matching "Buzz9 ft in the TJO handle case distinction or equivalence we call on the function U c ( ) shown below: /* NOT FOR EBCDIC : Returns upper case equivalent of c / * /* if c is a lower case and letter and if Mode is Equiv / * -—\. Ijiunctuation marks and other characters are ordered internal codes. for example. create two types* enum Mode and enum Logic. T j o make the parameters meaningful. and distinguishes strings on their first non-matching character. so " X ' s " precedes " X . gt. ne. *hich sets Ok to 1 if strings p and q are equal on the assumption that upper and corresponding lower-case letters are equivalent: Ok = Compare ( ps. Thus "Jones" is greater than "Joan's" because 'n' > V . gt. by the following declarations: enum Mode { Distinct. ge. s " in a sorted list. (enum Mode Th r 1 return ( M && ( c > V ) && ( c = } (Mode\ (nictinrr 2 CMode [Equiv ) ? c + <= V ) 3 'A1 . "Jo" is less than "Joan's" because V < V. JT function assumes V < V < 'c etc. eq. an apostrophe stop. In ASCII. call to Compare() might be: Ok = Compare ( p. 9 is greater than 1 so "Buzzltf" precedes sorted list ( not nice ). "Wilkins".

if ( ! * (Sub + i ) ) return q. enum Logic L. Uc ( * p. *(Sub + i & Uc(*(q + i). /* Finds first occurrence of substring in superstring /* Returns pointer to substring in superstring. C0] m n HPr M rn 12 :1 TJ*he mode of comparison d cases Distinct or cases Equiv J) may be specified as for the Compare ( ) function. int i ./* Compare two strings for equality (0). returns \ w~\ . char *Sub. if ( p >= q ) f while ( Q < p ) = { & = for(i=0.\ p [ » ^ h last position 0i 1: 2: 3: 4: 5: return return return return return return * P — * p !UcO p. I f a match is found. the function returns a pointer to the starting character of the matching portion in the long string. p = q + StringLen(q) . 6: POINTERS. NULL is defined in <stdio. or NULL char * Instr(char * Super.M) == Uc ( * q while ( * p> && *c£ && ( U c O a switch(L) case case case case case case return 0\ Tjfhe second comparing function finds the first occurrence of a short string in a long string. Uc(*p. M). Uc(*p.StringLen (Sub). M) < Uc(*q! M) <= Uc ( * q . enum Mode M) ^r~i? ensures range 0 to s) L %= 6 . match) rematch */ */ return NULL. */ /* with Equiv case ( 0 .h >. etc. M) >= M). ' *p. <J^2) r-^ ^u^fH^f/ flf no match is found the function returns a NULL pointer. ARRAYS. q = Super. M j > Uc (* cj.M). * c j .M) = Uc(*(Sub+i). char * q . enum Mode M) char * p . non-equality (l). or Distinct case (l) */ int Compare (char * p . STRINGS 103 .

this one is remembered from school days. 104 ILLUSTRATING C . Nevertheless this small program does illustrate string manipulation using a library' of simple home-made functions -a* and it's more fun than the usual examples in text books. TJhe program encodes and responds with: Isthay isay Ackslangbay! Ancay ouyay eadray itay? otnay atay irstfay. {•Jackslang is a secret language sp>oken in boarding schools. Numbers are not respected at all: 356 comes out as 35ay6 (} can you see why? )). in which case there is no fold (J itch -> itchay J). Erhapspay Jfype another sentence and press Return until fed up with it. Punctuation marks are coSered for only at the end of a word (J Backslang! comes out as Ackslangbay! 5 . A diphthong at the beginning of a word is treated as a single vowel (f oil •> oiiay not iloay. i j h e r e are checks this program fails to make. There are probably many dialects of Backslang \ also called pig Latin J)./ Isthay isay Ackslangbay/ Ancay ouyay eadray itay? Erhapspay otnay atay irstfay. e punctuation mark in front of or inside a word is x treated as if it were a consonant (J "Think" becomes ink"Thay" and Joan's becomes Oans'jay ]). Type: This is Backslang! Can you read it? Perhaps not at first. ^/ you run the program it waits for you to type a sentence and press Return. Each English word is folded about its first vowel and ay is appended \tea-$ eatay* tomato -> omatotay \ If a word begins with a vowel. Stop (I after space or new Line J) by holding down Ctrl and pressing Z (| or whatever you do to send EOF from your keyboard J then press Return. The u after q demands special treatment (J Queen -> Eenquay not ueenQay ]). It is suitably incomprehensible when heard For the first time but easy to master once you know the grammatical rules. And a sentence can only be as long as the keyboard buffer. like counting lines and occurrences of words. A trailing punctuation mark has to remain trailing (J Crumbs/ ^ Umbscray/ not Umbs!cray^% Opposite is a header file and main program for encoding a sentence into Backslang. the second vowel becomes the pivot d item -> errritayj) unless there is no second vowel. earwig •> igearway not arwigeay ]). Zj\ capital letter at the beginning of a word has to be transformed q Godfather -> Odfathergay not odfatherGay J.

Punctuators. i . i n t ) . ^X-S^-N^ .H" int main ( void ) char p [ 2 0 ] . if ( ! IsLetter (PuncMk) ) * ( p + —Length) = NULL. Middle ( fore. aft [ 4 0 ] . & PuncMk ) . if first letter is capital. PuncMk. _ _ N i ? make ^ avau / * Enigma encoder.H") them int IsLetter (char). * ^J^fmove i to first vowel if ( Qu ) " ^ — *( Qu + 1 ) * V . (. gt. int Cap./ * Header file. void Middle (char * . char * ) . "qu". STRINGY. char * ) . <3?^ append "ay' if the original word if (. (header file void StrCopy ( char * . enum Logic. * Qu. ' than a letter. Equiv ) ) * ( Qu + 1 ) « V . declaring string facilities * / #include < stdio. int Compare (char * . char * . ne. enum M o d e ) . i ) . enum M o d e ) . int KeyString (char * . (Z&ude "STRINGY. char * Tnstr (char * . i = IsVowel ( * p ) ? 2: 1. char Uc (char. j . P ) . p. p.h > enum Mode { Distinct. i n t ) . int. fore. Length-i )\^Xcopy last part and first part and Middle ( aft. mark Cap true. char * . p. int StringLen ( char * ) . aft ) .'IsLetter (PuncMk) ) ended in something othert Concat ( p. English > » Backslang */ include "STRINGY.'A . if (Length <= 2) Concat ( p . STRINGS 105 .H. enum Logic { eq.\ int IsCap (char). convert 1st letterj ^ ^ itol return 0 . set letter to lower case if ( Cap s.this is a int Punctuators ( char). Equiv } . char * .IsCapf ( * p ) ) *p += V . while (KeyString ( p . int Lines ( c h a r ) : ^^r~^~int Spaces ( char). fore [ 4 0 ] . void Concat (char * . It. yspace 6: POINTERS. 15) != EOF) Backslang encoder f Length = StringLen ( p ) . enum M o d e ) . simply append "ay " ). int ( * ) (char). ! IsVowel ( * ( p + i ) ) && i < Length. ^string utilities int IsVowel (char). p. if ( Qu = Instr ( p. <^OZ^^ concatenate Concat ( p. PuncMk = * ( p + Length -1 ) . p. "ay" ) . Length. (containing all the) int IsDigit (char). T T k V i / */ the original word was (capitalized. le } . char * . Concat ( p. now } Diintf ( "%S " . ^ ^ d e s c r ^ ^ \ ^ t. for ( . ay else for short words. append it if (Cap && IsLetter ( * p ) ) *p += 'Ar V. ARRAYS. ge. 0.

Recast the areas program on Page 55 to comprise a main program and three functions. &Cost.5. The function should return 0 if successful. or draw a parse tree. set up an array of pointers to functions as shown on Page 89. or depict the data structure with boxes and arrows. otherwise a non-zero value. This exercise involves handling strings. pointer to location for storing net cost. 4gp exercise with pointers to functions. &Tax ) \Jonvert the sorting program on Page 83 so that it sorts words rather than single letters. pointer to location for storing amount of tax. ILLUSTRATING C . Triangle ( ) reads three. To compare words. What does the declaration long int ( * ( * z [ ] ) [ ] ) O declare? Tackle it verbally. making it resp>ect numbers and all usual punctuation marks. 17. Function Rectangle ( ) reads two values from the keyboard. percentage rate of tax.95. Circle ( ) reads only one. It then calls the associated function and displays the value returned. TJfhe declaration int * x ( ) declares a function returning a pointer to int. (^ In the second edition of Kemighan & Ritchie « see Bibliography & are functions for constructing and unraveling complex declarations automatically^ Ij'age 104 lists some deficiencies of the Backslang program. T or C. Improve the program accordingly.fl \+fhen the price of an article includes value-added tax. book keepers have to break down the price into net cost and amount of tax. Set up a two-dimensional array of characters for storing the words by rows. To read the words. The declaration double ( * ( * z ) [ ] ) [ ] declares a pointer to an array of pointers to arrays of double. each row terminated with 0. Don't use a switch statement. use KeyStringO defined on Page 99. Write a function having four arguments: inclusive price. each of which returns an area. An example call might be: n = VAT( 23. R. The main program reads a letter. use Compare ( ) d( defined on page 103 ^ with Mode set to Equiv.

Related functions are described (£ fgetc(). both on the standard streams (J stdin. TJhe chapter begins with the input and output of single characters using library functions already introduced (£ getc(). putchar()]). ijfhe use of temporary files is explained l/inally. T/he mysterious format strings used in scanf() and printf() are at last fully described.V TJhis chapter explains how to handle input and output. ungetc(). Qtreams are explained. stderr ]) and on streams connected to files. These techniques are illustrated by an example of a simple utility for concatenating files under keyboard control. and how to open and close them. putc() ]) . These subjects are illustrated by an example of a rudimentary data base. Also how to rewind* remove and rename files. stdout. binary files are introduced and random access explained. . The chapter explains how to open such streams and create files on the disk. rputc() and getchar().

int getchar ( void ) . is of type int as shown by the prototypes above. ILLUSTRATING C . PUT TO AHY STREAM ljnpu\ and output of a single character has already been introduced informally. This stream is automatically connected to the keyboard buffer. yjach of these 'get1 functions returns the code value of the next character waiting in the stream buffer. int fgetc ( FILE * s ) . Qorne C compilers offer a global 'switch' by which to change the interpretation of type char to a one-byte unsigned integer. i . MyStream = fopen ("MYFILE". lyut this may cause trouble. The most common library functions are explained on this double page. All are defined and summarized in Chapter 10. however. This is the sign bit. V f fopei i » fgetc ( MyStream ) . or EOF if the buffer is empty. setting it to 1 would make the variable negative. nominate any input stream that has been created and connected to a file as described on Page 116./ 2 £ -> +127 of this kind can store any ASCII character (f value 0 to 127 ]) but cannot ( Bit properly handle characters with values 128 to 255 because these would demand a 1 as bit 0. 4^\ typical stream is stdin. int getc ( FILE * s ) . ). c = fgetc ( stdin ) .GET FROM ANY STREAM. For example: FILE * MyStream. A variable . Fhe following coerces the return value to type char: char c . allowina correct interpretation of character values in the range 0 to 255 (| typical of a personal computer \ But for the sake of portability it is wise to leave this switch alone and to treat characters as type int in all input operations. y*he return value. You may. i macro equivalent \to^getc( stdin )J Ch » g e t c h a r ( ) . Suppose your implementation treats type char as a one-byte signed integer.

They are called 'multi-byte characters'. This book does not deal specifically with them. Ifunction*. OK outside ASCII char range int ungetc ( int c. making the keyboard buffer appear as though the character had never been read from its stream. Other streams may be nominated and connected to files as described on Page 116.4w^SI C has facilities for handling characters that need wore than eight bits to encode them. int putchar ( int c ) . stdout) 'A' is equivalent to (int)65] yjach of these 'put' functions places the character corresponding \o code c onto the nominated stream. char Ch. f macro based on fputc ()) macro q to putc(c. fputc ( 241. OUTPUT 109 . n't try to 'push' any more than one character on the front of a stream. implying that if you provide a value type char. otherwise EOF. YrStream = fopen ( "YRFILE". int putc ( int c. FILE * s ) . FILE * s ) . TJypica! streams are stdout or stderr. The function returns EOF if unsuccessful. See the example on Page 99. YrStream ) . Each function returns c if successful. int fputc ( int £. stdin) . the value will be treated as type int on transmission. YrStream ). fputc ( '*'. 7: INPUT. "w" ) . For example: FILE * YrStream. FILE * s ) . Tjphis function is intended for use in cases where you cannot know if you have finished reading one item until you have read the first character of the next. The Kanji alphabet illustrates a typical requirement for multi-byte characters. You can then 'push back' this character. Tjhe function puts any character c on the front of the nominated input stream such that the next fgetc() ({ or getc() ]) to nominate the same stream will pick up character c. f he first parameter is of type int. ungetc ( Ch.

The following program displays one cycle of a sine curve: Leading width 110 ILLUSTRATING C . prefix 0 to values coded as style o . otherwise precede a negative K ~-^*+-^ number with a minus sign. .g. 1 (} wider values 2 are not constrained to this width j) * Signifies that width is specified by an int argument preceding the argument that provides the value to be printed.g. ) . Print a leading zero (f but ignore this flag if a minus flag is also present j) Minimum field width expressed as digits. f. . Left justify.tnt f printf (FILE * . a non-negative number with a space. i0. The 'specifiers' needed are common to all library functions having the letters 'printf' in their name: printf(). stderr also p (implementation dependent) ispacejlgnore if + is also present. g with at least one decimal place (![ e. const c h a r * .0 J) Prefix 0x to values coded as style x . then pad rightwards with spaces (i absence of a minus sign means right justify and pad to the left ]) + # Precede the number with + or Print values coded e. sprintf() etc. . destination stream e.g. e. TJhis double page defines f p r i n t f ( ) which sends formatted output to a nominated stream.

precision expresses the maximum number of characters to be printed. fprintf ( stdout.05 In style e or f. "\n%*c". Number of places after the decimal point expressed as digits. precision ). unsigned e. for ( i = 0 . -\. Print the entire string. fprintf ( stdout. "=%i".#include < stdio. whichever is the shorter These specify the same forms as x. as defined in the following table. L or L. optionally modified by h. &m ) . u. x unmodified h int Length L long int - L _ short int - double int long double - unsigned short int unsigned Jong int i. 123456= TJfhe sequence of arguments must match precisely the sequence of specifiers in the string. code X would produce FF2A J) Single character The associated argument points to a string. V return 0. g o. In the case of a string. la (f 26 decimal D Scientific format e.h > int main ( void ) { int i . The type of each numerical argument must be compatible with its associated style code.g. double rad = 3. "l23456%n".g. When the type of an argument fails to match its associated specifier the result is either crazy or non-existent. The asterisk works in the same way for precision as it does for width. -123 Decimal integer. unsigned e. extending field width (J if necessary j) to accommodate. i+=20 ) fprintf C stdout.g. but any letters involved are printed in capitals (f if code x produced ff2a. (int) ( sin ( i * r a d ) * 35+ 4 0 ) .141593 / 180. e.g. 123 Octal integer. Le signifies a long double to be printed in scientific format. code (styie) d. -123.g. d u o x e f 9 X.g.g. OUTPUT 111 .G \ Decimal integer e. 7: INPUT.g. e. f.12>e&&2 Decimal number e. i<=360. unsigned e. 2. g respectively. 777 ({ 175 decimal J) Hex integer. The associated argument points to an int variable to which the current count of printed characters is sent: int m. m ) .E. e. n e. i.h > #include < math.

int sscanf C const char * . ^ o use sscanf ( ) with keyboard data. address of objects matching their respective specifiers \fr\\e nothing in the format string except spaces and tabs (J which are ignored D and specifiers. That is not a practical way to read data. . '\0' is automatically appended.char * fgets ( char * . when called. If the item you type on the keyboard does not match precisely what scanf ( ) has been told to expect. Other characters in the format string would be expected to match corresponding characters of the input string &z and Murphy's Law says they wouldn't. The easiest way to do this is oy gets ( ) (j[ get string J). jxamples in this book show input from the keyboard via scanf ( ) . scanf ( ) evokes mayhem by ignoring the item. int. stdin ) . reads from the keyboard buffer into the string pointed to by the nominated pointer (J[ p in the example shown ])L Reading terminates on new line. ) . const char * . ^*^ J*>^ 1 as a buffer [junction fgets ( ) . & Nmbr ) . fgets ( p. FILE *s ) . If things go wrong you can scan again and again. 80. So if you really need the extensive scanning facilities offered by scanf ( ) it pays to use them under control of sscanf ( ) (j[ string scan format ]) as described below. lj\ is up to you to make the string buffer long enough (j[ typically 80 ]). & Chr . "%c ". . . *q fflush ( stdin ) . £| scan the string using sscanf ( ) . Do not use scanf ( ) for practical programs. specifier space tab 112 ILLUSTRATING C . char p [ 80 ] . The new-line character itself is stored with the string. \^^. first input a line as a string. n = sscanf ( p.

whichever happens first.g.g.n e. 0xla Decimal number e. 0.i. and coerced to the type of the receiving variable as tabulated below \e. The string is terminated by '\0 f on meeting a whitespace character or achieving the count. octal. -78 Integer: decimal e. (f This is a matter of particular implementations and is beyond the scope of this book. -78.f. %s implies %bigs where big is a large number. hi = short int J basic code d.x unmodified int float unsigned int Length modifier h L short int long int double unsigned int unsigned long L long double d i e. hex e.g. -12. The F or N signifies a 'Far' or 'Near' pointer to override the default format.g.g.u.g. OUTPUT 113 . then skipped ])• You may specify a field width beyond which the next specifier takes over (jj[ 456 processed by %2i would be int 45. +L2E-6 Unsigned decimal.^) The input string is encoded according to its associated letter.3.x c Decimal integer e.g o. octal e.f.o. leaving 6 to be resolved by the next specifier in the string ) . interpreted according to the specifier. %7s reads non-whitespace characters sequentially and stores them as a string from the given address.g u. Integer count of successfully read characters prior to meeting s n 7: INPUT. Not an ANSI feature. I or L. then discarded (? % * i as the first specifier would cause the first item from the keyboard to be treated as an integer. 077. optionally modified by h. implementation dependent. hex integer respectively %6c reads next 6 characters (j[ including whitespace J) and stores them as an array from the given address.specifier} % * digit also p (implementation t skip dependent) width (max) pointer Length The characters associated with a 'skip' specifier are read from the keyboard buffer. \<ti is not appended %c implies %lc.

0 . modify IsLetterO on Page 100 if you want it to be. l^ecide what characters are to behave as terminators.0 -1234. you simply cannot know what you may get and have to deal with. Typically these are space* tab and new Line* but you might wish to add comma* colon* semicolon It depends on the kind of program you are writing.000000 3 H2SO4 0. -i = GetNext ( p . Underscore is not included. Assume the one called Punctuators ( ) for the example opposite. Otherwise read on. How often do you need to read numbers in scientific format? Or in octal or hex? I f the answer is 'Often!' use sscanf ( ) .real 3 .1 2 3 4 . £J[ow consul! the return value of GetHexL This value tells you what was found in the keyboard buffer as far as the next terminator: 0: 2: neither number nor name a decimal number l: 3: a whole number a name 4f4 'name' is here defined as a string of letters d( and optionally digits ]) that starts with a letter. . It does not matter what sort of value you expect \ the person at the keyboard may have typed it wrongly anyway. address of a double to hoid value if numerical Assuming tab.000000 0 2B||!2B 2.000000 1 -1234 2 -1234. what it found'I .name EOF . newline & semicolon as terminators. 4jl\ numerical result is stored in a variable of type double.not number\ or name 1 . Specify your chosen terminators in a function having the form described on Page 98.000000 . Up your program.1 2 3 4 .integer 2 .000000 0 Me4# 0. space. 2B||!2B 1 1 4 1 call to GetNextQ says: 'Get the next item from the keyboard and show me what kind of item it is ' 114 ILLUSTRATING C . get the next item by a call to GetNext().error) & m ) . five calls to this line would produce results as follows: ^c^^ all *P ^{terminated'} m (with \0] -1234.TO USE WHERE sscanf() IS UHHECESSARILY CLUMSY gets() and scanf() is a clumsy way to handle keyboard input if your need is to read only simple numbers and words. H2SO4 Me4$.

break. . 7: INPUT.H" int main ( v o i d ) char w [ 8 0 ] .int GetNext ( char *p.* ) 1 0 + for ( ++r . break. Chaos printf ( " return 0. IsDigit ( *r ) . double m. case 0: printf ( " "). int i . decimal. &m ). if ( Sign == '-' ) (*n) *= -1. name } . break. + + r ) to char after ± if ( V r ^ * . infinite Loop.0 • for ( r = Sign ? p+l: p . case 2: printf ( " Decimal " ) . char Sign. ++r * n += ( * r . double Frac = 0 . double *n ) int Status. return Status. * r . if ( Status != EOF ) the four possible values of Status • 'Ignore characters the 15th after) '-') ? *prNULL. else starts with if ( IsLetter (*p) ) while ( IsLetter(*p) || IsDigit (*p) ) p Status ! * p ? name : string. puts ( w ). OUTPUT 115 . try this with the input \ l i n e shown opposite/ simple driver to demonstrate GetNext c . Value =%Lf\ n ". enter EOF to get out while ( l ) { i = GetNext ( w. Letter and comprises Letters & digits lyelow is a driving program with which to test GetNextCX include "STRINGY. Sign = (*p point * n = 0. enum { string. 15). printf ("\n"). switch ( i ) { case 3: printf ( " Name ").V ) / ( Frac *= 10 ) . String case i : printf ( " Integer " ) . m ). if ( i == EOF ) break.0. integer. if ( ! * r ) Status = Frac ? decimal : integer. IsDi(jit( * r ) . Frac=l. Status = KeyString X p» Punctuators. break. M default: printf ( " ).

The name must have been declared as a pointer to FILE. "w" ) .DOC". const char*. V \ stdout ) ijfhis name nominates a stream in the same manner as stdin nominates a stream.AND i j h e standard 'streams' are: • • • stdin stdout stderr standard input stream (J from keyboard D standard output stream (f to screen }) standard error stream (f to screen J If OKI may define any number of other streams connected to various devices \ such as printers and plotters ]) and to 'files' on disk. freopcn ( "PRNFILE. it should be possible to direct an input stream from any input device. where FILE is a type df just as int is a type D defined by C. mode ) .DOC". stream ) . 116 ILLUSTRATING C . In DOS. name redirect from stream to Filename 'ej. in a DOS environment: char *p = "C: \\MYDIR\\MYFILE. FILE* fopen ( const char * . Examples are: ''MYFILE.D0C" (J where \ \ is an escape sequence to represent a single \ JL if ou may express Filename as a pointer to a string. but the concept of a 'stream' remains independent of the implementation. freopen ( filename. const char * FILE* freopen(const c h a r * . For example: FILE * MyStream > Filename \ name" I j h e allowable syntax of name depends on the implementation.DOC" and "C:\\MYDIR\\MYFLE2. FILE * stream may be opened and connected to a file using fopen ( ) . MyStream = fopen ( p. stream = fopen ( Filename. The means of attaching other devices depends on the implementation. for example. lower case and corresponding upper case letters are equivalent and the path is punctuated by backslash. This book deals only with disk files. an output stream to any output device. mode. For example.

Close it first. otherwise EOF. in such a case you do not need fclose ( ) . Or just by rewind ( ) in* fclose ( FILE * ) . OUTPUT 117 . \^/hen you have finished with a file you should close it. The exit() function demonstrated overleaf serves to close all open files when obeyed.mode \ " r w a b + • • • v1 "wb" "wb+" may express mode as a pointer to a string: char * q = " w + b " . in * remove ( const char * ) . as explained later. it must be rewound before it can be read This can be achieved by resetting the file pointer. i = fclose ( stream ) . mode symbol r w « significance of mode symbols &> if file doesn 't exist error \ return NULL create file. 7: INPUT. but not while the file is open. q ) . or by rewind(). The function returns 0 if successful. a file has been written. or using fgetpos() and fsetpos(). i = remove ( "MYFILE. and open it for writing if nominated file exists open file for reading open file for writing open file for appending (J writing on the end D a b + declares file to be 'binary1 *& as handled by f r e a d O and fwriteCX The absence of b implies a formatted text file permits both reading and writing « using fseek ( ) and f tell ( ). or added to. void rewind ( FILE * ) .DOC" ) . Ijhe rewind function automatically clears error indicators \ see later J). The function returns 0 if successful. MyStream « fopen ( "MYF1LE". Xfx may remove $ delete j) an existing file. otherwise EOF. rei rewind ( stream ) .

using the following functions: (interrogate error indicator interrogate ^end-of-file indicator) feither function sets both indicators zero i = ferror ( MyStream ) . printf ( "Enter new path\n> " ) . old[strlen(old)-l] = V . fgets (new. r 118 ILLUSTRATING C . V ^ ^ ^ n e w name\ ^ :ause a file name may define a path. stdin). f gets (old. An attempt to read beyond the end of a file causes the end-of-file indicator to be set non-zero. new ) ) printf ( "Success ! \ n " ). clearerr ( RLE * ) : Ijvery file stream has two indicators^ initially clear (J[ zero )): • • error indicator end-of-file indicator l\f something goes wrong during an attempted read or write.DOC Enter new path >C:\Y0URS\LETTER. if (! rename ( old. rename ( ) may be used to Tnove' a file from one directory to another. "SENIOR" ) . stdin). If ou can interrogate either indicator. printf ( "Enter existing path\n> " ). 80. and re-set both to zero. open or closed. The following rudimentary utility achieves this in a general way: #include < stdio. y file. i = feof ( MyStream ) . rewind ( MyStream ) . return 0. int feof(FILE*). may be renamed rename ( "ELDERLY". const char * ) . f store this fiLe as S ^ MOVER.h > int main ( void ) char o\d[Q0\ new[80]. 80.DOC Success ! int f error (FILE*).int rename ( const char * . btrt this indicator clears itself before every attempt at reading.C Mover Enter existing path > C:\MINE\LETTER. else printf ( "Try again ! \ n " ). the error indicator for that stream becomes non-zero and stays non-zero until specifically cleared by clearerr() or rewind ( ) . new [ strlen (new) -1 ] = ' \ 0 f . clearerr ( MyStream ) .

^—> r^Y^Z^ else ^-^ close this 4 read file . fclose ( p ) . CATS NEWFILE AFILE BFILE CFILE ^commandx line name of utility /* f •name of results file ( typically a new name Jj *any number of names of existing files to r Se copied contiguously into the new filef MAKE NEW FILE FROM CATENATION OF LISTED FILES * / •include < stdio. "\nlgnore: % not found". * q . " w + " for ( i = 2 . type CATS. . fprintf(stderr. then nominate the files to be copied into the concatenated file.^ int main (int argc. argv[0] ) . For the concatenated file you may nominate a new file (j[ and let the utility create it D or an existing file (} and let the utility wipe out its current contents )). _ _ similar to return (l) but } else { fprintf(stderr.A UTIUTY FOR CONCATENATING NOMINATED FILES TO ILLUSTRATE Fopen().h > / ^ i ^ ^ r ^ 7 y ^ •include < stdlib. copy reac file to write file. for reading . if file \ J^kexists it is rewoundj ^ for overwriting if ( q » fopen ( a r g v f i ] . copy rewound ^ \ file to screen } else standard error stream made available by C fprintf(stderr. if ( argc > 1 ) if ( p = fopen ( a r g v [ l ] . OUTPUT 119 . s rewind write file k rewind ( p ) . "\nAbort: % couldn't be opened". then nominate the file you want to be the concatenated file. argvfi] ). 7 : INPUT.h > N ^ ^ J i ^ ^ . i < a r g c . "V1N0 arguments given for %s\n". char * a r g v [ ] ) FILE * p . FcLose() TJhis program is a rudimentary utility. 1 is ( if file doesn 't exist \ > it is created. c h . " \ n " ) . exit ( 2 ) . s exit ( l ) . fclose ( q ) . return 0. stdout ) . while ( ( ch * getc ( p ) ) != E F ) O putc ( ch. fprintf ( stdout. p ) . a r g v f i ] ). To run it. int i .> . " r " ) ) while ( (ch = g e t c ( q ) ) != EOF ) putc ( ch. rewindO.

RumpleStiltskin ) . defined in < stdio.h >. When the stream to that file is eventually closed. \fo\x can create a temporary file which has no filename. The only files to be removed automatically on closure of the stream are the nameless files created by tmpfile(). MyStream = ropen ( MayFly. char * MayFly = tmpnam(). #indude < stdio. 120 ILLUSTRATING C . tmpnam ( ) returns a pointer to a static array created internally. printf ("My name is %s\n". just a name to identify its stream. tmpnam ( RumpleStiltskin ) . The minimal length to allow ror this string is given by the constant L_tmpnarn. void parameter. I f you want to get rid of it. "w+b" ) . the file itself remains in the file directory. fclose ( MyStream ) . The mode of opening is "wb+" z& in other words you may write to the temporary file and read from it in 'binary' form. char * tmpnam ( char * ) . return 0. You may give tmpnam() a parameter pointing to an adequately long array in which to put the unique string. f l\f you omit its argument. BriefStream = tmpfile ( ) FILE * tmpfile ( void ) . function tmpnam() will provide a string guaranteed not to clash with the name of any other file. Leave empty i j h e nameless file is automatically removed when you close its stream: fclose ( BriefStream ) also removes * temporary fibe\ IXf you need a temporary name for a file.h > int main ( void ) char RumpleStiltskin [ L_tmpnam ] . Binary form is explained opposite.are FILE * Brief Stream. remove ( MayFly ) . use remove ( ) . 7 it is your) responsibility to\ remove the named file Tjfhe name returned by tmpnam ( ) may be associated with a new file using fopen().

size_Lsi2:e_t»FlLE*)i size_t Pread(vocd *. BinStream ). 4JJ1 streams so far illustrated are streams of characters.e_t fwr ite ( const void * . No matter how the local hardware treats such a file. A text stream comprises lines. BinStre^TT rewind ( BinStream ). or text. each line having zero or wore characters terminated by a new Line character. Size. char Record [ ] = "You'll never guess where I've been'Nn"mr oize = 36 + 1: -=•—•* <^<—^—^—^-—' ' for the fwrite (Record. fread ( PrintBuf. So the C library provides functions for writing and reading a stream of bytes regardless of what they represent. fclose ( BinStream ). then subsequently converting 2147483647 back to 0111111111111111 for processing in memory. n * fwrite ( (number of] items actually X transferred} pointer \ to K suitablej buffer] r number > of bytes S in a A record n « fread ( b. size. 7 : INPUT. stream #include < stdio. The size of any such structure is given by sizeof( type ) where type is the type of the structure (| e. sizeof (struct MyStruct ) J).h > /* JUST A DEMONSTRATION */ int main ( void ) open a stream to a temporary file record with 36 visible characters FILE * BinStream = tmpfile ( ) . ]) on the assumption that the file is modelled as just described \ you need to store a great many numbers in a file. PrintBuf ). it would be wasted effort converting. printf ( "% s \n". the binary integer 0111111111111111 to its decimal 1111111111111111 equivalent of 2147483647 for filing. size_L RLE * ).siz. binary streams are especially useful for filing data structures such as the personnel records defined on Page 127. size_t. As long as you remember what you wrote to file you can read it back without conversion. l. In doing this you 1111111111111111 might drop or pick up bits wherever binary numbers do not have precise decimal equivalents. and subsequently read them back for further processing. l. Size. OUTPUT 1 Record out to BinStrearn 121 . the C programmer may use library functions (J getc(). printfO etc. scanf(). say. precisely as it was. char PrintBuf [ 40 ]. return 0. count.g.

int fseek ( RLE * . you can locate a conceptual 'file pointer1 at any point in a file. end } . The value returned by ftell() is the number of bytes from the start of the file to the file pointer. origin ) . yfhe origin may be located at the start of the file (j[ at its first byte ]) by SEEK_SET. In the previous examples the files that have been written are rewound before being read.ero or as a value returned by ftell(). 4f may use equivalent integers or provide a less clumsy enumeration such as enum f start. But access to a file can be more selective.h > as an enumeration: JTC^ /TO r^ enum f SEEK_SET. current. The origin may be located at the current position of the file pointer by SEEK_CUR. offset. 0 ^ is depicted below: i 2 3 4 6 7 8 9 1112 13 14 15 16 17 18 19 20 21 22 offset I j h e next fwrite() or f r e a d ( ) starts with the byte at the file pointer. or write a record on the file starting at that position. The offset is expressed as a number of bytes and may be positive or negative: fseek (|f MyStream. 122 ILLUSTRATING C . long. long ftell ( FILE * ) . SEEK_CUR. (J Functions fsetpos() and fgetpos() serve a similar purpose. Location pointer yfrorr? start I = ftell ( stream ) . SEEK_END } . The pointer is located by the function fseek ( ) and you can discover its current position using ftell(). y^he offset for a text stream should be given either as z. or at the end of the file (f one past its last byte ) by StEK_END. These three constants are defined in < stdio. int ) . 13. 1 ) /T^^\ /-^"^ r v * S long / ^ int ( stream. ijfhe offset locates the file pointer relative to the origin. then read the record it points to.

h > •include "STRINGY. 97 Wentworth Avenue Who? /* PART TWO: INTERROGATE */ for ( . Dbase ) .J. . The program then asks for a surname. then another name and address. 1. 20. if ( feof ( stdin ) ) break.J. KeyString ( p.H" int main ( void ) prototypes for utilities listed on Page 105 char p [ 2 0 ] . Point. 19 ) . i . printf ( "Address?\n> " ) . 60. 2 Kingfisher Drivej Name? > Williams Address? > Mrs. KeyString ( r. fread ( p. for ( i = 0 . } return 0. Lines. Lines. Who? >Benson Mr. eq. all associated addresses are printed. ) printf ( "Who?\n> " ) . . etc. long i . FILE * Dbase « fopen ( "DBASE. 1. fread(). if ( feof ( stdin ) ) Name? > Benson Address? > Mr. A. P. q ) . p. Lines. Dbase ) . if ( Compare ( r.BIN". r [ 2 0 ] . SEEK_SET ) . 19 ) . KeyString ( q. OUTPUT 123 . 2 Kingfisher Drive Ms.TO ILLUSTRATE forite().. and so on until you enter EOF (J Cfrrl + Z in DOS J). T. enter EOF from the keyboard. 60. The program asks for a surname. q [ 6 0 ] . fwrite ( p. /* PART ONE: INPUT DATA */ for ( Point = 0 . 20. i< Point . If records have the same surname. 7: INPUT. To stop the program asking for names. fwrite ( q . Point += 80 ) printf ( "Name?\n> " ) . fseek() ((BINARY I/O WITH RANDOM ACCESS FILE } T/he following is a primitive database for names and addresses. 59 ) . When you enter one. i . Dbase ) . printf ( ff%s\n". then an address. i+=80 ) offsets jump in 80s fseek ( Dbase. the program searches the database it has created and prints a name and address. Dbase ) . Equiv ) ) fread ( q. /* PRIMITIVE DATABASE */ •include < stdio. 7 The Cottages Name? f break. A.E. 1. "w + " ) .

and make it possible to add names and addresses in subsequent runs. Let its prototype be: void Tabulate ( double Value. Make it possible to keep names and addresses in a disk file on leaving the program. 124 ILLUSTRATING C . 1 if on the next line Field is the number of character positions in the complete field Places is the number of places after the decimal (f zero signifying none. Display an error message if the number of matching specifiers is wrong. and no point \ Tabulate ( 234. 0 ) would display ssssssslte as an integer. in the form $55234. 3 ) would print the result on the same line as the previous number. 0. but attempt the following minimal improvements. Make it possible to delete and modify names and addresses. with fprintf() at its heart. With this simple function you can produce complex and elegant tabulations. Make the utility ask if you really intend to lose the current contents of the nominated file. you lose the current contents or that file without further warning. to tabulate numbers. offer the chance to retract.fi \+{r\\e a function. 0. int Places ) . arrange for a remedial line to be input by gets(). Consult the return value on each call to sscanf(). \JJonvert one of your C programs that employs scanf() to using gets() followed by sscanfQ. Value identifies the next value to be printed Line is set 0 if printing on the same line. int Line. 10. 4|mprove the database program on Page 123. man-years of effort are expended in producing saleable address-book programs. The possibilities are endless.000 (J where s represents a space j) . 10. Tabulate ( 234. TX h e concatenation utility on Page 119 is badly designed I f you nominate an existing file to receive the information. You should find error conditions much easier to handle than with gets() and sscanfC). (jonvert another C program to using function GetNext ( ) (jf defined on Page 115 ]) . int Field. Rectify this deficiency.

the syntax terms type and declaration. 4^4 structure can be handled in much the same way as a variable.ijfhis chapter explains the concept oF a structure as a collection of variables. assign to a structure. 1/inalfy the chapter explains the idea of stacks and gives an example of their use in converting simple algebraic expressions to reverse Polish notation. access the members of a structure. you can copy a structure. . this collection including nested structures if desired. fully. take the address of a structure with &. The operators for accessing members are defined and their use explained Concepts are illustrated by an example of a library list in which to search for a book if you know its title or can remember only part of its title. (^/nions and bitfields are introduced (£ a union is a structure in which members share storage space]). so a separate diagram is drawn for each context. You may declare arrays of structures. You can nominate a structure as a parameter of a function or write a function that returns a structure. TJhis chapter introduces structures by analogy with arrays. /jjaving described structures and unions it is possible to define. The allowable syntax or declaration differs according to context.

In short.[197 s E L L \0 J A C K \* K B M ME L R0 W D S D I T CH an array of 2-D arrays r wT T C H I T \0 T A 8 I T H A \0 MR S .. hence cannot by used directly as sorting keys. ]). You may define a shape to suit any particular collection of entities to be stored. A structure may incorporate any type of variable. Arrays are too uniform. a list of diseases survived. 4 T T L T NG R I D G E cAr 4 f o u could use this scheme to sort names and addresses on various keys (j[ surname. JACK 243 KENNEL ROW HOUNDSDITCH TWITCHIT MRS. And numbers. TJhese deficiencies can be overcome using a structure instead of a two-dimensional array. Xpec 101 RU S MR.4 ° f information handling is about updating and sorting lists of names and addresses. a code indicating the subject's purchasing power or likelihood of signing an order. It may also incorporate other structures (J nested structures )). I/or a list of names and addresses you could define an array of two-dimensional arrays (j[ in other words a three-dimensional array ^ as depicted below: char Xpec [i00] [ 4 ] [20]. F 0 RD RUSSELL MR. With each name and address may come other information: an amount of money owing. Xpec [ n ] [ l i n e ] ) . TJhe address book above is re-defined as an array of structures opposite. 126 ILLUSTRATING C . You might display the complete list of names and addresses as follows: for ( n « 0\ n<{00\ ++n ) for ( line = 0\ line<4. town & must have the same amount of storage allocated to it. house and street. 2A3 H0 U [99] (each string ^ \ terminated .. have to be stored as character strings instead of integers. forename. and sums of money. information comes as large sets of structured sub-sets. every item (j surname. TABITHA 4 TILING RIDGE CATFORD I^Jut this scheme has deficiencies. town etc. ++line ) printf C"\n%s".

idfleilwj \CAaLtjfLqrd\® J displaying the list involves the dot operator (j[ full stop j) for accessing each member of the structure.House 1 T. printf ( f \ n \ n % i . Town Mr. 'Members' of structure defined Xpec 'an array of 100 .W . . House.c. UNIONS 127 .n. Mr. char Street [ 13 ] .Forename .Street . Mrs. printf ( "\n\n%s ". J D9] 1 m M T4T~[ K.. This is 'CatFord' check on picture above for ( n=0. .Jack.^ . Town 14 1 m l^il^ng. 1 ra . Xpec [ n ] . n < \00\ ++n ) f printf ( "\n\n%s.Surname . .n. R. Street ) .e.Xpec [ n ] . Xpec [ n ] . 1 cm Ci] .X0 LIU ^ussjyJLl. %s ".Row. Surname. | HoundsditchN? .t.hi.l..Street .r keyword struct f char Surname [ 12 ] . Xpec [ i00 ] . . %s".Forename .structures« . Russell.^ . Tabitha 4 Tiling Ridge Catford 8 : STRUCTURES. int House . char Forename [ 20 ] .wi.Surname . Forename ) . Xpec[n]. char Town [ 15 ] .House . Jack 243 Kennel Row Houndsditch Twitchit. Xpec [ n ] .e.Town ) . .

p = & Sl . Namp 1 | 1 .Name | . Number = S2 . as described on Pages 136 to 137. } 51 = { "Mo Niker". 52 = { "Pert Ronymic". printf ( " % i fi 9 • ( * p ). or the shape declared. 33 ) . Sl. int Number . Number. • n = Fun ( Si1 ) • Sl = OtherFun ( "Jones" . • • n = Sl. Si struct char Name [ 20 int Number Sl.Number| I | v^bjects Si and S2 may be handled in some respects like scalar variables and arrays. S2. auto. S2 . S2 . 128 ILLUSTRATING C .AND UNIONS I J e r e is a declaration of a typical shape of structure along with the definition of two objects. 123 } . Si and S2. An auto structure may be initialized by assignment.Number) . You may do the following: • Initialize the members of structures in the manner of initialized arrays Declare structures static. Access the members of a structure in much the same manner as variables Copy or assign an entire structure as a unit Take the address of a structure Define functions that have structures as parameters (jf this depicts the invocation )) Define functions that return a complete structure fl[ this depicts the invocation j) struct usize must be declared i char Name [ 20 ] . extern. 987 } .Number| 1. Number.Number » n • S2 = Sl . 2/ ou may not compare structures logically if ( Sl S2 ) f i j h e above rules apply to unions as well as to structures.

AND J of the do\ operator for access to a member is demonstrated by an earlier example. n < 100. %s". Xpec[n]. Russell. Mr. So the access expression may be written: ^^—^—^—v-^ ( * ( Xpec + n ) . part of it reproduced below: for ( n = 0 . %s".Town. 8: STRUCTURES. (Xpec+n)-> Forename ) . Without the outermost parentheses the expression would be treated as *((Xpec + n ). (Xpec+n) ->House. printf ( " \ n \ n % i .a So the access expression may be written: ( Xpec + n ) -> Town [reference to object \ member name where the parentheses are needed because -> binds more tightly than + (} without them it would say Xpec + ( n -> Town ) J) . C provides the arrow operator -> (J minus sign followed by greater than J). Xpec[n]. n < 100. printf ( "\n\n%s ". V* A high 'precedence) f Low precedence djj i f h e outermost parentheses are essential because the dot binds more tightly (J has higher precedence J) than the asterisk. printf ( " \ n \ n % i . p->a is short for (*p). Xpec[n]. Jack 243 Kennel Row Houndsditch ijfhe essential shape of each access expression is: Xpec [ n ] . member name instead of writing Xpec[n] as the reference to the structure we may write: * ( Xpec + n ) TJfhis demonstrates pointer notation as an alternative to array notation as described on Page 84. %s ". T j o avoid the clumsiness of the dot expression. Xpec[n]. Street ) . TJhe fragment of program at the top of the page may be re-written as: for ( n=0. House. printf ( "\n\n%s ". ++n ) { printf ( "\n\n%s. (Xpec+n)-> Surname. ++n ) f printf ( "\n\n%s.Town ) . Forename ) . Surname. (Xpec+n)-> Street ) . (Xpec+n) -> Town ) . UNIONS 129 .Town ) which signifies a pointer \o a member of an impossible object. %s ". Xpec[n].

Subsequently ft not necessarily on the next line ]) objects of the same type may be declared by reference to the tag. d in the second arrangement because there is no tag. ILLUSTRATING C . make a struct MyTag f int Ego. b. to which to refer. b. hence no shape. * w .} YourType. d . copied. d in the same manner as a. Thus: A structure of such and such a shape comprises objects of such and such types! /<~^/~^\ -& define struct f int I d . used as arguments of functions and returned by functions. These objects may then be used much like variables: initialized. char Ripe[35]. ^declare „ . three of which are illustrated below. But with the first arrangement you may subsequently declare more objects of the same shape: ^ struct M y T a g J e. TJferminology: Excessive use of the word 'type' causes confusion. union. and establishes the shape of objects c. } c. TJfhe second arrangement is shorter than the first. I use the synonym 'shape' to avoid ambiguity where 'type' applies to a structure or union. n the above arrangement a type of structure is defined and given a tag. enumeration ]) is defined on pages 136 and 137. char Sweet[ 16]. char Ripe[35]. _ — . } . alias (J via typedef ]) is neat and avoids the need for a tag. If ou can declare an alias (} synonym J) for a shape using the keyword typedef: typedef ( struct MyTag j MyType or wore imaginatively: MyType is now an alias For 'struct MyTag ' r typedef struct {int I d . * t . It is possible to arrange such a declaration in several ways. YourType u.i j h e full syntax for declaring an 'aggregate' (J structure. pointed to. s [ 6 ] . f [ G ] . * f struct foLLowed by a tag constitutes a shape (in other words a type ) lA\ is impossible to do likewise with c. struct MyTag a. after which you may declare objects as follows: MyType r. v [ 3 ] .

"Donald Alcock".SEARCH FOR A BOOK. Equiv } . "Cambridge University Press". int Year. while ( 1 ) f-I read the { }\ search printf ("\nSearch on fragment: " ) .H is listed on Page 105 Search on fragment: fortr Title: Author: Publisher: Illustrating Fortran Donald Alcock Cambridge University Press. 1986}. 1987}. 40 ) !« EOF ) f o r ( p = List. ( p . "Cambridge University Press". {"Illustrating BBC-BASIC". "Donald Alcock". ( "\nPublisher: return on ^reading EOF\ 8 : STRUCTURES. Record_Shape * p. char Author [ 3 0 ] . "Cambridge University Press". Record_Shape. 19 82 i } Search on fragment: static Record__Shape List [ ] = {"Illustrating BASIC". E q u i O ) ( "ViTitle: %s". Lines. "Cambridge University Press". {"Illustrating Fortran". {"Illustrating C". UNIONS 131 . int main ( void ) char Buffer [ 4 0 ] . printf ("\nDatabase: Type any part of a book title t o \ n " "initiate a searcn for a took or booksAn" " (Ctrl+Z to end the session)" ) . / til} "Cambridge University Press". ++ p ) if ( Instr printf printf printf } else return 0. 1977}. 1982}. p->Author ". 1992}. "Donald Alcock". 1982}. p->Publisher. List "Cambridge University Press". {"Illustrating Super-BASIC1. "Donald Alcock". "Pan Information". Record-Shape ( & ( p -> Title ). 1985}. "Donald Alcock". j. {"Illustrating Computers". p->Title ( "\nAuthor: %s". / ^ ( seek if ( KeyString ( Buffer. {'Illustrating Pascal". "Colin Day & Donald Alcock". static int Num__Books = sizeof List / sizeof ( Record_Shape ) . char Publisher [ 30 ] . IF YOU REMEMBER ONLY PART OF A TITLE •include "STRINGY. p->Year).List) < Num__Books. STRIHGY. OR SET OF BOOKS. Buffer. "Donald Alcock". enum { Distinct.H" typedef struct char Title [ 4 0 ] .

An example. write Tab=She. 132 ILLUSTRATING C . chaining ]). Derno_Object. When you use a union you have to remember who is currently in bed. some pointers ]). Him. double Her . In the example shown here you could refer to the fields of the union named Nested_Object. The processor reserves enough space to accommodate the longest. is: "Otime" Minder 4 4 union may be nested inside a structure.Her. .Him . union char Him [ 6 ] . Nested_Object.Fido | int 1 i i i double C86ytes) .STRUCTURES THAT SHARE SPACE Ljj^ union is an aggregate similar to a structure. as: Demo_Object. which lies inside the structure named Demo_0bject. some double. Her etc. enumtlieTohe . but only with reference to its first field. Check when you 'fetch' from a union: use a statement such as 'if (Tab==She) i = Worker. else exit(i ) . Tab • 1 int 4J[n this example there are three fields sharing storage space. write Tab=He. Him[l]. using the shape defined above. (type)) Worker char (6 bytes) . Demo_Object.Her . It } Tab. thereby simplifying the handling functions (J filing. I f you assign to Worker. and so o n . The cost of this expedient is wasted space in unions that contain the smaller members. Nested_Ob j e c t . the difference being that all its fields share the same storage space. l / h e idea of 'Tab' is to keep tabs on the current type. struct Composite_Type char Title [ 40 ] . int Fido . Her. tagj } struct Composite_Type v^nions are useful for handling large sets of entities of different sizes Q some int. Nested_Object. if you assign to Worker. . union Factory char Him L 6 ] . 1 (2 bytes) 1 common bed (unjon^acj^rV) Worker . ' \foix may initialize a union. Like the married couple ^ factory workers /» who shared the same narrow bed but never slept together because he was on night shift and she on days. in this example the double. double Her r shape ) int Fido . By expressing each as a union f you may make all entities the same size.

The following fragment (J in which i . 15 unused. But you cannot know. : 1. Hearts. Tjhe colon denotes a f bit field'. v are of type int ]) does it dynamically: for ( i=s = for ( v f S < 4 . ++s ) . unsigned Suit: 2 . Value = v InPlay = 0 Deck [ i ] Deck [ i ] Deck [ i ] } Ijjow does the processor arrange the storage of bit fields? In the above example. declare unnamed bit fields to create boundaries where computers like them best 6* at powers of 2: typedef struct unsigned unsigned unsigned unsigned Value: 4 . The two-bit field represents Spades. v < 14 . Possible. ++v ) Suit = s . p bring the total to 8 bits lyit fields are useful to programmers who work at low level <&c\ose to the machine * ^ and best left alone by the rest of us. 1. static Card_Type Card_ Type Deck [ 5 2 ] . 8: STRUCTURES. Ifou can. s. The one-bit field is for representing the state ' not in play' or * in play' (I 0 or 1 ) . UNIONS 133 . Diamonds or Clubs (J 0. wasting one bit per record. 2 or 3]). Suit: 2 . Card_Type. The four-bit field can represent Ace (J 1 ]) through to King (J 13 j) leaving 0. 14. however. the method of storage depends on the whim of the processor.DOWN TO THE BASICS /jLjere is an array of 52 structures representing a deck of blank playing cards: typedef struct unsigned Value: 4 . common sense would suggest that the processor would pack each seven-bit record into an eight-bit byte. I f you want to play card games there are more appropriate facilities in C than bit fields. The integer after the colon specifies the number of bits (J binary digits J) in the field. unsigned InPlay: l . initializing the deck would be possible but laborious. InPlay: 1.

To prevent complexity getting out of hand. * PqlePt . But to make subsequent explanations dearer we use the term shape for the extended part of type: • • • • • struct struct struct union enum My Tag { float f. b. unions and enumerations. c . These are collectively termed 'aggregates/ We extend the type diagram to include aggregates. Polar c. oe t ^^^jr^^^^^^r^l^ liP* 4 may P01^ 1° ?oLar shapes 134 ILLUSTRATING C . double d } My Tag { int * p. int type signed unsigned short long char int float long void double i j h e concept of type is now extended to structures. C provides the typedef facility for declaring an alias \ in other words a synonym ]) that may be used instead of a complicated phrase: &^ typedef ^—v as aliasM • typedef unsigned long int Lengthy. e . alias for 'unsigned Long intj declared unsigned Long int) • typedef struct { double r. theta } Polar.AT LAST! WE CAM DEFIHE THE REMAIHIHG SYHTAX OF C TJfhe syntax o f scalar type is defined in Chapter 4 as : signed short — '---. struct My Tag } f long I. float f } Boolean f True = 1. Lengthy a. d . False = lj[xamples of type or shape can be more complicated than those shown. q . -^^^^d^el^^the^hape] P l P p.

the prototype may be written 'double Sine(double Angle). UNIONS 135 ./£\ declaration comprises three parts: an optional storage class specifier. Fun. a list of declarators. ijfhe syntax of declarator is formally defined as follows: declarator name ( declarator ) declaration^ — 9 name ) . In this example the names in the list of declarators are: i . An example is the prototype declaration 'double Sine(double). and in sizeof(J when finding the size of a type fl shape D. Colour [ 3 ] . IJtach declarator provides a unique name. Fun ( f l o a t ) . p. 1 para» • * f u n (int. Colour. and optionally as parameters in a prototype..' where Angle is no more than commentary. D But in type casts.' where the name of the parameter has been omitted. int) • a • *p •a[3][6] jp some contexts a declarator appears without a name. a type (J or shape j). * p . the entity denoted type-name combines type and abstractor as follows: type-name type shape abstractor • double • int [3][6] • struct T * as in void Fun (struct T*) alias 8 : STRUCTURES. For example: static int i . y n sizeof(type-name). it is essential to omit the name.. (J Omission is optional in this case. A declarator that omits the name is called an 'abstract declarator' (| abstractor for short ]) and is defined as follows: empty ( abstractor ) (function with two int parameters) returning pointer to .

integral * (number of bits)) —-* expression abstractor is for bit Reids only. • unsigned Suit: 2 . . it is not helpful to do so. GLOBAL ( OUTSIDE ) OBJECT this path for tagged shapes only declaration extern static type shape alias • int i . ILLUSTRATING C 136 . declaration auto extern register static register for scalar types only • static int n = 100. • struct Street MyStreet . k. } OBJECT IN A BLOCK .SELECT SYNTAX DIAGRAM ACCORDING TO CONTEXT 4 \ function definition and the declaration of a structure employ different symbols. The declaration of a parameter shows by its form and content whether the function is being defined or whether it is being declared as a prototype. • struct Street • struct Street {int No. MyStreet = {10. "Downing" } . nn ydere are seven separate diagrams. char * Name } . each defining declaration in a different context. f sntiaLs. So although it is possible to draw a single diagram defining the syntax of all declarations. For a particular context the general definition would not show which paths through the diagram were permitted and which forbidden. It is A mandatory for zero-Length bit fields MEMBER OF STRUCTURE OR UNION declaralion type shape declaration abstractor alias • char * Ref .

Including them would complicate the syntax diagrams out of all proportion to their worth.1415927 * r * r * r /3 . float f ) . Placement (| to the left of the entity qualified )) is depicted for const at the foot of Page 81.FUNCTION DEFINITION ( ALWAYS GLOBAL ) declaration extern static type shape alias declarator block • double Sphere ( double r ) return 4 * 3. block \ { declaration statement } PARAMETERS OF A FUNCTION DEFINITION type shape alias • int i • char * p declarator • int * f n ( ) PROTOTYPE DECLARATION declaration \ extern static V • double sin ( double ) . 8 : STRUCTURES. UNIONS 137 . PARAMETERS OF A PROTOTYPE DECLARATION declaration register type shape alias declarator abstractor • int * ( ) • int i • char const AND volatile EXCLUDED Tjhese definitions exclude the qualifiers const and volatile. The effect or volatile depends on the implementation. type shape alias declarator • void Fun ( int i.

as depicted.A SIMPLE DATA STRUCTURE WITH WIDE APPLICATION programmer's stack is a simple concept with wide application. Pop and Peep. X^*/^ 4 \ stack may be created. char c) if ( q -> pos < 40 ) q -> A[ q -> pos++ ] = c. then remove the top object 'ijake a copy of the object at the top of the stack without removing it. 138 ILLUSTRATING C . Stacks can be found in all kinds of program. For typical invocations of these. else return '\0'. Send a signal if the stack was empty. -> Afq. char Pop ( Stack_Type * q ) if ( q -> pos > 0 ) return q -> A[— q -> pos]. typedef struct int pos. char Peep ( Stack_Type * q ) Tjfhe next chapter explains how to avoid arrays (J for which you have to specifv a maximum height of stack J) by using dynamic storage. Stack_Type . -> p o s . char A [ 4 0 ] . setting it up to stack characters. -> pos > 0 ) return q. On the right of the page are compatible function definitions of Push. else return V . void Push (Stack-Type * q . at system level and in every field of application. if C q. TJhree functions are all we need to manage such a stack: Push Pop ijJlace a new object on the top of the stack i j a k e a copy of the object at the top of the stack. see the program on Page 141. from an array of stackable objects and an integer variable for storing the number of objects currently stacked. To maintain the analogy of a physical stack (J of bricks or trays ]) we draw the programmer's stack (} of numbers. Peep iyelow is the type definition of the shape depicted above. characters or structures ]) upside down.l ] .

. F = 3.F / (G + H) transforms to ABC-D* + FGH + / TJhe reverse Polish expression is easier to evaluate than might appear.ILLUSTRATING THE USE OF STACKS 4ijgebraic expressions in conventional form may be expressed in reverse Polish notation which has no parentheses (J 'Polish' because the notation was devised by the Polish logician Jan Lukaciewicz which only Poles can pronounce. So how do you transform C ) * D . C = 1. B = 4. H = 5 . operator * / precedence $(high) 3 2 2 1 + = 0 £^ that the left bracket is included in the precedence table and allocated low precedence.C that reverse Polish notation would be by computer. With these values the expression to be evaluated is: \£f ork f r o m left to right taking each item in turn. D = 2. 8 : STRUCTURES. As an example of reverse Polish notation: A + (B . Whenever you come to an operator.F / ( G + H ) i n t h e first stacks. For example let A = 6.or is a Left bracket.. Clever. UNIONS 139 ... apply it to the previous two terms^ reducing two terms to one: ^ he above should demonstrate useful f o r evaluating expressions an expression such a s A + ( B place? The process employs two A + ( B .C) * D . This is a trick to avoid having to treat explicitly the condition . the steps are explained below: Continue stocking conventionally . G = 7. 'Reverse' because his original order of operators and operands has been reversed ]).

The function shown below is given a character as its parameter and returns the corresponding integer from the little table. int Prec ( char c ) f operator precedence * / $(high) 3 2 2 1 switch ( c ) case = case ( case + case V default return 0 .dig out matching bracket as before [dig to the floor because J f the equals sign ( the \ (terminator ) is treated as A f an operator with Lowest J [precedence of all. return 1 . + ss c 0 \J the next page is a program to transform conventional expressions to reverse Polish. To use the program type the expression and terminate with an equals sign: A+(B-C)*D-F/(G+H)= ABC-D*+FGH+/- 140 ILLUSTRATING C . case '-' : return 2 case '/' : return 3 printf ("\nChaos") . see table) Up addition to the functions Push() and Pop() a function is needed to return the precedence of an operator.

for ( i = 0 . while ( ch != V ). X.A I I 1 1 17 Stack_Type. ch ). break. Push ( &Y.pos I 0 I Stacks Type L39J 10] Cll IZ1 [3] . . char ch. Pop (&Y) ). place here: Push(). Peep(). do ch = getchar ( ) . switch (ch) case (: Push ( &Y.h > typedef struct int pos.AN EXAMPLE TO ILLUSTRATE THE USE OF STACKS •include < stdio. UNIONS 141 . return 0. break. ii ii ii ii ii while ( Peep ( & Y ) != V && Prec ( ch ) <= Prec ( Peep ( & Y ) ) ) Push ( &X. ++i printf ("%c". char Peep ( Stack_fype * ) . int main (void) Stack_Type X = { 0 }. char ). K X .Pop ( & Y ) . p o s . break. case ) : I\I while ( Peep (&Y) != '(' ) Push ( &X. default: if ( ch >= 'A1 && ch <= 'Z1 ) Push ( &X. int Prec C char ). Pop (&Y) ) .A[i] ). int i . Pop(). ch ) . void Push ( Stack_Type *. printf ("\n"). Prec() case +: case -: case *: case /: case =: 8 : STRUCTURES. ch . char Pop ( Stack_Type * ) . Y = { 0 } . char A[40]. ch ).

let the user of the program specify any of the members and provide a fragment of text for the search. adopt a suitable convention & such as a match wherever a date falls within a year of the search date.l ) * 2 .i\ ** V / h a t is one third times seven eighths? Answer: Seven twenty-fourths precisely. selecting an operation i| add. Devise a test program for reading two fractions (J as two pairs of integers j).875 gives an approximate answer. Fraction^Shape } Use HCF(). subtract. 142 ILLUSTRATING C . for example. Write a set of functions to add.3 / ( 7 + 5 ) « and the answer should be 11. multiply. There is no reason to confine the search to the first member. ijfhe program on Page 141 transforms an algebraic expression from one notation to another. defined on Page 24. int Sign. Try your program with 6 + ( 4 . By contrast. Base the work on a special shape defined to contain fractions: typedef struct unsigned int Numerator. 0. When you meet the equals sign you should be left with a single number on the left staclc. etcty and printing the resulting fraction. Whenever you are about to place an operator on the left stack.3333 times 0. The left stack should be made to contain numbers instead of letters. unsigned int Denominator. the book list program on Page 131 for looking up other books or other kinds of information particular to your own field. reduces to 70/33 when numerator and denominator are divided by their highest common factor of 21 D . pop two numbers.75. then push the result back on the left stack. In the case of numerical members. to convert vulgar fractions to simpler form (J 1470/693. Change the program so that it reads a numerical expression instead of an algebraic one •&> and produces a single numerical result. multiply and divide pure fractions and produce pure fractions. that is the result of the expression. apply the operator.

TJhe concept of a linked list is introduced with particular reference to stacks.TJfhis chapter explains the shortcomings of arrays having pre-determined length and the consequent need for dynamic storage. The concept is then extended to cover rings and binary trees. [jxamples in this chapter include a program for demonstrating ring structures and a program for finding the shortest route through a road network. Finally there is a sorting program based on the monkey puzzLe technique. . The use of library functions for allocating and freeing memory is then explained.

use the library function mallocO (J memory allocator ^ whose prototype may be found in the header file < stdlib. There are many applications for which it is impossible to know the detailed memory requirements in advance. ' For practical purposes it is based on structures. where p must have been established using mallocO (| or one of its derivatives. is: void free ( v o i d * ) . A program written to use such a scheme fails only if demands on total memory exceed supply. which returns storage to the heap. Smoke 'Green ^2 struct Puff • Smoke *Gr&. We use a library function for allocating these structures. This function returns a pointer to a region of storage of a size specified by the argument of the function.Smoke. struct Puff • struct Puff struct Puff -Smoke • &rect\ • lyut you can declare shape: a member that points to a structure of the same struct Puff struct Puff struct Puff char Green.h > .n r^J •Smoke 'Green . T/he prototype of mallocO is shown opposite. not if one of many individual arrays exceeds its bounds. What we need is a scheme in which the processor allocates memory during execution and on demand. i j o create structures of identical shape it is meaningless to define a member that has the same shape as its parent structure: Bfrd struct Puff | struct Puff •Green . The prototype of f r e e ( ) . zjhe scheme is called 'dynamic storage. (struct Purry * Smoke. With good luck and management the heap should retain enough memory to meet all demands throughout execution.CONCEPTS OF DYNAMIC STORAGE & CHAINING Tfhe trouble with arrays is that the processor has to be told what space to allocate to each of them before execution starts. When a program has finished with a structure it frees the memory from which that structure was built. embellished with explanatory remarks. Bird. 144 ILLUSTRATING C . Bird i j f o create the structure being pointed to we must allocate space for it. When the program needs a new structure it creates one from a 'heap' of unstructured memory. tossing it back on the heap. To allocate space. dy storage involves linking structures of identical shape. callocO or reallocO )) . Bird.

Smoke -> Smoke -> Smoke -> 9: DYNAMIC STORAGE 145 . shape. The library defines an appropriate 'size_t' for your particular implementation and 'model' (j tiny. you may link structures in the form of a chain: BirdSmoke = ( struct Puff * ) malloc ( sizeof ( struct Puff ) ) .( struct Puff * ) malloc ( sizeof ( struct Puff ) ). if using a PC ]) . Add another link: Bird. the shape of object pointed to is struct Puff. huge. The size of object is sizeof(struct Puff) where the value returned by sizeofC) is of the shape demanded by malloc() (^namely the type: size_t J).prototype*. p. Bird. returned to heap undefined content iore usefully. cast malloc to appropriate Ijp the example opposite. jcast 'pointer to type _w struct Puff and free a pointee thus: free ( p ) . . void * malloc ( si2ie_t Uoc() Returns a pointer structured b ) .Smoke->Smoke = (struct Puff* ) malloc ( sizeof( struct Puff ) ) .Smoke 1 id so on: Bird.Green | . etc. Bird . you may create a pointee thus: p . pointing to objects of shape struct Puff: struct Puff *p. [jf you declare a pointer.Smoke -> Smoke -> Smoke = NULL .

p -> c = ch p -> next = * . 'A' ) to push 'A' onto stack X. Push(&X. * Pointer_Type. The ordinal number (J 1st. 146 ILLUSTRATING C . top /*- are is the definition of the shape of each element: typedef struct Element char c . ]) shows the order of operations needed to avoid overwriting. To depict such operations we use the notation shown here. etc. char ch ) { Pointer_Type p. 2nd.WITH DYNAMIC MEMORY ALLOCATION S n the previous chapter. p = ( Pointer_Type ) malloc J^sizeof ( Element_Type ) ) . For example. A new shape of stack is introduced below. alias for 'struct Element' l^ist processing' is the art of diverting pointers by copying addresses from one pointer variable to another. struct Element * next. stacks are xsed on arrays and have the shape depicted on the right. it is based on dynamic storage rather than an array. Elernent_Type. together with sketches of the linkage before and after the copy operations: pointer to objects of type Pointer_ Type void Push ( Pointer_Type * q . The fat arrow depicts a simple copying of contents in the direction of the arrow. * 1 = P 4 j p invocation of Push() demands two arguments of which the first nominates a pointer. Notation (flere is the definition of Push(). The copy operations are depicted opposite.

* q « p -> next . if ( * q ! = NULL ) ch = p -> c . pointer to objects of type ^^PitT' else return '\0' . p = * q . else return \<z)' . return ch . ) -> c . free ( p ) . char Peep ( Pointer_Type * q ) if ( * q != NULL ) return ( * q. (i) ORIGIHAL STACK (ii) MAKE p POIHT TO TOP STRUCTURE free (Hi) COPY POIHTERS (iv) new top RESULTIHG STACK 1/inally. here is the definition of Peep(). The copy operations are depicted under the definition together with sketches of the linkage before and after the copy operations.(i) ORIGIHAL STACK (ii) CREATE HEW STRUCTURE ( maLLoc ) j j r e is the definition of P o p ( ) . 9: DYNAMIC STORAGE 147 . No pointers are disturbed. Pointer_Type p . char Pop ( Pointer-Type * char ch .

PeepO are replaced by the dynamic versions defined on the previous double page. but their prototypes are the same as before. int Prec C char ) . char Pop ( Pointer_Type * ) .. struct Element * next. ch = Pop ( & Y ) . ^ . char Peep ( Pointer__Type * ) . / * POLISH WITH DYNAMIC STACKS */ #include < stdio. default: if ( ch >= 'A' && ch <= 'Z' ) Push ( &X. case V : case ' . * Pointer_Type. ch ) . switch ( c h ) case ( : Push ( &Y.— ' while ( Peep (&Y) ) pop and printf C%c\ Pop( &Y) ). while ( Pop(&Y) != V / * end of do-while. while ( ch != '=' ) . .do ch = getchar ( ) . void Push ( Pointer_Type * . vN N <^j^J pop TronV X into Y while ( Peep(&. p( . Pop ( & Y ) ) . Element^Type.THIS TIME WITH DYNAMIC STACKS 4 \ program for transforming algebraic expressions into reverse Polish form is given below.h > #include < stdlib.print entire Y\ printf ("\n"). ( .a. break. P o p ( ) .' is identical to that on Page 14L Function Prec() is also identical. Functions Push(). The main bop from 'do' to 'while (ch N '=').h > typedef struct Element char c. return place here: Push(). case while ( Peep (&Y) != '(' ) Push ( &X.' : case V : case ' / : case '=': while (Peep (&Y) != V && Prec (ch) <= Prec (Peep (&Y)) ) Push ( &X. break. break. Y = NULL. ' . Prec() 148 ILLUSTRATING C . ch ) . ch ) . . loop * / ) Element_ Type Pointer_ Type two stacks Xfoi Yfo" . Pop ( & Y ) ) . Push ( &Y. int main ( v o i d ) char ch. Pointer_Type X = NULL.X) ) ^ \ £v % reversing order} PushC&Y. Pop(&X) ) . char ) . Pop( ) f PeepO.

chains are more flexible than this.'E' ) H = H . ifraversal means referring sequentially to the elements of a chain. /* TRAVERSAL . In this demonstration. 1 H case.'R1. 'declare two working pointers\ linkage: before insertion: /* INSERT 'R' AFTER 'E' */ p = H . else p = H . l/or demonstrating the techniques introduced below. INSERTION & DELETION chain is demonstrated on earlier pages in the particular form of a stack.N N RECURSIVE */ O p = H. Assume the following chain already set up. <^j " 2nd copy i* DELETE 'E' LEAVING GARBAGE * / if ( H -> c =. 'referring to' involves printing the content of an element « the content being just a single character. p -> next * n. they have many applications. while ( p -> next -> c != 'E' ) p = p -> next • p -> next 55 P .PARADIGMS FOR TRAVERSAL. The example which follows this introduction illustrates an algorithm for finding the shortest route through a road network.> next -> next . p = p -> next. In general. while ( p ) printf ("\n%c". n -> next = p -> next. Pointer_Type p. n. p -> c ) .> next . oc: if first element cast |3. while ( p -> c != 'E' ) p = p -> next. if not first element IN \ht\ 149 9 : DYNAMIC STORAGE . we adopt the same structure (f type Elernent_Jype D as that employed on the opposite page for stacks. n = (Pointer_Type) malloc ( sizeof ( Element Type )). n -> c .

0 START\ Tjfhe data structure needed for a shortest-route program is depicted below. has to be an improvement. another for storing NodeFacts[2].Switch 0n\ value. This example is for edge 2 to 5. T—^ T/he records for edges running out of a node are created dynamically. the initial time in this component is set so high that the first feasible route. In the NodeFacts[2]. however slow.Bestime iongfune \ component named Switch is a Boolean ) NodeFacts[2]. another NodeFacts[2].Switch . In the component named Bestime is the value LongTime ri NodeFacts[2].Tip for storing the journey time along NodeFacts[2].AN EXAMPLE TO ILLUSTRATE THE USE OF CHAINS I/inding the shortest (J or longest ]) route through a network is a problem that crops up in various disciplines & one of which is critical path scheduling for the control and monitoring of construction projects. An exception is the starting node: the best time to the starting node is.Link the node number at the tip. There is a record for each nodey and a chain runs from each such record Each chain comprises edge records which store data describing all the edges which run out of that node. The record for node 2 is annotated more fully oelow. by definition. .Head. Before the process can start the chains must be formed > » and initial values placed in the components that will eventually hold changing values. 150 ILLUSTRATING C .Route these items are explained later. i j h e shortest route is found by an iterative process. A switch that is On implies that the edges leading out of that node must be explored (J or re-explored )) .Head.Head .Head. Uses of NodeFacts[2].Head (t a constant set to 10 m J).0 .Time the particular edge. nothing. The journey must follow the direction of the arrow.Route record for node record For edge record for edge R e c o r d s for all nodes are held in an array named NodeFacts. initially switched to On.Bestime LongTCme . The component named Bestime is to hold the best time so rar achieved to this node by different trial routes. ^ a node. 4\|l switches are turned On initially. the problem is to find the shortest route from the node marked START to that marked END. Each record has a component for storing the link. Given a network such as that below. The number against each arrow shows the journey time. / 2 .

For each edge in the chain. such references are i 5 12.Head . .Switch . data and Route from 6 to 3 -s—a_ results would be as shown 4. so the iteration is not yet finished.0 -^^^^ rzr. the faster time is substituted and the node switched £h. several things must be recorded. . r^£> Time taken is 31. To be able to trace this improved route subsequently.0 2 3 16.Bestime . The process continues until all switches are off *& in other words until a complete cycle through the nodes fails to make a single improvement to the route. So the outcome of dealing with the edge from 2 to 5 is as shown here: node . The result is compared with the best time so far recorded in the node record for the tip.edges Startnode Endnode ^ e. .Switch . as depicted for node 5 above. If the new time is better. the action at node 2 included turning On the switch at node 5.Head . .0 array.g. .Route . The array structure was chosen because node records are accessed in a 'random' way nodes No.TJhe iterative process starts at the starting node.0 ^ — change of subscript.Bestime .0 sketched opposite.Head .1 . 1 ^ ^ ^ 6 Jresults) \ here.0 (e/t resolved quickly by a simple 4 2 6. the Switch at node 2 is turned off. 2 5 8. However.0 i 6 9.Switch .0 5 \ TjVied with the network 4 6 10. the Route component is made to contain the number of the node through which the route came. then cycles the array o? node records until terminated. the time to reach its tip is found by taking the best time so far achieved at the tail and adding it to the journey time for that edge.Bestime . ijfhe node records are assembled as an array rather than being created dynamically and linked as a chain.Route l i f t e r traversing the chain of edges from node 2.0 4 5 1. These are depicted below: node . The process terminates on detection of all switches being OFF 4V each node the chain of edge records is traversed.2. when dealing with node 6 9 3 6 2 you have to refer to 1 3 10. 9: DYNAMIC STORAGE 151 .0 nodes 5 and 4 ]) .Route \^/henever a better route to a node is found. Using an i 2 5.

i . Startnode. Endnode\n"). int main ( void) Head. Nothing = 0. replace time at start node 152 ILLUSTRATING C . NodeFacts [ i ] . Switch = On. * Ptr_Nodetype. & EndNode ) . & StartNode. Edge = NULL. StartNode. ^ j array of node NodeFacts [ $0 ] . Route = 0 . scanf ("%i %i %i % i " . NodeFacts [ i j . & Edges.Nodes.Edges.h > / * ROUTE PROGRAM BEGINS * / typedef struct Edge struct Edge int double * Link. impracticably high LongTime = 1E20. f NodeFacts [ i ] . p = NULL. Try. i<= Nodes. j . Time. NodeFacts [ i ] . EndNode. f enum double const double const double int Ptr_ Edgetype f Off. Tail. No. Head = NULL.* * ^ records ' Boolean switch) Node_Type printf ("\nNo. Bestime = Nothing. Tip. & Nodes. Bestime. Nodes.h > •include < stdlib. typedef struct Node Ptr__Edgetype double int int } Node_Type. Switch. } Edge_Type. Cycles. Edges. * Ptr_Edgetype. for ( to. } NodeFacts [ StartNode ] . n. Route. ^ .THE COMPLETE PROGRAM /* SHORTEST ROUTE PROGRAM * / •include < stdio.(3. On } . Best. Bestime = LongTime.

9: DYNAMIC STORAGE 153 . if C Try < NodeFacts[ Edge->Tip l.2f". n ) .BesHme + Edge -> Time. ' Edge->Tip ]. • ' • to leads i Cycles = 0 . or going return 0 . if ( n ) printf (". while ( Edge != NULL ) Try = NodeFacts [ n ].Bestime ) NodeFacts NodeFacts NodeFacts ' Edge->Tip ]. } Best = NodeFacts [ EndNode ] .Route = n . NodeFacts [ n ] . Head. else printf ("\nNo way through. + + j ) P = ( Ptr_Edgetype ) malloc ( sizeof (Edge_Type) ) .for Edges. Switch == On ) { Cycles = 0 . while C Cycles < 2 ) f Cycles += 1. Edge = Edge -> Link.Switch = On. Best). Edge = NodeFacts [ n ] . NodeFacts [ Tail ] . Head = p.. if ( NodeFacte [ n ] . & Tail. Bestime.BesHme = T r y . Edge->Tip ]. scanf ("%i %i %lf". printf ("\n\nTime taken is %. StartNode ) . n = EndNode. n = n % Nodes + 1. nowhere").. & p -> Time ) . p -> Link = NodeFacts [ Tail ] . if C Best != LongTime && Best != Nothing ) printf ("\nRoute from %i to % i \ n " .1. while ( n ) f printf ("%i". Route. Switch = O f f ."). & p->Tip. EndNode. n « NodeFacts [ n ] . n = StartNode . Head.

Procedures for both these operations are given below: void In_After ( P_Type Old. 4 \ new record may be inserted before or after the record currently pointed to.Fore . -> Aft = Old. Fore -> Aft = Young . Young pointers initially finally INSERT Young AFTER Old 154 ILLUSTRATING C .AN ELEGANT DATA STRUCTURE Tjfhe fundamental record of a doubly linked ring has pointers pointing fore and art thus: . it is also depicted empty. struct Petal * Aft . if so. * P_Type . P_Type Young ) Young Young Old -> Old -> -> Fore = Old -> Fore . Very messy. Head I • I Head gp\ ring is depicted above with four records. Fore = Young . L^C^ l\n the main program an empty ring may be set up as follows: typedef struct Petal struct Petal * Fore . To keep everything simple. p = ( P_Type ) malloc ( sizeof ( Ring_Type ) ) .Aft 4j£cess to records in a ring is simplified by '{data •! employing one record as a dummy head as illustrated below. and. l#lere is the definition of a shape suitable for constructing a ring. } Ring_Type. char Data . This device makes it unnecessary to check whether the record to be added or deleted is next to the fixed head. to take special action. this shape is made capable of storing just a single character.

. lAf both occurrences of Fore were changed to Aft. start by pointing to the first record and arrange to stop as soon as the pointer points to the dummy head ({ before trying to refer to data in the dummy head J). Old -> Aft -> Fore » Old -> Fore. the result of the above piece of program would be ELBA rather than ABLE. •A <\ . copy these in either order TJraversal is simple in either direction.Head -> Fore while ( a != Head { printf ("%c". Aft = Young. ) -> Data ) .void In_Before(P_Type Old. \Jver\eaf is a demonstration program designed to exercise the principles and procedures introduced on this double page. -> Aft = Old -> Aft Aft -> Fore » Young. the only difficulty is stopping. . q <\ = <\ -> Fore printf ("\n") . P_Type Young) Young Young Old -> Old -> -> Fore « Old. Young Old ^ if pointers initially finally Young INSERT Young BEFORE Old l^eletion (J without freeing and returning to the heap ]) is simple: void Delete( P_Type Old ) Old -> Fore -> Aft = Old -> Aft. 9: DYNAMIC STORAGE 155 . If the aim is to traverse the ring precisely once.

Head.g.any existing letter ) to remove letter" n \nEnter > to list alphabetically. printf ( "\nEnter +L ( or + any letter ) to add letter to the ring" M \nEnter -L ( or . To display in reverse order enter <. Head -> Aft = Head. Enter + L Car + any letter] to add letter to the ring Enter -L Cor . enter +L (j[ or + other letter )) . Fore. p. void In_Before( P_Type Old.h > #include < stdlib. enter > at the start of a line.h > typedef struct Petal struct Petal * struct Petal * char Data.A PROGRAM TO DEMONSTRATE THE PRINCIPLES OF A DOUBLY-LINKED RING ijfhe following program maintains a doubly-linked ring organized alphabetically. * P_Type. w [ 80 ]. /* MAIN PROGRAM */ int main ( v o i d ) char P-Jype char Choice. Head -> Fore = Head. void DeleteC P_Type Old ) . /* RING A RING OF ROSES */ #include < stdio. q .any existing letter] to remove letter Enter > to list alphabetically. enter -L (J or . To introduce a letter. Head -> Data = NULL. Letter. P_Type Young ) . To display the stored data in alphabetical order. hold down Ctrl and press C )j) .C < FA 156 ILLUSTRATING C . prototypes input buffer for $scanf() Head = (P_Type) malloc ( sizeof ( Ring_Type ) ) . abort the run (J e. struct PetoL } Ring_Jype.whatever the letter j) . in DOS. or < to list in r e v e r s e W ) . To remove a letter. Aft. To stop. or < to list in reverse • C +F ACF .

while ( i ) { Choice = Letter = 0\ sscanf ( gets(w), " %c %c ", & Choice, & Letter ) ; if ( Letter == 0 || ( Letter >= 'A' && Letter <= 'Z') ) switch ( Choice ) case V : p = (P_Type) malloc ( sizeof ( Ring_Type ) ) ; p -> Data = Letter; q = Head -> Fore; while ( ^ != Head && q, -> Data < Letter ) q, = q -> Fore; In_Before ( q, p ) ; break; case '-' : q = Head -> Fore; while ( q, != Head && q^ -> Data != Letter ) Q = Q -> Fore; if ( q != Head ) Delete ( o ) ; v break; case '>' : q = Head -> Fore; while ( q != Head )
list alphabetic

ra

remove Letter

printf("%c", q, -> Data); (\= (\-> Fore; printf ("\n"); break; case '<' : 0 = Head -> Aft; while ( ^ != Head ) printf("%cf \ q -> Data); q, = q -> Aft; printf ("\n");
^Jyour compiler may warn of f unreachable code\

return 0;

functions Injefore () and Delete () here 4)p application such as a book index $ a secondary sorted list under each entry j) can be handled as a ring of rings.

•i

9: DYNAMIC STORAGE

157

I

ANOTHER ELEGANCE

TJake some letters to sort: D, Z, B, E, A, F, C /^T~^\

(a node J luring the first letter, D, to the root of a ^ - ^ - * * - * f t tree and store it as a node. (J Trees grow (add D\ upside down as do several metaphors in W^^-' computer science. ]) ^~ _ _ _ M o w take the next letter,^ Z, and bring it to the root node. It is 'bigger' than D so go right and make a new node to contain Z as shown here. the third letter, B. It is smaller than D so go left and make a new node. ijfhe next letter, E, is bigger than D so go right. It is smaller than Z so go left. Then make a new node to contain E as shown here. Ijp general, bring the next letter to the root node and compare. If the new letter is smaller go Left, if bigger go righL Do the same thing as you reach the next node, and the next and the next. Eventually you will find no node for comparison. At that stage make a new node and store the new letter in it.

158

ILLUSTRATING C

4 ^ any stage the tree may be traversed (Jf or stripped ]) as shown below. Notice that the arrow runs through the letters in alphabetical order.

TJhe type of node record depicted opposite is easily defined
Right

typedef struct Nod struct Nod struct Nod char int * Left; * Right; Data; Count;

Node_Type, * P_Type; l^janging letters on a tree & depicted in stages opposite « is best done recursively. If the current node is NULL make a new node to contain the new letter; otherwise invoke Add_Item with the parameter specifying the left or right pointer according to how the new letter compares with that pointed to:
r

-Type

Add_Jtem ( P_Type p,

char Letter

) ^—^ ,—-^ A create new j '{node with null\ \potntersj^

{

if ( P == NULL ) P = Create_Node ( Letter, i ); else if ( Letter < p -> Data ) p -> Left = Add Item ( p -> Left, Letter ) ; else if ( Letter > p -> Data ) p -> Right = Add_Item ( P -> Right, Letter ) ; p -> Counf ++; return p ;
\ don t .store twice, just J ( to the count ir

} Tjhe function for creating a node involves the mallocC) function whose prototype is in <stdlib.h>: P-Jype Create_Node (char D, int C) P_Type p; p = (P_Type) malloc ( sizeof ( Node_Type ) ) ; p -> Left = NULL; p -> Right = NULL; p -> Data = D; p -> Count = C; p return p ;

9: DYNAMIC STORAGE

159

(COHTIHUED) TJfhe tree may be traversed recursively: void Strip ( P_Type p ) if ( p !« NULL ) Strip ( p -> Left ); Print ( p -> Count, p -> Strip ( p -> Right ) ; } where the Print() function is as follows: void Print ( int i , char c )
I print the Letter as j many times as Count dictates T

f
while ( i — ) printf ("%c", c ) ;

I j h e order of stripping shown above is called 'in order other orders are useful to programmers:
^V"

stripping. Two
"V^
>^ V

V^

\/*^

-V

^V"

^s^

^V

'pre order

D BAC ZEF

'post order

ACB FEZ D

, Print ( p -> Count, p -> Data ) ; Strip ( p -> Left ) ; < > Strip ( p -> Right ) ;

Strip ( p -> Left ) ; Strip ( p -> Right ) ; Print ( p -> Count, p -> Data ) ;

4 ^ g to the tree is simple, as demonstrated by the elegant brevity of Add_Jtern, but true deletion is not simple because it requires rearrangement of the tree. The following function finds the letter specified, then decrement its count of occurrences. The Print() function ignores letters that have a zero count, so Lose_Itern effectively deletes letters. void Lose_.Item ( P_Type p, char Letter ) { if C p != NULL )

^ - ^

Zjnods not found)

if ( Letter < p -> Data ) - < S—^/ recursive\ (V calls J Lose_Item ( p -> Left, Letter ) ; else if ( Letter > p -> Data ) * Lose_Item ( p -> Right, Letter ) ; ^ \^ ^ else Cnode found and J if ( p -> Count > 0 ) ^j£ -Jk decremented if f p -> Count — ;
V/" *\^

ILLUSTRATING C

break. A abort the program ^ f Choice = Letter = 0 .ANOTHER NAME FOR THE BINARY TREE SORT /* MONKEY PUZZLE SORTING */ •include <stdio. Add_Jtem ( P_Type. w [ 8 0 ] . Data. while ( l ) to Leave the loop. printf ("\nEnter +L ( or + any letter ) to add letter to tree" "\nEnter -L ( or . printf ( \n f l ). * Right. " %c %c ". & Choice.any existing letter ) to remove it" "\nEnter to list alphabetically\n" ) .h> typedef struct Nod struct Nod struct Nod char int * Left. int ) . Root = NULL. * P_Type. case '-': case ' _ ' : Lose_Item ( Root. Strip ( P_Type ) . ) make underscore a synonym for a minus signj case V : Strip ( fRoot ). Choice. Node_Jype. Letter). Lose_Item ( P_Type. 9: DYNAMIC STORAGE 161 . Letter. sscanf ( gets ( w ) . if ( Letter == 0 || ( Letter >= fAr && Letter <= %t ) ) { switch ( Choice ) case V : Root = Add_Item ( Root. break. P_Type P_Type void void void Create_Node ( char. & Letter ) . Letter ) . your compiler may warn of (unreachabte code A here the functions whose prototypes are listed above return 0. char ) . Print ( int. f int main ( void ) P-Jype char Root. char ) . char ) .h> •include <stdlib. Count.

Contrive a network in which there is more than one 'shortest' route. Each structure on the main ring should also contain a nested structure (| of similar shape j) defining a sub-ring to enable an entry in the book index to look something like this: cats. implement the shortest route program on Page 152. Change the program so that it reads a numerical expression instead of an algebraic one -ss* and produces a single numerical result. 178-81 in which the sub-entries for 'cats' are in alphabetical order. Which does the program choose and why? Modify the program so that it detects multiple shortest routes and warns the user of their existence. exercise 3. Extend its scope so that entering < from the keyboard makes the list of letters appear in reverse order. 176-7 in literature. it employs dynamic stacks. The structure on the ring should contain a pointer to a chain of integers representing page numbers. 172-4 habits of. The way to go about it is explained on Page 142. implement the monkey puzzle program on Page 161.implement the program on Page 148. 172ff care of. ]) 162 ILLUSTRATING C . As a challenge. order program ROSES such that it stores words in alphabetical rather than just letters. develop the program as a tool for book indexing. (| The scope of binary trees is only touched on in this book.

yfhis chapter presents the functions of the ANSI C library. Ijjach function is described by name of function. Functions are grouped according to application. its prototype. name of header file in which it is defined. . For full details see ANSI X 3. use the summary in Chapter 11 for alphabetical reference. a brief description of the function. and an example of its usage.195 which also explains why such functions were included in the standard library. Inunctions concerned with multi-byte characters and foreign locales are not fully described in this book.

FILE * s ). size_t fread ( void * buF% size_t b. OutStream ). InStream ) . 80. so avoid arguments that have side effects. sizeof ( char ).h > int putc ( int c. FILE * s ).h > int fputc ( int c. macros: putc() is equivalent to fputc(). Both functions return the number of items successfully transferred. size_t c. Nr Out = fwrite Nr . 164 ILLUSTRATING C . output and file management are described under the following subheadings: Low-level input & output Single character input & output File management Random access String input & output Formats for input & output Temporary files Buffering LOW LEVEL I/O fwrite.I n = fread c P out. getchar • #include < stdio. SINGLE CHARACTER I/O fputc. stdout ). 80. gete. fgetc. • #include < stdio. size_t c% FILE * s ). Low level functions for writing from buffer to file and reading from file to buffer. Output a single character to stream s. size_t b. int putchar ( int c ). size_t is a special type defined by typedef in stdio. FILE * s ). stdout ).h > int fgetc ( FILE * s ). sizeof ( char ). fread • #include <stdio.h> size_t fwrite ( const void * buF. putc* putchar • #include < stdio. putcharQ is equivalent to putc( int c. P_in.l/unctions for dealing with input. fputc ( Ch.h.

fopen. Ch a fgetc ( stdin ). freopen. so avoid arguments that have side effects.Input and return a single character from stream s.h> FILE * fclose ( RLE * s ). otherwise NULL 10: LIBRARY 165 . thereby redirecting input or output from stream s to the nominated file. Returns 0 if successful. I f a second character is 'ungot' before the first has been picked up.h> FILE * fopen ( const char * file. Function fopen() opens a file in the mode specified and returns a pointer to the associated stream. flushing the output buffer if writing. Closes an open stream. the first is lost. Returns the code of the character 'ungot'. • #include <stdio. Causes the next fcjetc() (J or other 'get1 function]) on this stream to pick up the character ungot1. The composition of *mode is defined on Page 117. fflush ( stdout ). Function freopen() is similar to fopen(). const char * mode ). getchar() is equivalent to getc(stdin). FILE * s ). ungetc • #include <stdio. Flush output buffer on stream s. FILE * freopen ( const char * file. but points to stream 5. or EOF if unsuccessful ungetc ( Ch. int getchar ( void ).h> int getc ( FILE * s ). Return &% ifsuccessful.h> int fflush ( FILE * s ). Returns NULL if unsuccessful. const char * mode.h> int ungetc ( int c9 FILE * s ). FILE MANAGEMENT fflush •include <stdio. • #include <stdio. stdin ). fctose •include <stdio. macros: getc() is equivalent to fgetc().

remove.h> void rewind ( FILE * s). V . ferror • #include <stdio. Resets the error • indicator and end-of-file indicator without rewinding. rename. • #include <stdio. MyStream * fopen ( p. currently closed. • clearerr.char *p = "C:\\MYDIR\\MYFILE.h> int fseek ( FILE * 5. int origin ). Locates the file pointer: 166 ILLUSTRATING C . See page 1 8 for fuller description. "w+" ). Renames a file. or the error indicator has become set.ME". remove( "MYFILE. rename ( "HER. stdout ). and returns 0 if successful. long offset.h> int remove ( const char * ftLe)\ Deletes a file. rewind ( MyStream ). Locates the file pointer such that the next read will pick up the first item. printf ( "%s\n". #include <stdio. returning 0 if successful. whether it is open or closed. ftell • #include <stdio. Returns z. Clears end of file and error flags for stream s. #include <stdio.DOC") ? "Error": "OK" ). int ferror ( FILE * s ).TXT". printf ( "%s\n". Returns non-zero if there has been an attempt to read the stream beyond its end-of-file indicator.h> int rename ( const char * old* const char * new ).h> void clearerr ( FILE * s ). rewind • #include <stdio. 1 RANDOM ACCESS fseek. feoF. fclose ( YourStream ).SUR") ? "Error1 : "OK" ). "HIS. freopen ( "PRNTFILE.h> int feof ( FILE * s ).ero if all's welL Each function clears its associated indicator.SUR".

puts • #include < stdio. origin must be zero (£ SEEK_SET ]) . From stream s the function reads as many as n-i characters to buffer b[J.h > int fgetpos ( FILE * 5. SEEK_CUR. one byte past the end of the file if origin specifies 2. 1 and 2. fsetpos ( MyStream. 0. SEEK_END } is defined in stdio. at offset bytes from the start of the file if origin is 1.• • • at the start of stream s if origin specifies 0. • #include < stdio. PosPoint ). For clarity: enurn { SEEK_SET. PosPoint ). fpos_t is a special type defined by typedef in stdio. Saves the position of the file pointer on stream s at the location pointed to by c I f successful. the function clears the end-of-file flag for stream s and returns 0. gets. 10: LIBRARY 167 . otherwise it sets the global variable errno and returns a non-zero value. It appends '\0' to the character string.h as constants for 0. fsetpos. fpos t * PosPoint. If successful. If the return is used as offset in f seek(). the function returns 0. fpute. The function returns a pointer to burfer 4 or NULL if the operation rails.h > long ftell ( FILE * s ).h > int fsetpos ( FILE * $9 const fpos_t * p ). STRING I/O fgete. Returns the position of the file pointer. • #include < stdio. Sets the file pointer for stream 5 to the value pointed to by />. the function sets the global variable errno and returns a non-zero value.h > char * fgets ( char * b. ftell ( YrStream ). The function returns 0 if successful. fseek ( MyStream. It stops reading if it meets \n (J which it RETAINS]) or EOF. fgetpos • #include < stdio.h. I f unsuccessful. int /7. SEEK_SET ). but under MS DOS may return 0 after an unsuccessful attempt. fpos_t * c ). fgetpos ( MyStream. FILE * s ).

#include <stdio.h> char * gets ( char * b );

Reads characters from stdin until meeting \n (J which it DROPS ]) or EOF. It appends '\0 f to the character string. The function returns a pointer to buffer 4 or NULL if the operation fails. • #include <stdio.h> int fputs C const char * b% FILE * s );

Sends the character string in buffer b (J which must be zero terminated ]) to stream s. Returns 0 if the operation fails. • #include <stdio.h> int puts ( const char * b );

Sends the character string in buffer b (J which must be zero terminated ]) to stream stdout and appends a new line character. The function returns 0 if the operation fails. 80 ], v [ 80 ]; char w fgets w, 80, stdin ); V ,); gets w, stdout ); fputs puts

c c

r

FORMATS FOR I/O

fprintf, printf, sprintf
• #include <stdio.h> int fprintf ( FILE * 5, const char * fmt^ ... );

Prints on stream $ as many items as there are single percentage signs in Fmt that have matching arguments in the ... list. Pages 110 and ill describe the composition of the format string. The function returns the number of items actually printed • #include <stdio.h> int printf ( const char * fmtn ... ); As fprintfC) but with stdout implied for stream $. m #include <stdio.h> int sprintf ( char * /?, const char * Fmtn ... ); As fprintf() but with string p in place of stream s.

168

10: LIBRARY

char fmat [ ] = "First %i, then %6.2f then %c then %s\n"; char sink [ 80 ] ; fprintf ( stdout, fmat, 1, 1.25, 'A', "OK" ); printf ( fmat, 1, 1.25, 'A', "OK" ); sprintf ( sink, fmat, 1, 1.25, 'A', "OK" ); printf ( "%s", sink );

vfprintf, vprintf, vsprintf
• #include <stdio.h> #include < stdarg.h >

First 1 then 1.25 then A then OK First 1 then 1.25 then A then OK First 1 then 1.25 then A then OK

int vfprintf ( FILE * 5, const char * fmt, va_Jist ap ); int vprintf (const char * fmt, va_Jist ap ); \x\\ vsprinif ( char * /?, const char * fmL, va_list ap ); These functions correspond to fprintf, printf, sprintf respectively, but instead of having a list of arguments they have a pointer of type va_Hst pointing to the 'next1 argument retrievable by va_arg(). Page 96 explains the use of va_arg(). va_list is a special type defined by typedef in stdarg.h. for C n=0; n< Count; ++n) vprintf ( "%f", va_arg ( ap, double ) );

fscanf, scanf, sscanf
• #include <stdio.h> int fscanf ( FILE * 5, const char * fmU ». );

The function reads from stream s as many items as there are percentage signs in Fmt for which there are corresponding pointers in the ... list. White space in fmt is ignored. The function returns the number of items actually read; if excess arguments are provided they are ignored. Pages 1 2 and 1 3 describe the composition of the format string. 1 1 • #include <stdio.h> int scanf ( const char * fmt, ... ); As fscanf() with stdin implied for stream s. m #include <stdio.h> int sscanf ( const char * ^, const char * fmL, ... ); As fscanf() but with string b in place of stream s. fscanf ( stdin, " % i " , &n ); scanf ( ' % i ' \ &n ); char w [ 80 1; gets ( w ); t sscanf ( w, '%i %f %lf" , &n, &x, &y );

10: LIBRARY

169

TEMPORARY FILES

hmpfile, tmpnam
• #include < stdio.h > FILE * tmpfile ( void );

Opens a nameless, temporary file in mode "wb+" and returns the associated stream. Mode is defined on Page 117. The function returns NULL if opening fails. The nameless file is automatically deleted on closure of the stream. • #include <stdio.h> char * tmpnam ( char * nam );

Generates a unique name and returns a pointer to it. The argument points to the array in which you want the name stored. The minimum length of array is given by L_tmpnam, the maximum number of names by TMP_MAX, these constants being defined in stdio.h. Absence of an argument implies storage in the form of a constant. See Page 120 for clarification. FILE * Brief Stream; Brief Stream = tmpfile Q ; fclose ( Brief Stream char R [ L tmonarn ] ; tmpnam ( R j ; FILE * S; char * M = t m p n a m ( ) ; S = fopen ( M, "w+b" ) ; );

' name stored as a constant >

fclose ( S ) ; remove ( M ) ;

BUFFERING

setybuf, setbuf
• #include < stdio.h > int setvbuf ( FILE * 5, char * A, int mode, size_t sz );

Changes the buffer for stream s from that allocated by the system to that specified by A The mode of buffering should be specified as: • • • _IOFBF f o r full buffering, _IOLBF for buffering a line at a time, _IONBF f o r no buffering.

170

ILLUSTRATING C

Buffer size is specified by sz. The mode constants, and the special type size_t, are defined in stdio.h. • #include < stdio.h > void setbuf ( FILE * 5, char * b );

As setvbufC) but with mode set to _IOFBF and sz set to BUFS1Z. The constants are defined in stdio.h. setvbuf ( MyStream, MyBuf, _IOFBF, 2048 ); setbuf ( YrStream, YrBuf );

l/unctions for process control are described under the separate subheadings: Termination Environment Locale Error recovery
Signals & exceptions

TERMINATION TJhe following functions are concerned with terminating a program, printing explanatory messages and tidying up at exit. Three libraries are involved.

exit, abort, assert
• #include <stdlib.h> void exit ( int status );

Call exit() to exit a program normally. The function flushes file buffers, closes files left open. If you registered a set of functions using atexit(), these are now invoked in the reverse order of their registration. Constants EXIT_SUCCESS and EXIT_FA1LURE are defined in stdlib.h for use as an argument. EXIT_SUCCESS has the value zero.

10: LIBRARY

• #include <assert. assert ( Nodes > Edges ). atexit ( Second_Func ). perror ( "out of memory" ). Registered functions should be simple ones that cause no side affects. A macro intended for program development. You may register as many as 32. see local manual for the number permitted. You can disable assert() using macro NDEBUG in the preprocessor. Call abort() to exit a program abnormally.h> void assert ( int expression ).• #include <stdlib. I f expression evaluates as z. Prints on stream stderr the message you give as argument. certain diagnostics are sent to stderr. The function does not flush file buffers or call functions set up using atexit(). Precedes the message with the error number currently held by the global variable errno. perror • #include <stdio. if ( ! Chaos ) exit (0). exit (2). When atexitO is invoked it 'registers' the function p>ointed to by fun as a function to be invoked by exit(). then abort() is invoked. 172 ILLUSTRATING C .h> int atexit ( void ( * fun )( void ) ). if ( Chaos ) abort(). atexit ( First_Func ).h> void abort ( void ).The exit() function invokes all registered functions in the reverse order of their registration. atexit • #include <stdlib.h> void perror ( const char * mess ). possibly more.ero.

also the usage of commas and periods.ENVIRONMENT TJhe following functions are concerned with a program's environment. LC_MONETARY etc. f r o m inside computer's operating string. Ho Function in the C Library refers to any Locate convention save that of the decimal point. Do not attempt to change the static object pointed to. 10: LIBRARY 173 . a program.h> int system ( const char * command ) . A set of such conventions may be set up in a C program as a named structure. Environment strings may be interrogated and commands to the operating system executed f r o m inside the program. f o r example "PATH" or "MYFILE2".h> char * getenv ( const char * Hame ). The name used as an argument is matched against the list of 'environment names' held by the system. z e r o to indicate absence. See ANSI X3. otherwise it returns NULL.159 for further information. the structure named C specifies only the use of a period as a decimal point. a command addressed to the system. and these may be picked up for use in any 'international' functions you may write. LOCALE M y values in different countries are printed in diverse styles. ]) which may be independently changed. getenv • #include <stdlib. the function returns non-zero to o f a command processor. The command should be encoded as a the argument. A locale has categories (J accessed by the constants LC_NUMERIC. The prototypes shown below declare functions for setting conventions for a locale and interrogating the structure. Separators and groupings of digits vary. Given NULL as indicate the presence system ( "DIR" ).95 versus J£3-15. for example #5. Executes. I f a match is found the function returns a pointer to the corresponding data object. LC_TIME. system • #include <stdlib. p = getenv ( "PATH" ). By default.

if C ErNo = setjmpCMyBuf)==0 ) { normal program } else f handle errors: switch CErNo) } if C Chaos ) longjmp C MyBuf. the same in scope.L1 of ANSI X3. To avoid unwanted interaction. longjmp • #include <setjmp. which causes a jump to a label in function.h> int setjmp C jmp__buf saver ).h>. The second argument of longjmpC) provides an error code which setjmpC ) then returns. struct Iconv * localeconv ( void ). damned %s. longjmpC) and setjrnpO. setjmp. printfC'Out. On invocation. " C " ) . control returns to setjmpC). referred to above as 'simple'. void longjmp C jmp_buf saver^ int value ). setjmpO saves its calling environment in the nominated buffer for use by the next invocation of longjmpC). The macro returns 0 if successful. 1 ). When a subsequent longjmpC) is executed. Also defined is an array type named jmp_buf. out I say!\n". The a similar use is not A macro. seHocale ( LC_ALL. The program behaves as though there had been no interruption to its flow.6. localeconv ( ) . but their constrained to the scope of a single function. can be useful for error recovery but is limited facilities.h> char seHocale ( int category const char * Locate ).setlocale. may be found in 4. A definition of the four allowable contexts. ERROR RECOVERY TJhe 'goto' statement. is defined in <setjmp. 174 ILLUSTRATING C . The location of setjmpC) serves as the 'label'. localeconv • #include <locale. are designed to serve purpose as the 'goto' and the label respectively.159. setjmpO.> decimaLpoint). calls to longjmpC) should be made only in simple contexts.

errors and interruptions. The header file defines the following macros f o r processing signals: • • • SIG_DFL SIG_IGN SIG_ERR default treatment. int raise ( int sig ). raise • #include <signal. When an exception occurs during execution the processor raises a corresponding 'signal'. x ^Jignals a r e objects of type sig_atomic_J. described collectively as 'exceptions'. I f the signalC) function fails it returns SIG-ERR. This function may. After ianoring a signal. The header file defines the following signals: SIGABRT SIGFPE SIGILL SIGINT SIGSEGV SIGTERM abnormal termination. When the nominated exception arises. I f you write a handling function it should have a single int argument for the signal to be handled and return a value of like type. When an exception arises.h> void ( * signal ( int sig^ void ( * hndtr )( int ) ) ) (int ).SIGNALS. and may be designed to abort the run or return to the place where the signal was raised. e type defined in the header file. or it may be SIG_DFL or SIG_IGN. The default manner' depends on the implementation. A signal is raised by means o f the raise() function. Instead o f writing a handling function you may call one of the standard macros SIG 1 N or SIG_DFL f o r ignoring the signal or treating it in the G default manner. The second argument may be the name of a function you have written for handling the exception. control reverts to where the signal was raised. and 'handled' as specified in the function (J which you may write]) nominated as the second parameter o f signal(). I n addition to handling signals you may raise them. the corresponding signal is automatically raised. 10: LIBRARY 175 . invoke signalQ in various ways. the associated function or macro is called. EXCEPTIONS Tjfhe signal-h header file provides tools f o r handling failures. itself. The first argument of signaO should be one of the six listed. signal. depends on implementation ignore the value returned by signalC) if signal fails. as with a b o r t ( ) arithmetic error ( such as division by z e r o ) illegal instruction interrupt ( typically Ctrl+C f r o m keyboard ) attempted access outside memory range request f o r termination received by program.

•include <stdarg. Place function at start of extraction sequence. defined in the header file. SIGJGN ). va_list. l/unctions may be defined with an argument list argument always present followed by a variable arguments.h> void va_start C va_!ist p% name ). va_arg. I f a pointer to a structure is made to point elsewhere. va list o va start ( ap. double. va_start. Place function at end of extraction sequence. type ). float. according to the type of argument to be extracted in each case. etc. which may be 'freed' and returned to the heap. 176 ILLUSTRATING C . This is obeyed once for each argument extracted. the structure formerly pointed to becomes 'garbage'. Counf ). signal ( SIGFPE. Allocation functions specify the number of bytes required.h> void va_end ( va_Jist p ). exit(l).h> provides tools for picking The pointer must have the special type. va_end • #include <stdarg. <stdarg. perror (" signal failure"). raise ( SIGSEGV ). MyHandler ) « S1G_ERR ). type will be int. memory has to be allocated for the structure pointed to. • #include <stdarg.h> type va_arg ( va_list /?. comprising at least one number of 'extra' up the extra arguments. The first argument declares the pointer. \ffhen one structure points to another of the same type. See Page 96 for clarification. the second is the name of the last fixed argument in the function. Memory is allocated from a 'heap' maintained by the processor.if ( signal ( SIGINT. va _end C ap ).

Changes the size of an allocated section of memory.malloc. p = (Ptr_to_Edgetype) malloc ( sizeof ( Edge_Type ) ). pointed to by p. • #include <stdlib. • #include <stdlib. calloc. Frees the section of memory previously allocated. atoi • #include <stdlib. 10: LIBRARY 177 . (**char) NULL. The type of pointer may be indicated by a cast. <\ . realloc. sizeof ( int ) ). ijfhe functions described below are for converting values expressed in character form to values in numerical form and vice versa. atoi ( " -987" ) ).h> void * malloc ( size_t bytes ). The function returns a pointer to a buffer for an array having HurnELts elements. and pointed to by /?. The pointer should have been established by malloc(). the call: prinff ( "%i\n". The size of element is usually given via sizeof() which returns a value of the required type. • #include <stdlib.h> int atoi ( const char * s ). Size is measured as a total number of bytes. usually by sizeof() which returns a value of the required type. calloc() or realbc() — or it may be NULL. If the new size is smaller than the previous size. returning it to the heap.h> void free ( void * p ). Equivalent to (int) strtol ( 5. The type of pointer may be indicated by a cast. Returns the decimal int value represented by the argument. \0 ). to the new size of newsiz bytes. See Chapter 9 for clarification.h> void * calloc ( size__t NumELts^ size_t ELtSiz ).( int * ) calloc ( [000.h> void * realloc ( void * />. each of EitSiz bytes. the new content will remain the same as far as it goes. free • #include <stdlib. in which case realloc() behaves like malloc(). size_t newsiz ). The function returns a pointer to a buffer comprising storage of the specified size.

K LL • -98. p ) . or pointing to the start of the trailing string if such exists. e. Short f o r 'string to double'.Qtol • #include <stdlib.5e6ABC".digits exp sign digits excess • • • • • wsp means optional white space sign means an optional + or digits means an optional sequence of decimal digits. & p ) ). printf ( "%f\n".765000 strtod • #include <stdlib.765" ) ). the function returns the value of the constant HUGE VAL and sets errno.h> long atol (const char * s ). f -98765 atof • #include <stdlib. It leaves p NULL. Returns the decimal long int value represented by the argument. Equivalent to the calh strtol ( s.. atoi ( " -98765") ) . non-conforming string such as "ABC" in "-4. Equivalent to the call: strtod ( s. printf ( " %s\n". atof ( " -98. 10 ). If the converted value is too big for its type. char String [ ] = "-4. (char**) NULL ). (char**) NULL.h> double atof ( const char * s —p / / ).' excess signifies any trailing.h> double strtod ( const char * 5. printf ( "%li\n". at least one digit must follow the decimal point if there is no digit before it exp is E. printf ("%lf". D or d to signify 'times ten to the power. The f o r m of string is expected to be the following: wsp sign digits. Returns the double value represented by the argument.5e6ABC". -4500000.000000 ABC 178 ILLUSTRATING C .. strtod (String. The function returns the value represented by the string. char * * / ? ) .

next 0 to 7. p ). strtoul ("0777". leaving p NULL. char * * /?. If set -z. may be set from 2 to 36 or to -zero. char * * />. The form of string is expected to be: wsp sign 0 x digits • • • • • wsp means optional white space sign means an optional + or x means an optional x or X digits means a sequence of octal. int radix ). ( " % ] i \ n " . ( " % s \ n " . Short for 'string to long' and 'string to unsigned long'. 0 ) ). decimal or hex digits. TJhe mathematical functions are described below under the headings: Arithmetical Trigonometrical Hyperbolics Random numbers Modular division Logarithms & exponentials : LIBRARY 179 . strtolO returns the value of the constant LONG_MAX or LONG_MIN according to the sign given in 5.h> long s\r\o\ ( const char * 5. strtoul() returns ULON6_MAX and sets errno. strtol (String. excess signifies any trailing.$\r\oU strtoul • #include <stdlib. or pointing to the trailing string if such exists. first character 0. The argument. 0) ). If the value is too big for its type. char printf printf printf String [ ] = tf+i2345xxx". unsigned long strtoul ( const char * 5. implies base 16 (hex). and sets errno. &p.ero the base is deduced from the initial characters of s by the following rules: first character 0. base^ which specifies the number base. implies base 8 (octal). first character 1 to 9 implies base 10 (decimal). The function returns the value represented by string 5. ( " % l u \ n " . next x or X. non-conforming string. * p. int base ). &p.

4f\n". is set to the value returned by macro EDOM. 2 2 printf ("%ti\n".002) ). • Absolute (J positive ]) value of the argument. long labs ( long w ).h > int abs ( int n ). and the nearest whole number below the value of the argument respectively. printf ("%. If an argument supplied to a function is outside the domain over which the function is defined.999 ) pow •include < math. Idiv ]) .h header but a few are to be found in stdlib. fabs. floor ( 2. abs(0). the global variable. printf ( %.001 ) ) printf ( %. If the value computed by a function cannot be represented by type double. abs (-2). Check local manuals about domain and range errors. l 0 2 / ( / • • - 0. These are functions concerned with: • • • absolute values (Jabs.4n\ost of the mathematical functions and macros are defined in the math. In either case the value returned by the function then depends on the implementation. labs (-2). 180 10: LIBRARY .2f\n". printf ( " % i %i % i \ n " . #include < math. errno is set to the value returned by macro ERANGE. ARITHMETICAL abs. double floor ( double d ). The value returned by macro HUGE_VAL may be employed.h > double pow ( double double y ). labs • #include < stdlib. Fabs. fabs (. labs]) pseudo-random numbers (£ rand.2f\n". ceil ( 2.h > double fabs ( double d ). floor • #include < math.. errno.h > double ceil ( double d ). abs (2) ).h. srand ]) modular divisions (J div.0020 ceil. (mm* The nearest whole number above the value of the argument.

The sine.00 3. Domain error the argument is negative. cos ( .000 -1.500 0. const printf printf printf double pi = 3. / sort • #include <math. and arc cosine (J the angle is. A range error occurs if the computed value is too big. 0.71 -s.h> double sqrt ( double a ).45) ). | 8 .]) . The arc sine whose cosine the range is the argument (J the angle whose sine is.3f </o. double tan ( double ar ).h> double asin ( double a ).3f\n". f 0. printf ( "%.3f %. sqrt (0\ sqrt (13. The value returned is measured in radians.1415926.61 J TRIGONOMETRICAL sinf cos.3f %.000 1. pow (2. acos ( sqrt ( 3) / 2 ) ).3f\n". pow (2. for acos() the range is [0. A domain error if x is negative and y non-integral.2f\n". 3.5.00 2 4 .2f\n".5 ). O 524 ) ) i0: LIBRARY 181 . asin ( 0.2f %. double acos ( double a ). ( "%.2f %. tan ( pi/4 ) ). tan • #include <math. 5 2 4 0. fo. Domain error if falls outside the range -1 to +1.. sin ( 0 ) ). cos ( pi ) ) .866 0. 7l]. cosine. sin ( pi/6 ).5 ) ) . For asin() [-7C/2. double cos ( double ar ). acos • #include <math.3 ) . 7 printf (: n%. +71/2].000 asin.« ]) .p i / 6 ). ( "%. tangent (J respectively ]) of an angle measured in radians. —'—* ^J ' if The square root of an argument that must be positive.3f\n".h> double sin ( double ar ). printf i: "%.The result of x raised to the power y.3f\n". ( "%.

angle whose tangent is-. double cosh ( double x ). The value returned is For atan() the range is [-71/2. cosh. A range error occurs with sinh() or coshQ if the computed value is too big. ]) . double atan2 ( double y. arguments of atan2() specify the same x independently signed. srand(l) is implied srand ( 10 ). is [-71. printf ( "%. The seed is based on the argument given to srand().3f\n".000J rand.h> int rand (void). hyperbolic cosine.h.3f %. RANDOM NUMBERS 1. srand • #include <stdlib. if e program is re-run with x identical seeds. printf ( "%. The hyperbolic sine. 182 ILLUSTRATING C . rand() will generate an identical sequence of numbers.rand( ). const double d = 7.h> void srand ( unsigned int seed ). When called.rand() ).6009025. cosh(d). The argument o f atan() y to x. oiani • #include <math. • #include <stdlib. . tanh • #include < math. rand( ). double tanh ( double x ). hyperbolic tangent respectively. atan(l).l ) ). The starting value (J the seed ] ) may be set by a call to function srand(). f o r atan2() it The arc tangent (Jthe specifies the ratio of ratio but with y and measured in radians. tanh(d) f1000.000 ).atan. +7l]. HYPERBOL1CS sinh.3f %.3f %. sinh(d). In the absence of any srandO function.h > double sinh ( double x ). the function sets a seed for the rand() function. Returns a pseudo random number having a value between zero and the constant RAND_MAX which is defined in stdlib.h> double atan ( double a ). +71/2]. printf ( "%i %i %i\n". atan2(-l.000 1000. double x ).3f".

printf ( " %.4.h as: • #include < stdlib.4. The arguments specify the numerator and denominator of a division operation.3).3) ). The structure returned is defined in stdlib. shorty. printf ( "%i %i\n".h> double fmod ( double A-.2f\n". : LIBRARY 183 . This structure is defined in stdlib. 6. fmod (36.2f %. long denom ). double y ). 8 ).MODULAR DIVISION div.quot. shorty = div ( 37.rem ).h as: div_t shorty. fmod • #include <math.h > div_t div ( int numy int denom ). The function returns the quotient and remainder of that operation in a structure of type div_J. but involves long integers. shorty. fmod (36. where the division operation is designed to stop when the quotient reaches the highest possible integral value. Returns the remainder of a floating point division. -6. The function works as described above. positive or negative. IdiY • #include < stdlib.h > Idiv t Idiv ( long num.

2f %. Frac LOGARITHMS & EXPONENTIALS log. Function IdexpO returns the product of x times 2 to the power n. Idexp • #include <math. The natural logarithm (£ base e ] ) of the argument.modf • #include <math.00 1. double Frac. the natural anti-logarithm of the argument — in other words e raised to the power of the argument. 0. Int. int Exp. I f d is negative. Man. Exp ) ). Jog(e). double Man.3. Man = frexp ( 6. double logl0 ( double a ).2f\n M . exp(log(l23))).00 1. log(l). exp(l). int * p ).2f %. • #include <math. 184 ILLUSTRATING C . & Int).00 2.2f\n". ldexp( Man.h> double Idexp ( double x.4f %i\n".718282. logl0.h> double frexp ( double * .2f\n". & Exp ). dy leaving p pointing to a whole number expressed in floating point form.2f\n". Frac = modf(-12. both parts are taken as negative.h> double modf ( double d^ double * p ). exp • #include <math. printf ( "%.2f %. int n ). frexp.72 3. printf ( "%.34.00 123. Function frexpO returns the 7 mantissa of x and leaves p pointing to the integral exponent. printf ( "%.2f %. Exp ). Int. printf ( "%. g ( ) . printf ( "%.00 The composition of binary floating point number x is m times 2 to the integral power A . double exp ( double a ). where m is the 'mantissa'.2f %. exp(0).h> double log ( double a ). Returns the fractional part of a floating point number. the base i0 logarithm of the argument. const double e = 2.

The tests are respectively for: • • • • isalnum(). ) are defined in header file ctype. a digit from 0 to 9 isxdigit(). isgraph(' ') ). isprint • #include < ctype. a hex digit. are defined in header file stdlib. isprint(V). e letter x isdigitQ. isalnum. isdigit(V). a printable character including a space character printf ("%i %i %i\n". These functions return a non-zero value (true) if the test passes. int isalpha ( int c ). int isprint ( int c ).h > int isgraph ( int c ). and vice versa.h > int islower ( int c ). These functions return a non-zero value (true) if the test passes. isxdigit(V) ). The tests are respectively for: • • isgraph().h. isxdigit • #include < ctype. is lower. cin alphanumeric character. isprint(' '). isupper • #include < ctype. a printable character excluding a space character isprint(). int isdigit ( int c ). isaipha('G').h > int isalnum ( int c ). int isupper ( int c ). isalnum(V). int isxdigit ( int c ).l/unctions for identifying characters ( 'is it an integer?' etc.h. isgraph. Functions for converting values from character representation to numerical representation. otherwise 0 (false). otherwise 0 (false). isalpha* isdigit. letter or digit isalphaO. 10: LIBRARY 185 . 0 to F (or f) printf ("%i %i %i %i\n".

h>. ispunctC*'). tolower. a few in <stdlib. int ispunct ( int c ). isspace('. a punctuation mark such as . These functions return a non-zero value (true) if the test passes. or : or . a control character such as that sent from the keyboard by holding down Ctrl and pressing C. int isspace ( int c ).h> int iscntrl ( int c ). 4^\ost of the following functions are defined in string. ispunct(). ispunct. isspace(). \ n .These functions return a non-zero value (true) if the test passes. In the explanations that follow. \f. \ t . They concern character arrays and their manipulation. islower('n'). isspace • #include <ctype. otherwise 0 (false). one of the white space characters r '. a letter from A to Z printf ("%i %i\n". \ v printf ("%i %i %i\n". If there is no such equivalent. e letter from a to z x isupper(). The tests are respectively for: • • • iscntrl(). 186 ILLUSTRATING C . \ r . toupper • #include <ctype. otherwise 0 (false). iscntrlC ')). The tests are respectively for: • • islower().h.') ). the phrase 'string s' is used as a short way of saying 'the array pointed to by s.h int tolower ( int int toupper ( int c ). treated as type int. To 64 0 f (example Returns the lower case or upper case equivalent of the argument respectively. isupper('n') iscntrl. the function returns the same value as its argument.

e_t strlen ( const char * s ). 1(2): LIBRARY 187 . The functions return a pointer to the copied string. "ABCDE". strlen ( ADC ) ). < COPY & CONCATENATE Tfhe library offers several string copying functions. char * strncpy ( char * 5/. but copies only n characters. If a terminator in s2 is met before all n characters have been copied.h> char * strcpy ( char * sU const char * s2 ). the target string is padded with null characters to the full count of n. Returns the number of bytes in the null-terminated string pointed to by 5.h> siz. char S[6]. HOT counting the null terminator. For neither function should the strings overlap. strncpy • #include <string. const char * s2% size_t n ). including its terminating null.The functions are described under the following subheadings: • • • • String length String copy & concatenate String comparison & search Miscellaneous strings STRING LENGTH strlen • #include <string. 8). to s2. strncpyO does a similar job. Function strcpyO copies string 5/. printf ( "%r\ n " . all subtly different in behaviour. strcpy. strncpy ( S.

if it encounters a difference it returns a positive or negative value. memcpy ( S.h > void * memcpy ( void * bu const void * b2* size_t n ). strncmpO does a similar job. I f it reaches the end. The copied string is not disturbed. until it reaches the end of both strings or encounters a difference. memmove • #include < string. Function strcat() copies s2 onto the end of sU overwriting the terminating null of si with the first character o f s2. int memcmp ( const void * 5/. strcrnp( "ABCDeFG". size_t n ). strncat ( S. void * memmove ( void * b/9 const void * A?. memcpyO copies n characters from buffer b2 \o buffer bu returning pointer bL The objects should not overlap. strncmp.merncpy. strncat • #include < string. size_t n ). printf ( " % i \ n " .h > char * strcat C char * sU const char * s2 ). memcmp() is similar to strncmpO but not constrained to work with null-terminated strings. char S[3]. The value returned is positive if the first non-matching character in si is greater (£ treated as unsigned char ^) than the corresponding character in 5f. "ABC". const void * s2. 188 ILLUSTRATING C . then copied from the buffer to bu thus tolerating overlap. Function strcmpO compares si and s2^ character by character. "ABCDEFG" ) ). The objects copied by these two functions are not limited to nullterminated strings. int strncmp ( const char * sU const void * s2^ size_t n ).h > int strcmp ( const char * sU const char * s2 ). otherwise the value returned is negative. For neither function should the strings overlap. memcmp • #include < string. but appends only the first n characters o f s2. but considers only the first n characters — fewer if a null terminator is met early. 2 ). char * strncat ( char * $U const char * s2. 3 ). the function returns zero. strcat. then adds a null terminator. char S[6] = "XY". size_t n ). STRING COMPARISON strcmp. strncatC) does a similar j o b . The return value is si. "ABCD". memmoveO does a similar job to memcpyO but behaves as though the n characters were first copied from b2 to a private buffer.

strrchr() is similar to strchr() but returns the last occurrence instead of the first. On the first call to strtokO the first argument should identify the string full of tokens.h> size_t strcspn ( const char * sU const char * s2 ). 5 leading consonants ian 4 leading digits at oats The function returns pointers to successive tokens constituting the string si. strrchr( "abba". strstr • #include <string.h> char * strchr ( const char * s.h> v*—-^ *~ char * strtok ( const char * sU const char * s2 ). strchr( "abba". const char * s2 ). char * strptrk ( const char * 5/. size_t n ). strspn. mernchr() does a similar job to strchr() but is not constrained to work with null-terminated strings and considers only the first n characters of buffer b. The function returns NULL when there are no more tokens to deal with. void * mernchr ( const void * i>. size_t strspn ( const char * sU const char * s2 ).STRING SEARCH strchr. int c. the terminators may be different on each call. 10: LIBRARY 189 . V). strrchr. In both these functions. Function strstrO finds the location of sub-string s2 in si and returns a pointer to its leading character. printf ( "%s %s\n" . char * strstr ( const char * 5/.h> •include <srnna. strspn() returns the number of characters in si encountered before meeting one that is outside the list in s2. memchr • #include <string. on subsequent calls the first argument should be NULL to signify the same string as before. i >. bba strcspn. sh-tok •include <strinq. char * strrchr ( const char * s. Function strchr() returns a pointer to the first occurrence of c in 5. ba S " /*—^~ Function strcspn() returns the number of characters in si encountered before meeting any of the characters in $2. Characters deemed to separate the tokens are listed in s2. strpbrkO returns a pointer to the first character encountered in si that matches any of the characters in s2. const char * s2 ). V ) ). int c ). '\0' is included as one of the characters of the string. int c ). The original string is overwritten with undefined information. Returns NULL if there is no match. or NULL if it fails to find one. strpbrk.

The content of the message depends on the implementation. Make sure b has at least n characters. printf (: "%s\n". strxfrm() is for transforming strings such that their transformed versions can be compared rapidly by strcmp(). The function sets the first n characters of buffer b to the value c and returns the pointer you give as the first argument. wctomb.char * p. " /. '\0'. Line[] = "Para 37. memset ( MyBuffer. mblen.h> char * s\rerror ( int n ). ILLUSTRATING C . p=strtok( NULL. strcoll. strxfrm Functions for comparing the strings employed in particular locales. 6 d r s . strcolO is designed for use where few comparisons are expected. mbstowcs. See ANSI X3. wcstombs The ANSI C library defines a set of functions that work with multi-byte and 'wide' characters such as those in the character sets of Asian languages. printf ( "%s". See ANSI X3.6 : drs = xl / 12. while (p) printf (" %s". p=strtok (Line. ":") ) . L. 7 3 . x l . printf ("\n"). / ^ P a r a 3 7 . strerror( errno ) ). Returns a pointer to a system message corresponding to the error number given as the argument. 1 2 . ( n u l l ) .159 for details.159 f o r details. 2048 ). ( ^ r f Invalid data \ / example \ rnemset • #include <string.-") ). The argument is typically the value of the global variable errno. mbtowc.h> void * memset ( void * b^ int c^ size_t n ). MISCELLANEOUS STRINGS s\rerror • #include <string.73".

bsearch ( Key. "miny".Tjfhe following functions typically employ a Quicksort algorithm and 'binary chop1 respectively. qsort • #include <stdlib. the function returns a pointer to the matching element. -*^-^_^-^-^—** -^^—**^—>^-—^^-^^^^^__^^-> The function searches the first n objects in a sorted array.{ "eeny". the key being associated with first argument. otherwise zero.159 does not demand any particular methods of implementation. comparison ). The function rearranges the n pointers held in b such that the objects they point to ( each of w bytes ) may be accessed in ascending order. n = sizeof Kids / sizeof Kids[0]. 6. Specify which order by providing a function to compare the objects indicated by its arguments. "meeny". "miny" }. ++i ) printf ( "%s ". Comparisons employ the function you nominate. i<n. where comparison is a function call as defined for qsort(). 6. const void * ) . qsort ( Kids. size_t w. where comparison is a function call in the form: int ( * / " ) ( const void *. b. size__t tf. Kids. otherwise it returns NULL If more than one element matches the key. strcmp ). the array element with the second. char Kids [ ] [G] = f "mo". but which of them is unspecified char Kids [ ] [6] . for ( i = 0. 4. The function should return a positive integer if the first argument points to the greater object. Use a library function like strcrnpO or write your own. printf ( "%s\n". but ANSI X3. int j . 10: LIBRARY 191 . "meeny". and compares them with the key indicated by k.h> void qsort ( void * b* size_t /7. If a match is found. one of them is pointed to. "mo" }. size_t wn comparison ) . Kids[i] ).h> void * bsearch ( const void * const void * £. char * Key = "meeny". n. "eeny". strcmp ) ). a negative integer if it points to the lesser. bsearch #include <stdlib. each element of size w bytes. printf ( \n ).

divide the returned value by CLOCKS_PER_SEC. If the implementation does not provide a clock facility the function returns -1 (J cast as type clock_t J) . 30 } . 1-31 months since January. in Greenwich. time_t. The string contains an encoding of what is represented in the structure indicated by L Function ctimeO does the same thing. since the current process was started. printf ( "%s \ asctime ( & MyBirthday ) ). there are two distinct representations of time: • • as a type. tm isdst. but for an argument of type time__t The form of the encoding is: Sun Nov 10 21:21:00 1991\n\0 struct tm MyBirthday = f 0. tm_mon. char * ctime ( const time_t * O . 1. ctime • #include < time. time is represented as the number of seconds since the start of New Year's day. measured in 'ticks'. to obtain the number of seconds. tm_yday.h > docket clock ( void ). which is a macro defined in the time. /* /* /* /* /* /* /* /* /* Leap seconds seconds after the minute. The duration of a 'tick' depends on the implementation. 1972. 0. Sun F e b 28 1 0 : 0 0 : 0 0 1930 Returns the time. tm_wday. 0-6 days since 1st January. struct trn 4\s a type. 0-23 day of month.and if or the Functions defined in the time.h header file. Function asctimeC) returns a pointer to a string. 10.365 daylight saving time flag */ */ */ */ */ */ */ */ */ asctime. time_t as a structure. tm_year. 0-59 hours since midnight. 0. The definition of struct tm is as follows: (range allows up to two struct tm int int int int int int int int int tm_sec.h > char * asctime ( struct tm * t ). 0-11 years since 1900 days since Sunday. trn_hour. 0-61 minutes after the hour. clock • #include < time. 28. 192 ILLUSTRATING C . tm_min.h header file. tm_rnday.

the result is also copied to the location / points to.pp. Encodes information representing local time.h> struct tm * gmtime ( const time__t * / ). stores the expanded information in a structure of type struct tm.159-1989 CLK_TCK is the name some #inc!ude <Hme. tm_wday and tm vday. printf ( "%i secs\n".. ( j . and returns a pointer to this structure. time • #include <time. 10: LIBRARY 193 . Decodes information contained in the object pointed to by the argument. mktime • #include <time.h> double difftime ( Hrne_t» ^ Kme_t tl ). Consults the computer's timer. implementations grntime. Finish ). Returns the number of seconds between the earlier time.h> time_t mktime ( struct tm * p ). / CLOCK$PERSEC . t2. tU and the later time. see your particular manual about the implications of GMT and local time. dimime • according to AHSI X3. t. and held in the structure pointed to by /?. play no part in the encoding.h> time_t time ( time_t * O. Returns .. then returns this information encoded as type time__t.l (J cast as time_t ]) if the function fails.i ) /CLOCKS_PER_SEC ). localiirne • #include <time. Two of the fields. Occasion = mktime ( & MyBirthday ). Returns the current date and time encoded as type time_t If t is not NULL. time_t Occasion. Lapse = difftime ( Start.j = clock ( ) . The results are based on Greenwich Mean Time or local time according to the function chosen. p = gmtime ( & Start ). struct tm * localtime ( const Mme_t * O .

( now Thu Dec 19 1 5 : 5 0 : 0 5 L99ir sfrftime A function for formatting the date and time held in a structure of type struct tm as a string to your own design. See ANSI X3. c. A battery of about twenty format specifiers is provided. The application of strftime() is sensitive to locale. each begins with a percentage sign on the principles adopted in printf() and scanr() but using multi-byte characters. 194 ILLUSTRATING C .159 for details.time ( & TimeNow ) 1 Time is ).time_t TimeNow. time ( & TimeNow ). printf ("Time is now %s\n".

including a table showing the relative precedence of operators.TJfhis chapter contains summaries of information designed for quick reference. listing alphabetically the prototypes of all library functions except those concerned with multi-byte characters and foreign locales. showing all syntax diagrams included in the text Library summary. It contains: • Operator summary. Syntax summary. .

[ ] signifies array () [1 196 ILLUSTRATING C .w — INFIX OPERATORS expressions integral expressionsJ pointer > <= »= /%757/ZT OPERATORS use value. ASSOCIATIVITY & SEMANTICS High -*• •4— ~* 0 [1 J ++ % * & ++ sizeof ^^prefi^\ preceden associativ ? 4444 A r & 1 && += (g^stj^ t 1 Z II -4+ & * ! ++ v *» • +a • -a • &v • *p • !m • PREFIX OPERATORS confirmation negation address of l-value pointee of \ object pointed to b ones' complement ~1110 t p> [ H I logical not ( [ 1 if n /»/5^ j J KEY increment J decrement ]) 1-vaLue then use value integral l-value • • • • • • • • • • • • • • • a*b a/b m%n a+b m&n m«n a.'PRECEDENCE. then increment (Jdecrement]) OTHER OPERATORS (type-name ) sizeof sizeof ( ) • m?a: b • (double) a v sizeof v sizeof ( d o u b l e ) if m=0 value is a.b n>m n&&m v =a a +«b n&=m n«=m v.w p->w product quotient member name remainder sum (f difference ]) bitwise ^7/7^/ (J ^ r ]) $ exclusive or 1 ) m shifted left (J right ]) n positions evaluate & discard a. eval & retain b 1 if comparison is truey otherwise 0 logical and (J or D assign value of a to l-value v short for a=a+b d and similarly J) short for n=n&m ({n=n|nnj) fln=nAmI) short for n=n«m (j[ n=n»m ]) member w of structure v short for (*p). otherwise b result is a double (J 'a' undisturbed size in bytes of object v size of every object of type double ( ) signifies function.

octal. or\ \hex Letter N V a B C c D d E e F f G 9 H h I i J j k L I M m N n 0 o P space l 2 3 4 5 6 7 8 9 symbol v a b f n r t v \ r BEIL 35 FF /ASCII Nt S notation] R r /r S s T t U u ??( V v W w X x Y / Z z 197 11: SUMMARIES .THE HOTATIOH EMPLOYED IS DEFIHED OH PAGE 28 character Letter digit symbot escape decimal.

digit digit or f {float)) or L {long double) - names a constanl of type int Letter digit symbol escape 198 ILLUSTRATING C .token \ keyword name constant string operator punctuator punctuator w keyword V oxx\o break { } case char const continue default do double else enum extern float for goto if int long register return short signed sizeof static struct switch typedef union unsigned void volatile while name Letter better digit empty character constant • > integer number enumerator char-const or I {long) •—v—^—v- or u {unsigned) double number y digit .

operator prefix infix postfix other infix prefix & postfix other (type) () [1 sizeof && of an object: constant I variable. array.'* string s^S structure. ] f ? \ o r enumeration name name [ expression ] /= %= <<= >>= &= A - 1= name sizeof ( expression ) expression ( type-name ) ( expression ) expression expression : expression ( type-name ) expression ? ( expression ) 11: SUMMARIES 199 . union.

return goto expression block { declaration statement } program j declaration precisely one declaration must be a definition of main() 200 ILLUSTRATING C . expression . expression ) switch ( expression ) case expression : statement statement default : statement break.statement block if ( expression ) statement while ( expression ) do else statement statement > statement statement statement while ( expression ) . continue. f o r ( expression .

expression } declarator name abstractor empty ( abstractor ) [ expression ] ^^ . } enurn name { name . ( name ) ) type shape abstractor alias 11: SUMMARIES 201 . «.char float long void double (permutations^ allowed shape struct union name name f declaration. ^ ( declaration .

PARAMETER OF A PROTOTYPE DECLARATION declaration \ register type shape alias declarator abstractor I 2(2)2 ILLUSTRATING C .GLOBAL OBJECT declaration extern static type shape alias DECLARATION \ OF OBJECTS ]) OBJECT IN A BLOCK declaration auto extern register static MEMBER OF STRUCTURE OR UNION declaration type shape alias FUNCTION DEFINITION declaration extern static type shape alias DECLARATION (f OF FUNCTIONS)) declarator block PARAMETER OF A FUNCTION DEFINITION declaration register type shape alias declarator Hote: const & volatile omitted from diagrams see Page 137 PROTOTYPE DECLARATION declaration extern static type shape alias declarator .

Ijjach directive must be on a line of its own (J possibly extended by 1 \ j | «J | ]) preceding the program it is to modify PREPROCESSOR preface #define name replacement •define name ( name ) replacement #undef name •include "file" •include < /ile > •line constant fibe l number of ^ next line •if expression preface •elif expression preface •ifdef name preface •ifndef name preface •endif replacement token ( replacement ) 11: SUMMARIES 203 .

h math.h math. assert ( int expression ) . atan2 C double y. time_t if ) . atoi ( const char * s ) . atan C double a ) . int denom ) . math.h math. double x ) .h stdlib.h math. math. stdio.e_t EttSiz ) . stdio.h fclose C FILE * s ) . math. ill 180 181 192 181 172 time.h stdlib. const void*i>. size. ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ bsearchCconst void *k.h cos ( double ar ) . atof ( const char * s ) . time. stdlib.h cosh C double x ) . atexit ( void ( * fun X void ) ) . abs C int n ) . ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ math.h stdlib.__t w.h ctlme C const time_t * I ) timeJi difftime ( time_t ^ .FUHCTION PROTOTYPES IN ALPHABETICAL ORDER Return void in* Function ( Prototypes of parameters ) Header Page stdlib. stdlib.h div ( int nun7.h double char * double void double double int double int long void void * double void clock_t double double char * double div_t void double double FILE * abort C void ) . asin ( double a ) . ascHme ( struct tm * t ) . atol ( const char * s ) .h 178 191 177 180 166 192 181 182 192 193 183 17! 184 int stdio. acos ( double a ) .h stdlib.h feof ( FILE * s ) .h 180 165 204 ILLUSTRATING C .h 182 182 172 178 177 stdlib. comparison}\ calloc C size_t NumEIts.h stdlib. time.h exit ( int status ) .h exp C double a ) . siz.h clearerr ( FILE * s ) clock ( void ) .h fabs ( double d ) . size_t n.h assert.h stdlib.

165 164 167 167 180 183 165 168 164 168 164 177 165 184 169 166 167 167 164 165 165 173 168 193 185 185 186 li: SUMMARIES 205 .h stdio. Freopen ( const char * file.h stdio.h Page 166 double double FILE * int int int size_t void FILE * double int int int long size_t int int char * char * struct tm * int int int ferror ( FILE * s ) .h stdio. FILE * gete ( FILE * s ) ..h stdio. double y ) . FILE * Frexp ( double x.h stdio.h math. Isalpha C int c ) . size_L c. getchar ( v o i d ) . Fseek ( FILE * s. int * p ) .h math. size_t b. . FscanF ( FILE * 5. const fpos_t * p ) . FILE * s ) . Ftell C FILE * 5 ) .h stdlib. Fgets C char * b. fflush C FILE * s ) .h stdio. const char * mode ) . FprlntF ( FILE * s. ^ ^ ^ ^ ^ ^ ^ ^ ^ Fmod ( double x .. Fread ( void * &//. size_t c. Fgetpos ( FILE * s. size_t />.h ctype. FILE * 5 ) . long offset. fwrtte C const void * buF. Free C void * p ) .h stdio. gets ( char * b ) . getenv (const char * Name ) .Return int int int int char * Function ( Prototypes of parameters ) Header stdich stdio.h stdio.h stdio. int origin ) . ) .h stdich stdio.h stdio. gmHme ( const time_t * isalnum C int c ) . int n. Fsetpos C FILE * 5. iscntrL ( int c ) .h math. const char * mode.h stdio. Fputs ( const char * i>. .h stdlib. fgetc C FILE * s ) . fpos_L * c ) ... FILE * s ) .h stdio. Fputc ( int <r.h stdio.h stdich timeJi ctype. Fopen ( const char * File. ) . const char * FmL.h stdio.h ctype. const char * fmt. Floor ( double d ) . FILE * s ) .

log C double a ) .h 185 185 185 186 186 185 185 180 184 183 174 193 184 184 174 177 189 188 188 188 190 193 184 172 180 168 Isgrctpb ( int c ) . Idiv ( long num. Islower ( int c ) . mcmmove C void * bj. memcmp ( const void * si.h math.h stdlib. Isxdlglt C int c ) . ILLUSTRATING C .h stdlib.h strinq. size_t /? ) .h stdich math.h stdlib.h math. p e r r o r ( const char * mess ) . double y ) .h locale. malloc ( size_t bytes ) . isupper ( int c ) .h ctype. int c. const void * s2.h string. pow ( double x. mernchr ( const void * b.h string.h time.h ctype. memcpv ( v o i d * ^ / .h string. Idexp ( double x% int /7 ) . double * p ) . 200. const v o i d * M size_t n ) .h math. size_t n ) .h ctype. int c.. modf ( double d.Return int int int int int int int long double ldiv_t struct Iconv* struct tm * double double void void * void * int void * void * void * time_t double void double int Function (Prototypes oF parameters ) Header Page ctype. const void * b2. labs C long w ) .h math. long denom ) . ispunct ( int c ) .. localeconv ( void ) .h stdio. localHme ( const time t * t ) . prlntf ( const char * fmt.h string. isspace ( int c ) . ) . •onfljrop Cjmp_buf savery int Kfl^/e ) . . mktime ( struct tm * p ) .h ctype. size_t /7 ) .h ctype. size t n ) . togI0 C double a ) . isprJnt C int c ) .h setjmp..h ctype.h time. memse* ( void * b.

h stdfib.h signal.h stdio. scanf ( const char * fmt. puts ( const char * b ) .h locale. rand ( void ) . 171 174 174 170 175 181 182 168 181 182 169 188 189 188 187 11: SUMMARIES 207 . size_t sz (*signal (int sig.. sin ( double ar ) . char * b. sscanf ( const char * b. size_t n. setbuf (FILE * s. const char * s2 ) . ) . raise ( int sig ) . size_t newsiz ) . .h stdlib.h string.h stdich stdio.h stdio.h stdlib. const char * fmt.h math. remove ( const char * file ) . int c ) . ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ sprlntf ( char * p. sqr\ ( double a ) . comparison ) .h stdio. ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ realloc ( void * p. void (* nndlrX'^0 ) ) (int).Function ( Prototypes of parameters ) Header stdio.h signaLh math.h string. srand (unsigned int seed ) .h string. int mode. const char * new ) .h stdio. strcmp ( const char * si. char * b set jmD ( jmp_buF saver ) .h string. rename ( const char * old. setvbuf ( FILE * s. const char * S2 ) . FILE * s ) . const char * locale ) .h stdio. strchr ( const char * s.h stdio. qsort ( void * b. const char * s2 ) strcpy ( char * si. Dutchar ( int c ) . setlocale ( int category.h math. rewind ( FILE * s ) . size_t w. Sinn ( double x ) . const char * strcat ( char * si..h stdlib.h setjmp.h Page 164 164 168 191 175 182 177 166 166 166 169 putc ( int c. .h stdich stdio.

h Page 189 I I ( size_t size_L char * | size_t * char * int char * char * .h ^ 1 8 9 179 stdlib.h stdarg.h 182 Hme. va_list ap ) .h string. const char * s? ) . sfrtol ( const char * 5. Jnt c ) . strncpy ( char * si. size_t n ) . strpbic C const char * sf.har char * :har size_t char double char * long unsigned long in* ~ double double time_t : ILE * . const char * s2 ) .h stdio. va_list ap ) .h string. tupe ) .h string. vfprintf C FILE * . strtod ( const char * s. strlen C const char * s ) . vprintf ( const char * Fmt.h 176 176 169 169 169 stdio.h stdarg. int A3. name ) .Return Function ( Prototypes oF parameters ) Header string. strncmp ( const char * si. toupper ( int c ) .h 170 ctype. vsprintf ( char * p. const char * s2. const char * $2 ) . char * * A int radix ) . const char * $2 ) .?. const char * s2 ) . ILLUSTRATING C math.se ) . sfrrchr ( const char * s. const char * s2. char * * p.h 181 math.h stdio. const char * fmt. va_end C va^list p ) . time C time_t * t ) .h 208 .h stdio.h string. const void * s2.h 186 165 176 stdarg.h 178 stdlib. strncat (char * si. char * * p ) . const char * Fmt.h 173 tolower ( int c ).h string. ungetc ( int c. size_t n). strstr ( const char * J/. va_list ap ) . strtok C const char * sf. strspn ( const char * 5/.h 179 stdlib.h string. FILE * s ) . va_start ( va_list p.h string. tanh ( double x ) .h 189 189 189 189 string. size_t n ) . tan ( double ar ) . strtou) ( const char * s. tmpfile ( void ) .har * nt int int type void void int int int shrcspn ( const char * si.h 186 ctype.h stdlib. v a _ a r g C va_list p. tmDnam C char * nam 190 187 188 188 187 string. strerror ( int n ) .h string. system ( const char * command ) .h ^ 1 9 3 stdich 170 stdio.

It is a joy to read. responding to the feedback and resolving the old ambiguities. & Ritchie. and certainly the best. (Prentice Hall) I^ennis Ritchie invented C. this book is its bible. D.American National Standard f o r Information Systems Programming Language . its syntax. and a list of names of related functions.Cn ANSI X3. B. The second edition shows every sign of professional involvement in its authorship.W. It is not a tutorial text. (Howard W. (1989) The Waite Group s Essential Guide to ANSI C.) TJfhis is a pocket-sized reference to ANSI C. The oook is marked 'ANSI C'. and expensive. During the intervening decade there must have oeen an enormous amount of feedback from readers.159-1989 ijfhe Standard defines the dialect of C presented in this book.159 is worth having if you are going to program seriously in C. National standards can be forbidding documents. an example call. Bakakati. but appended to the Standard is a 'rationale' to explain difficult paragraphs of the Standard and say why certain library functions were included. The description of each library function comprises a short explanation of its purpose. (1988) The C programming Language^ Second edition. book on C (J although not the easiest to read ]) until the second edition was published ten years later. N. but ANSI X3. A useful reference for the practical C programmer. The first edition is dated 1978 and remained the only authoritative. but most of it describes the library. It covers the language and keywords. a description of what it returns. Kernighan. Sams & Co.M. . The document is beautifully organized and the prose intelligible.

196 39. 46. 196 40. 130 alias. 71-2 #else. 196 43. 4. 196 42. 130. 71-2 #ifndef. 172 abs. 36. 196 40. 196 40. 104-5 Backus Naur form. 1. 46. 196 40. 196 41. 196 43. 40-1. 8. 46. 196 41. 46. 46. 8. 46. 46. 20-1. 34. 196 42. 196 41. 39 40. 196 43. 46. 66 #elif. 158-60 bit fields. 72 back-slash. 196 address. 134 area of polygon. 46. 80. 72 #undef. 196 41. 196 42. 181 assert. 129. 196 42. 196 42. 22 acos. 8. 46. 129 39. 46. 80. 46. ill associativity. example. 137 call by value. 36. 75-7. 197 Backslang. 196 42. 3. 191 bubble sort. 69 paster. 13. 133 bits. 33 case statement. example. 46. 182 atan2. upper & lower. 8. 46. 121 C. 46. 178 atoi. 131 Boolean. 46. 46. 196 127. 68. 180 absolute value. see binary digits blocks. 46. 44. 196 logical. 69 39. 196 41. 82 calloc. 38. 196 arrays. 67. 93-4 asctime. 196 44. 46. 16. 59 bsearch. 196 40. 23 = > >= >> >> = ?: A * = 1 1= I I Directives #define. 178 4- ++ += --> / < << << = auto storage class specifier 73-7. 196 I/O. 181 arithmetical. 196 string-izer. HI atoL. 46. 47 atari. 137 Booklist. 46. 196 42. ill atof. 46. 192 asin. 196 42. 12 break statement. 80. 46. 46. 71-2 #if. 46. 58 210 .Italics indicates an ANSI C library function b o l d indicates a keyword of ANSI C Operators 1 Is # # # % %« & && & = * * S5 13. 46. 46. 196 abort. 32. 121-3 trees. old-style. 196 40. 18 bytes. 82. 46. 46. 84-5. 29. 46. 196 42. 46. 31. 209 binary digits. 71-2 #ifdef. 54 arguments. 46. 196 39. 6. 128 automatic versus static. 46. 46. 196 42. 39. 46. ill case. 46. 182 atexit. 196 40. 44. 196 reference. 196 45. 12. 58. 41. 36. 71-2 #endif. 46. 28 bibliography. 33. 80-1 aggregate. 71-2 •include. 88 arithmetical. 133.

23. 149-53 char type. 31. 32. 135 default statement. 165 fgetc. 168 fputc. 27ff concatenation of files. 134 floor* 180 fmod. 134 dynamic storage. 73-7. 31. 52 DOS. 109. 9. 34. 14. 1 8 1 fflush. 31. 37 deckxra\or. 116. 116. 89 pointer. 77 of pointers. see enumeration enumeration. 169 fseek. 20 in header file. 108. 89 continue statement. 33. 166 Database. 116. 59 clearerr. 31. 193 digit. 36. 116. 167 tgets. example. 84. 119 of quoted strings. 166 fsetpos. I43ff concept of. 67 const Qualifier. 183 do statement. 164 free. 1 8 1 ferror. 15. 74 versus declarations. 66 components of C. 167 function prototypes. 165 rgetpos. see if statement enum keyword. 25 fclose. 190 Christmas. 122. 70 tentative. 7. 9. 5 exit. 117. 167 FILE. 95. 171 exp. lid clock. 76 of parameters. 35 extension of name. 197 multi-byte. 122. 123 decisions. 15. 120. 184 expression. 36 control. 134 characters. 184 fscanf. 12-13 declarations complex. 112. 180 chaining. 156 double type. 4 extern storage class specifier. 105. 99. 165 for statement. 67-72 div. 73. 74 style of. 128 fobs. 110 fprintf. 34. 81. 90 in a block. 152 EOF. 29. 48 difftirne. library type. 100. 32. 29. 130 syntax of. 48 named. 6-7. 192 directives. 135 abstract. 99 escape. 30 feof. temporary. 192 closing a file. 81 outside functions. 180 factorial. see prototypes 211 . 5lff cos. 36 defined ( preprocess operator ) 71 definitions function. 33ff character. 197 Euclid's hcf method. 181 cosh. from bop. 119 ceil. 182 dime. 24 execution. 53 sequence. 71 Cats ( utility ). 33. 32. 119 compiler. 121. 7. 144 Q edit. 165 frexp.cast. 5. 168 fread. 145. 29. 102. 120 float type. 118 files. 34. 74 redundant. 53 format. 3. 5 else keyword. 167 ftell. 109. 136-37 typical. 3. 33 literal. 28 command line. 31 versus definitions. 37 demotion. 164 fputs. 137 constants. 14. 183 fopen. 45. 177 freopen. 33. 36. 117 comma list.

preprocessor. 186 isspoce. 185 isprint. 20 pointer to. 29. 23. 180 Ldexp. 184 &y. 185 isLower. 33. 190. 185 iscntrL. 31. 165 getchar. input function. 78 names. 193 Logl0. 165 getenv. 2. 18 of macros. i08. 92 input. 190 IDE. 184 MK. 88 fwrite. 5 object concept of. 13 initialization. 114-5 gets. 190 mktime. 164 . 32. 36 of braces. 8. 30 linker. 134 iongjmp. 194 a name space. 68-9 main. 30. 144 hidden names. 173 GetNext. 184 long type. 23 Hooke's law. 14 counted. 30 nesting of blocks. 52 macros. 6 malloc. 174 goto statement. 4-5 identifier. 107ff \n\ type. 53 of strings. 146 localeconr. 36 object code. 36. 32. 42 label. 37 of loop. 78 L-value. 5. 17 mblen. 30 if statement. 161 moving a file. (3 getc. 112. 118 multi-byte characters. 189 memcmp. 16. 188 memseL. 85 keyword. 185 mbtom:. 174 Loccdtime. 185 isgraph. 38. 186 isupper. 59 hcf. 12. 52 infinite. on bank loan. 66 list processing. 134 interest. 190 memchr. 74 OOP. 69 NULL. 193 /77^/i 184 Monkey-puzzle sort. 30 definition of. 75 212 . 193 183 letters. 31. 185 isaLpha. 168 global scope. 145. 70 heap. 16 of loops. 24 header 3. 177 matrix multiplication. 21 file. 34 in declarations. 22 isaLnum. 121. 74 gmtime. 53 escape from. 190 mbstowcs. 55 indentation. 31. 108. 3. 18 loops. 188 memmove. 198 in macro. 186 isdigit. 185 ispunct. 185 isxdigiL.function. 36. 14 tested. 188 memcpy. 37 global.

7. 46. 80 pointer arithmetic. 181 sin/?. 139-41. 66 syntax of. 47 reference. 181 srand. 8. 166 parameters. 175. 38 precedence & associativity of. 96 names of. 88 declaration of. example ring. I07ff qsort. 146 statement. 62-3. 177 recursion. example. 53 reverse Polish. 191 Qualifier. 112. 8 access. 36 promotion. 154 Roman numerals. 150-3 signal. 44 summaries of. 73-7 remove. 21 parentheses. 34. 170 shape. 38ff sequence. 71. concept of. 12 syntax of. 67 purpose of. 166 return statement. 38 in header files. 69 perror. example. 4 operators. synonym for type short type. 39 demotion & promotion of. 73. 122 realization. 49 arithmetical. 180 power cables. 110 prints 168 program concept of. 23 semicolon. 172 pointee. 88 as pointers. 32. as a block. 1 2 1 scanf. 110. 3. 174 setlocale. 113 sprintf. 4 realloc. 74 of declarations. 117. 164 ring structures. 23. 175 signed type. 43 logical. 169 stacks. 38 assignment. 48 counting of. 166 rename. 47 preprocessing. 196 syntax of. 169 scope. 82 coercion of. 81 to functions. 168 sqrt. 48 prototypes concept of. 134 sin. 60 precedence. 66 print format. 43 organization. 171 setjmp. 31. 145 spacing. 174 setvbuf. 32. example. 88 pow. 109. 34. 36 static storage class specifier. 182 random access. 148 rewind. 65ff output. 168 scan format. 71 preprocessor. 84-5 pointer concept of. 70 punctuators. concept of. 24 register storage class specifier. dynamic.operating system. 156 putchar. 31. 80-1 constant. 90. 36. 67 putC. 2-3 processing. 48-9 incrementing. 128 213 . 118. 7 setbuf. 164 puts. 91 paster. 81 Quicksort. concept of. 134 shortest route. 109. 7. 68 Parlour trick. 129 action of. 31. 117. 73-7. 138. 83 raise. 86-7 parse trees. 37 of variables. see whitespace specifiers. 182 sscanf. 36 compound. in macros. 56 Roses. example. 42 bitwise. conditional. 182 sizeof operator 45.

165 union keyword. 120 zero padding. 60 vertical bars. 69 strings. 102 tentative definition. 187 strpbrk. 31. 49 type-name. 176 vector algebra. 56-7 syntax notation for. 169 wcstombs. 182 temporary files. 189 . 29-46. 66 traversal. 58 symbol-state table. 188 strncmp. 160 trigraphs. 101 printing of. 69 arrays. 74 time. 16 ASQI. 187 strncat. 31. 194 string arguments. concept of. 126-7 usage of. 189 strrchr. 4 toiower. 178 . 188 strncpy. 116 stdout. 190 while statement. 197-203 system. 132 unsigned type. 40 type cast. 67. 32. 67 in scan format. 134 strxrrm. 94 quoted. 101 copying. 130. 72 summary. 108. 176 va-end. 67 strten. 1 6 1 strerror. 186 toupper. 190 subscripts. 159 pre & post order. see cast type. 134 mixed. 36. 1 3 1 tan. 170 token. 190 wctomb. 128 syntax of shape. 15. 189 ^ ^ . Y10. 179 strtout. 187 strcspn. 28 of C. 169 vsprintf. 193 tmpRle. 98 utilities. in strings. 75 void type. 170 tmpnam. 93 length of. 32. 100 pointers. 52 whitespace. 15. 186 translation unit. 134 0 underscore. 128. 134-7 of preprocessor. 92ff comparing. 130. 30 ungetc. 31. 120. 181 tanh. 9. 92 214 . 149. 179 struct keyword. 176 variables. 190 strcpy. 73. 116 strcat. 188 strcolL. 93 terminator. 189 /. 188 strchr. 134 structures concept of. 189 stream. 37 visibility. 36. see arrays switch statement. 173 va-arg. 98 string-iz. 134 pointer to. 5. 134 concatenated. 67. 28 vFprintF. 189 strcmp. 109. 6 v a j i s t ( type ) 96 va^start. 197 truth tables. 29. 134 unions.stdin. 145 volatile qualifier. 137 vprintdf. 169 visibility. 32.er. 189 strspn. 135 typedef statement. 7. concept of. 190 strftime.