c or not c

93
TO C OR NOT TO C, SOME WAYS TO TAME THE BEAST ********************************************* The ’C’ Programming Language, following on a dialect called ’B’, which incidentally did not descend from ’A’ (and certainly not A Programming Language, better known as APL), has taken increasing prominence in the Nineteen Eighties and early Nineties. Were it not for the vast legacy of COBOL Applications still used in business Data Processing, it would be without doubt the most common Programming paradigm. It now underlies all sorts of computing, from Operating Systems, in particular UNIX, but also the Microsoft Windows family, to commercial, mathematical and scientific Packages. For the luddites, it has definitely supplanted BASIC in games Programming. Finally, it forms the base on which the Object Programming Language ’C++’ was built. In fact, ’C++’ represents a straight superset of ’C’, so that its own explosion in the late eighties in no way implies the demise of ’C’ itself. Despite this huge success, the Language betrays its origins as a Systems programming tool. It was meant to reduce the need for Assembler Coding, and its designers did not really consider its suitability for other purposes. The Language goes against several general features of its contemporaries. At times this simply runs against established instincts, but in other areas, I can only describe ’C’ as a large retrograde step. So, my first suggestion has to be ’do you truly need it ?’. If you’ve heard it’s much better than Fortran or Pascal, and you are a competent Programmer in these, than you could do much worse than carry on with them or look into Fortran 90. Certainly, your productivity will not be exposed to the severe drop that accompanies a transition to ’C’, at the very least for an extended learning curve period. For the brave who feel they must become acquainted with this widespread Programming language, this set of lectures will present the key features in the Language, together with advice on avoiding some common pitfalls. 1

Upload: kostadinovladimir

Post on 28-Jan-2016

216 views

Category:

Documents


0 download

DESCRIPTION

C ++ book

TRANSCRIPT

Page 1: C or Not C

TO C OR NOT TO C, SOME WAYS TO TAME THE BEAST

*********************************************

The ’C’ Programming Language, following on a dialect called ’B’, which

incidentally did not descend from ’A’ (and certainly not A Programming

Language, better known as APL), has taken increasing prominence in the

Nineteen Eighties and early Nineties. Were it not for the vast legacy

of COBOL Applications still used in business Data Processing, it would

be without doubt the most common Programming paradigm.

It now underlies all sorts of computing, from Operating Systems, in

particular UNIX, but also the Microsoft Windows family, to commercial,

mathematical and scientific Packages. For the luddites, it has

definitely supplanted BASIC in games Programming. Finally, it forms the

base on which the Object Programming Language ’C++’ was built. In fact,

’C++’ represents a straight superset of ’C’, so that its own explosion

in the late eighties in no way implies the demise of ’C’ itself.

Despite this huge success, the Language betrays its origins as a Systems

programming tool. It was meant to reduce the need for Assembler Coding,

and its designers did not really consider its suitability for other

purposes. The Language goes against several general features of its

contemporaries. At times this simply runs against established instincts,

but in other areas, I can only describe ’C’ as a large retrograde step.

So, my first suggestion has to be ’do you truly need it ?’. If you’ve

heard it’s much better than Fortran or Pascal, and you are a competent

Programmer in these, than you could do much worse than carry on with

them or look into Fortran 90. Certainly, your productivity will not be

exposed to the severe drop that accompanies a transition to ’C’, at the

very least for an extended learning curve period.

For the brave who feel they must become acquainted with this widespread

Programming language, this set of lectures will present the key features

in the Language, together with advice on avoiding some common pitfalls.

1

Page 2: C or Not C

TO C OR NOT TO C - THE PROBLEMS WITH ’C’ - Part 1

=================================================

Difficult Areas and Limitations in ’C’ :

----------------------------------------

- 1/ Program Units - No Subroutines as in Fortran, COBOL or BASIC,

’C’ Sub-Programs only of the Function type,

that is, Returning a Single Value.

- 2/ Arrays - ’C’ only supports Single Dimensional Tables.

So, multi Dimensional Arrays are implemented

as Arrays of one Dimensional Arrays,

which become a Data Type for this purpose.

- 3/ Array Bounds - Array overflows (or underflows) not reported,

by ’C’ Compilers or Run Time Diagnostics.

- 4/ Character Strings - No Blank Padding of Strings, Terminators used,

many problems arise when they’re missing.

- 5/ Input/Output - Formatting is difficult,

Robust Input Validation forces lots of Code.

- 6/ Standards - K&R (Kernighan & Ritchie) or Traditional ’C’

not fully compatible with later ANSI Standard.

Some good features nevertheless :

---------------------------------

- 1/ O/S Integration - Blends very well with UNIX Operating System,

likewise Microsoft ’C’ with PC Platform.

Extensive Libraries of pre-coded Routines.

- 2/ Argument Passing - Great mechanism to pass Arguments to Programs,

much reduces need for small Parameter Files.

- 3/ Dynamic Storage - Dynamic allocation or Memory available.

2

Page 3: C or Not C

TO C OR NOT TO C - THE PROBLEMS WITH ’C’ - Part 2

=================================================

Beside the difficulty of the Language, and its departure from the

paradigms of its contemporaries, another major problem with Programming

in ’C’ lies in the terrible quality of the Compilers.

Deficiencies in ’C’ Compilers :

-------------------------------

- 1/ Syntax Checking - Often, incorrect Syntax not detected.

Input/Output Statements in particular to watch.

- 2/ Consistency - Often, arrangements of main Load Module Blocks

varies depending on hardware,

so a Module running well on one Computer might

hit File Buffer or Memory faults elsewhere.

- 3/ Poor Diagnostics - Few Warning or Error Messages generated.

Compilers poor aids to initial debugging.

- 4/ Interfacing - Mixing ’C’ and other Code, (Fortran, COBOL)

forces weird Naming and Argument conventions.

Only Routines adhering to them can interface

correctly. Few books care to mention this.

3

Page 4: C or Not C

To C or not to C - C Data Representation - Part 1

=================================================

- 1/ Basic Types - ’char’ - Character (Single Char, one Byte).

- ’int’ - Integer (may be only 2 Bytes,

so for Flags or Options).

- ’long’ - " (at least 4 Bytes,

so ok for Calculations).

- ’float’ - Real (limited Precision).

- ’double’ - " (normally 8 Bytes,

best for Calculations).

- 2/ Type Prefixes - ’long’ - ’double’ (may be same as ’double’).

- ’int’ (’long’ alone same).

- ’short’ - ’int’ (may be same as ’int’).

- ’signed’ - ’char’ (Range -127 to +127).

- ’int’ (Default for Integers).

- ’unsigned’ - ’char’ (Range 0 to 255),

- ’int’ (always Positive,

all Bits make Value).

4

Page 5: C or Not C

To C or not to C - C Data Representation - Part 2

=================================================

- 3/ Scope Prefixes - ’auto’ - Local to Unit (inside ’{ }’ set),

Default for in ’{ }’ Declarations,

Transient to given Run of Unit.

- ’const’ - Initialised Variable may be changed,

but not those, so, effectively,

same as ’static’ and of fixed Value.

- ’extern’ - Default on out of ’{ }’ Declarations,

but Prefix needed if in other File.

Note ’auto’ with same Name in a Unit

takes precedence (hides ’extern’).

- ’register’ - Not for Applications Code.

- ’static’ - as ’auto’ for locality,

but Value Saved between Unit Runs.

- In Data Declarations,

place Scope before Variable Type and Prefix,

like ’extern long ll’,

or ’static long double dd’.

- 4/ Conversions - Called ’casts’ or Coercions in ’C’,

quote Target Type in ’()’ Brackets as prefix,

like ’(long) ll’ to force a ’long’ Integer.

5

Page 6: C or Not C

To C or not to C - C Data Representation - Part 3

=================================================

- 5/ Pointers - Reserve memory for an Address of given Data Type.

Generally not a Data quantity, so virtual,

and any actual Data at Address held in Pointer.

Quote without ’*’ to use Address in Pointer,

or with ’*’ to get Data Value,

so called ’dereferencing’ or ’indirection’,

like ’long *ll’ to hold an Integer Address,

’ll’ to get that Address,

and ’*ll’ " " Value at that Address.

- Can Add or Subtract off Pointers,

with resulting arithmetic increment,

of Unit Size of Type attached to Pointer,

and implicit if not explicit use of ’sizeof’,

so ’ll + 1’ = ’ll + sizeof ( long )’.

- Conversions (Casts) off Pointers possible,

with ’*’ Mark after Type in ’()’ Brackets,

like ’(long *) name’ to get Pointer to ’long’.

- Additional Type of ’void’ for Generic Pointers,

for which increments by singly Byte like ’char’.

- Pointers used to address Data Items in Memory,

to get Address of dynamically allocated Memory,

to hold Positions (current, start) in open Files,

but not to move existing Data Items in Memory.

6

Page 7: C or Not C

To C or not to C - C Data Representation - Part 4

=================================================

- 6/ Data Addresses - To get Address of Variable, quote ’&name’,

which gives Location in Memory, not Value there,

like ’&name’ to get Address of ’name’,

or ’ll = &name’ to assign addr. to Pointer.

Memory atomically addressed in Bytes,

containing 8 Binary Bits on modern hardware.

Addresses got via ’&’ Prefix may be incremented,

like Pointers, with similar Increment Size rules,

like ’ll = ( &name + 4 )’, effectively,

’ll = ( &name + 4 * sizeof ( long ) )’,

for address 4 Logical Units off ’&name’.

Note this cannot be used to relocate a Data Item,

so ’&name_1 = &name_2’,

or ’&name = ll’ illegal,

thus Addresses of explicitly declared Data items

may only show on right hand side of ’=’ Signs,

of assignments involving Pointers or Addresses.

7

Page 8: C or Not C

To C or not to C - C Data Representation - Part 5

=================================================

- 7/ Simple Arrays - Single Dimensional only,

Append ’[NN]’ to Declaration (for ’NN’ Items),

or ’[] = { List of Values between Commas };’,

like ’long ll [NN];’

or ’long ll [] = { 1, 2, 3, 4 };’

Note when Values list numbers less than Array,

rest of Items made Zero (or 0.0).

- for Character Arrays only, can also write

’char cc [] = "Set or Chars. in Array";’.

Note Null (’\0’) Added at end of Array.

- Items picked by Offset, from Zero to ’NN - 1’,

not by Subscript, ranging from 1 to NN,

as used in many other Programming Languages,

so First Item = ’name [0]’,

and Last " = ’name [NN - 1]’.

- 8/ Strings - Special form of Character Arrays,

where Memory reserved for Data and its Address,

like ’char *cc = "String_Data";’,

where tail Null (’\0’) added,

and extra Memory Location holds Address ’cc’,

so ’cc’ may receive another ’char’ Address,

unlike ’char c_fixed [] = "String_Data";’.

8

Page 9: C or Not C

To C or not to C - C Data Representation - Part 6

=================================================

- 9/ Structures - In effect, an association of Data Items,

possibly composite and of different Types.

- Introduced via Named Template,

establishing a Data (Variable) Type,

for one or more Declarations of that Type,

each then including all Contents (Items),

like ’struct stdata { char [20] stname , ’,

’ long stfnum , ’,

’ char [40] stfldt };’.

or directly via List of Contents,

followed by Name of Structure Variable,

or list of Names separated by Commas,

like ’struct { char [20] stname , ’,

’ long stfnum , ’,

’ char [40] stfldt } stinst ;’.

Template Format may be followed by Names too,

named Template allowing more later Declarations,

of extra Structures with same Items, or Pointers,

like ’struct stdata stdt01, stdt02 ;’,

or ’struct stdata *stpt01, *stpt02 ;’.

- Initialise Structures like Arrays,

Item Values following Structure Declaration,

like ’struct stdata stdt01 = { "Nstr", ’,

20 , ’,

"Data" } ;’.

- Arrays of Structures possible,

declared with Size following Declaration,

like ’struct stdata stdt01 [NN] ;’.

Put Offset after Structure Name,

to access Items of an Array’s Structure,

like ’stdt01 [nn].stname = "Struct. 1 Data" ;’.

9

Page 10: C or Not C

To C or not to C - C Data Representation - Part 7

=================================================

-10/ More Dimensions - Writing ’type name [N1] [N2] ;’

set up a One Dim. Array of ’N1’ Arrays,

each a One Dim. Array of ’N2’ Basic Types.

- Writing ’type name [N1] [N2] [N3] ;’

set up a One Dim. Array of ’N1’ Arrays,

of ’N2’ One. Dim Arrays of ’N3’ Basic Types.

Can get hard to manipulate,

and can be emulated with single Dimension Array,

like ’long ll [ N1 * N2 * N3] ;’,

with Items referenced via ’ [ n1 * N2 * N3

’ + n2 * N3

+ n3 ] ;’.

- Initialising, note difference between

Single ’{ }’ Set (as if whole Array One Dim.),

and one ’{ }’ Set per Basic (One Dim.) Array,

like ’long ll [3] [2] = { 1, 2, 3, 4 };’,

giving ’ll [0] [0]’ = 1, ’ll [0] [1]’ = 2,

’ll [1] [0]’ = 3, ’ll [1] [1]’ = 4,

’ll [2] [0]’ = 0, ’ll [2] [1]’ = 0,

not ’long ll [3] [2] = { { 1 },

{ 2 }, { 3, 4 } };’,

giving ’ll [0] [0]’ = 1, ’ll [0] [1]’ = 0,

’ll [1] [0]’ = 2, ’ll [1] [1]’ = 0,

’ll [2] [0]’ = 3, ’ll [2] [1]’ = 4.

10

Page 11: C or Not C

To C or not to C - C Data Representation - Part 8

=================================================

-11/ Pointer on Arrays - Array Name quoted with no Offset acts as Pointer,

so with ’long ll [NN];’ Integer Array,

’ll’ = Address of ’ll [0]’,

or ’ll + 1’ = " " ’ll [1]’.

that is ’ll’ = ’&ll [0]’,

and ’ll + 1’ = ’&ll [1]’, or ’( &ll [0]) + 1’.

- Can equate Pointer to Array, but not contrary,

or can use ’[]’ Offsets with Pointers,

but only to get Values (in effect dereferencing),

like ’long *long_pt;’,

’long_pt = ll;’,

or ’long_val = long_pt [2];’

= ’*(long_pt + 2);’,

but not ’ll = long_pt’,

or ’*long_pt [2]’ (use ’*(long_pt + 2)’.

- Key Array/Pointer difference is former fixed,

and represent actual Memory Locations with Data,

whilst latter can change but holds no Memory.

11

Page 12: C or Not C

To C or not to C - Assignments and Operations - Part 1

======================================================

- 1/ Assignment (1) - Statement Syntax ’Target = Value’,

where Value may be absolute, or an Expression,

involving several Operands and Variables.

Data Types on Left and Right sides should match,

but when not, Right hand Side force casted,

to Type on Left. When Left hand Variable smaller,

in terms of number of Bytes (Memory Length),

resulting Value unpredictable.

Conversions of Integer Variables to Floating

give a Zero Mantissa (Decimal Part) to Result,

but Floating to Integer conversion delete Decimals,

so round down Absolute Value of Real Variable,

like ’long lneg = -10 ,’,

’ lpos = 15 ;’,

and ’double dneg = -25.75 ,’,

’double dpos = 25.25 ;’,

give ’lneg = dneg ;’ as ’-25’,

and ’lpos = dpos ;’ as ’+25’,

but ’dneg = lneg ;’ as ’-25.00’,

and ’dpos = lpos ;’ as ’+25.00’.

When Right hand Side exceeds Left in Byte Count,

and Absolute Value within Bounds for Left,

conversion will succeed. Otherwise, unpredictable,

like ’int ii = 15 ;’,

’long ll = -75000 ;’,

and ’float ff = 25.75 ,’,

’double dd = -85000.85 ;’,

give ’ii = ll ;’,

’ii = dd ;’ both uncertain,

and ’ff = dd’ would be uncertain,

when ’dd’ very large,

in terms of Exponent.

12

Page 13: C or Not C

To C or not to C - Assignments and Operations - Part 2

======================================================

- 1/ Assignment (2) - For clarity in reading and checking Code,

can code Casts implicit in assignments explicitly,

without incurring computational penalties,

so with ’int ii ;’,

’long ll ;’,

’double dd ;’,

assign. ’ll = ii ;’,

becomes ’ll = (long) ii ;’,

and ’dd = ll ;’,

becomes ’dd = (double) ll ;’,

or with ’ int ii ;’,

’unsigned int iu ;’,

’double dd ;’,

assign. ’ii = iu ;’,

becomes ’ii = (signed) iu ;’.

- 2/ Arithmetic

Operators - Arithmetic Operations allowed, at least in part,

on all basic Data Types, as well as Pointers,

with : Add : ’+’ (allowed on Pointers),

Subtract : ’-’ ( " " " ),

Multiply : ’*’,

Divide : ’/’,

Modulus : ’%’ (remainder in Integer Divide).

Note Integer Division truncates result,

to highest Integer Value less than Real quotient,

while Modulus given by equivalent Numerator Value,

subtracted off actual Numerator.

13

Page 14: C or Not C

To C or not to C - Assignments and Operations - Part 3

======================================================

- 3/ Implicit Casts

in Arithmetic - When computing Operations, Data Types equalised,

to that of Operand highest in Hierarchy given by :

Top : ’double’ (’long’ then Standard),

’float’,

’long’ (’int’ being implied),

’int’ (’signed’ above ’unsigned’),

Bottom : ’char’ ( " " " ).

Like for Left hand side of Assignments,

can code such implicit Casts explicitly,

for clarity in reading and checking Code,

without incurring computational penalties,

so with ’int ii ; ’,

’long ll ; ’,

’double dd ; ’,

expr. ’ ii * ll ’,

becomes ’(long) ii * ll ’,

and ’ ii * dd ’,

becomes ’(double) ii * ll ’.

Pointer Variables always of same fixed Byte size,

on a given computer system (commonly 4 or 8 Bytes),

but Unit Value in additions or subtractions

as per size of Data Type associated with pointer,

so with ’long *lp ; ’,

’double *dp ; ’,

expr. ’lp + 4 ’,

becomes ’lp + 4 * sizeof (long) ’,

and ’dp - 5 ’,

becomes ’dp - 5 * sizeof (double) ’,

but ’dp + ip ’,

becomes ’dp + ip * sizeof (double) ’.

14

Page 15: C or Not C

To C or not to C - Assignments and Operations - Part 4

======================================================

- 4/ Operator

Precedence - Multiply, Divide and Modulus processed first,

before Add and Subtract, when computing Expressions,

with operations of same Level handled left to right,

but Operations after any Casts or Function Calls.

Use Parenthesis to alter order of execution,

like ’rr = aa + bb * cc * dd - ee / ff ;’,

same as ’rr = aa + ( bb * cc * dd ) - ( ee / ff );’.

In long Expressions,

can make Code clearer by grouping operand anyway,

so no doubt as to order of execution of operations.

- 5/ Operator

Overload - Note Asterisk Symbol (’*’) in dual roles,

as Multiply Operator and Pointer Prefix,

so good to always separate Operators and Operands,

with at least one space, to avoid confusion,

so ’long la ; ’,

’long lb ; ’,

’long *lp ; ’,

mean ’la = la*lb ; ’,

same as ’la = la * lb ; ’,

but ’la = la*lp ; ’,

same as ’la = la * lp ; ’,

with ’lp’ Address Value, not Data (’*lp’).

Note, with Pointers, ’**pp’ and so on legal,

for "Pointer to Pointer" and so on,

so spacing Arithmetic Operators strongly advised.

15

Page 16: C or Not C

To C or not to C - Assignments and Operations - Part 5

======================================================

- 6/ Increment (1) - For Variable as well as Pointers,

Auto Increment or Decrement Operators available,

to add or subtract a Unit from Variable or Pointer.

Operator must be juxtaposed to Variable Acronym,

without any Spaces or Separators in between.

Position on left or right of Acronym important,

with ’ ll++’ : Add 1 to ’ll’,

after computing any expression,

where ’ll’ involved,

called "postfix" Mode,

’++ll ’ : Add 1 to ’ll’,

before computing any expression,

where ’ll’ involved,

called "prefix" Mode,

’ ll--’ : Subtract 1 off ’ll’,

after computing any expression,

where ’ll’ involved,

as for ’++’, "postfix" Mode,

’--ll ’ : Subtract 1 off ’ll’,

before computing any expression,

where ’ll’ involved,

as for ’++’, "prefix" Mode.

So, in expressions,

Prefix Mode Increments take precedence,

while Postfix Increments computed after all of rest.

Note Increments can result in multiple Assignments,

in one Assignment Statement (’Result = Expression’),

with some to Variables in Right hand side,

and not always of same Type as Left hand side,

16

Page 17: C or Not C

To C or not to C - Assignments and Operations - Part 6

======================================================

- 6/ Increment (2) - Increments possible as stand alone Statements,

with Equal (’=’) Sign and Left hand side deleted.

Postfix Mode should be used in such situations.

Increment and Decrement examples :

with ’long la ; ’,

’long lb ; ’,

’long *lp ; ’,

assign. ’la++ ; ’,

same as ’la = ( la + 1 ) ; ’,

assign. ’--la ; ’,

same as ’la = ( la - 1 ) ; ’,

but ’la-- ; ’ clearer here,

and ’lp = --lp ; ’,

same as ’lp = ( lp - 1 ) ; ’,

that is ’lp = ( lp - sizeof (long) ) ; ’,

but ’lb = ++la + 5 ; ’,

same as ’la = ( la + 1 ) ; ’,

then ’lb = la + 5 ; ’,

and ’lb = la-- + 5 ; ’,

same as ’lb = la + 5 ; ’,

then ’la = ( la - 1 ) ; ’.

17

Page 18: C or Not C

To C or not to C - Assignments and Operations - Part 7

======================================================

- 7/ Self Operation - When Assignment Target also in Left hand side,

may write Assignment as ’Operator=’,

and omit Target Variable from Left hand side,

so ’long la ; ’,

’long lb ; ’,

’long lc ; ’,

give ’la += 3 ; ’,

same as ’la = ( la + 3 ) ; ’,

and ’la *= 7 ; ’,

same as ’la = ( la * 7 ) ; ’,

and ’la -= lb / lc ; ’,

same as ’la = ( la - ( lb / lc ) ) ; ’.

Add and Subtract may be used thus with Pointers.

18

Page 19: C or Not C

To C or not to C - Flow Control and Logic - Part 1

===================================================

- 1/ Conditions - Normally presented as ’Expression Operator Value’,

where Value may itself form an Expression,

or the result of executing one or more Statements,

and Logical or Relational Operators specific,

in Set : Equal : ’==’ (not same as ’=’),

Not Equal : ’!=’,

Strictly Greater : ’>’,

Greater or Equal : ’>=’,

Strictly Less : ’<’,

Less or Equal : ’<=’.

Note Parenthesis around Condition(s) compulsory,

and Conditions often called Logical Expressions,

so with ’long la ; ’,

’long lb ; ’,

Test ’(la != lb + 5 )’,

means ’lb’ Value incremented 5 Units,

and matched against ’la’ Value,

neither being actually changed,

However ’( la == lb++ + 5 )’,

means ’lb’ incremented 1 Unit after match,

Likewise ’( la = printf ( "Test" ) > 0 )’

means ’printf’ Message Output attempted anyway,

and Value returned tested against Zero,

usual Return Code from successful Call.

19

Page 20: C or Not C

To C or not to C - Flow Control and Logic - Part 2

===================================================

- 2/ Implicit Casts

in Conditions - When testing Conditions, Data Types equalised,

as when computing Value of Expressions,

to that of Operand highest in Hierarchy given by :

Top : ’double’ (’long’ then Standard),

’float’,

’long’ (’int’ being implied),

’int’ (’signed’ above ’unsigned’),

Bottom : ’char’ ( " " " ).

Like for case of Expression computations,

can code such implicit Casts explicitly,

for clarity in reading and checking Code,

without incurring computational penalties,

so with ’int ii ; ’,

’long ll ; ’,

’double dd ; ’,

cond. ’( ii == ll )’,

becomes ’( (long) ii == ll )’,

and ’( ii > dd )’,

becomes ’( (double) ii > dd )’.

20

Page 21: C or Not C

To C or not to C - Flow Control and Logic - Part 3

===================================================

- 3/ Composite

Conditions - Basic Conditions may be combined into Composites,

with ’&&’ for "And" Logic,

and ’||’ for "Or" " .

Composite Conditions evaluated Left to Right,

unless Parenthesis used to enforce different Order,

so with ’long la ; ’,

’long lb ; ’,

cond. ’( la == lb || la > lb + 12 )’,

same as ’( ( la == lb ) || ( la > lb + 12 ) )’,

meaning ’la’ same as ’lb’ or above ’lb + 12’,

but ’( ( la == lb || la > lb + 12 ) && ’

( lb >= 56 || lb < -24 ) ) ’,

means individual basic Conditions evaluated,

in left to right Order to answer each "Or",

and, last, "Or" outcomes tested for "And".

21

Page 22: C or Not C

To C or not to C - Flow Control and Logic - Part 4

===================================================

- 4/ Basic

Conditionals - Basic Conditional execution of Statements with ’if’,

where syntax ’ if ( Condition ) { Statements }’,

resuming unconditional execution at Block’s end,

so with ’long la ; ’,

’long lb ; ’,

Block ’if ( la != lb + 5 ) { ’,

’ la += 5 ; ’,

’} ’,

’lb *= 12 ; ’,

means ’la’ incremented 5 Units,

when ’la’ not same as ’lb’,

and ’lb’ anyway doubled afterwards.

However ’if ( la == lb++ + 5 ) { ’,

’ la += 5 ; ’,

’} ’,

means ’la’ incremented 5 Units likewise,

but ’lb’ then incremented by 1 Unit anyway.

Likewise ’if ( la = printf ( "Test" ) > 0 ) { ’,

’ printf ( "Error in Printing" ) ; ’,

’} ’,

means Message Output from inside ’if’ Block,

when Output attempt of String "Test" fails,

and non Zero Value returned by ’printf’.

Braces (’{ }’ Pair) optional when single Statement,

to execute Code when Condition satisfied,

otherwise, carry on with Statements after ’if’.

22

Page 23: C or Not C

To C or not to C - Flow Control and Logic - Part 5

===================================================

- 5/ Alternate

Conditionals - Basic Conditional execution of Statements with ’if’,

Optionally, ’else’ Block may be added to an ’if’,

like ’else { Statements }’, where, like for ’if’,

Braces (’{ }’ Pair) optional when single Statement,

to execute Code when ’if’ Condition not satisfied,

so either Code with ’if’ or with ’else’ executed,

before following with Statements after both.

so with ’long la ; ’,

’long lb ; ’,

write ’if ( la = printf ( "%d", lb ) > 0 ) { ’,

’ printf ( "Error in Printing" ) ; ’,

’} ’,

’else { ’,

’ printf ( "Value ’lb’ shows OK" ) ; ’,

’} ’,

so as to pick between Diagnostic Output Options.

Finally, ’else’ Clauses can be juxtaposed to ’if’,

in effect giving one or more ’elseif’ Blocks,

with their own Entry Conditions,

and ’else’ Block still possible last, so,

can test ’if ( la = printf ( "%d", lb ) > 0 ) { ’,

’ printf ( "Error in Printing" ) ; ’,

’} ’,

’else ’,

if ( lb < 0 ) { ’,

’ printf ( "Value ’lb’ negative" ) ; ’,

’} ’,

’else { ’,

’ printf ( "Value ’lb’ positive" ) ; ’,

’} ’.

23

Page 24: C or Not C

To C or not to C - Flow Control and Logic - Part 6

===================================================

- 6/ Nested

Conditionals - Basic ’if’ Conditionals may be Nested in each other,

and Braces (’{ }’ Sets) may be used around them,

to Nest ’if’ Blocks in ’else’ or ’else if’ Blocks.

so with ’long la ; ’,

’long lb ; ’,

can test ’if ( la = printf ( "%d", lb ) == 0 ) { ’,

’ if ( lb >= 1 ) ’,

’ printf ( "’lb’ above 0" ) ; ’,

’ else ’,

’ if ( lb == 0 ) ’,

’ printf ( "’lb’ exactly 0" ) ; ’,

’ else ’,

’ printf ( "’lb’ below 0" ) ; ’,

’} ’.

Note, this same as 3 separate ’if’ Blocks,

with Composite Conditions for Entry,

written ’if ( Value Test && Print Test )’,

so appropriate Message printed in response.

24

Page 25: C or Not C

To C or not to C - Flow Control and Logic - Part 7

===================================================

- 7/ Iterative

Conditionals - When Conditional Code Block may be run many times,

use : ’while’ to test Condition before Entry,

and before next Iteration, Reentry,

that is, before executing Block,

which may thus never be executed,

when Entry Condition false,

’do’ and, after Conditional Block,

’while’ to test Condition after Block,

and after each Iteration, Reentry,

so Block always run at least once,

so with ’long *la ; ’,

’long *lb ; ’,

Block ’while ( la < lb ) { ’,

’ printf ( "Data %d", *la ) ; ’,

’ la++ ; ’,

’} ’,

prints Data Value at Address ’la’,

but only when that below Address ’lb’,

but, ’do { ’,

’ printf ( "Data %d", *la ) ; ’,

’ la++ ; ’,

’} ’,

’while ( la < lb ) ; ’,

prints Data Value at Address ’la’ once,

and then again when ’la’ still below ’lb’.

25

Page 26: C or Not C

To C or not to C - Flow Control and Logic - Part 8

===================================================

- 8/ Loops - As an alternative to ’while’ or ’do while’,

Loop Statement ’for’ available, in general form :

’for ( Statements to execute before first run ; ’,

’ Entry Condition for Run of Block ; ’,

’ Statements to execute after each run ) ’,

’ { Block of Statements controlled by Loop } ’.

When more than single Initial or Post run Statement,

separate individual Statements with Commas,

making exception to normal termination with ’;’.

Note, when Entry Condition not initially met,

Loop only results in execution of pre run Code,

and Block inside never executed, as in ’while’,

when Entry Condition not true.

Most commonly, some Counter set before first run,

tested against some final Value for repeat runs,

and incremented or advanced after each run,

so for ’while’ Block in above examples,

Loop : ’for ( la = lb - 100 ; ’,

’ la < lb ; ’,

’ la++ ; ) { ’,

’ printf ( "Data %d", *la ) ; ’,

’} ’,

gives same effect, assuming ’la = lb - 100 ;’,

before ’la < lb’ Condition tested in ’while’.

Loop constructs clearer than ’while or ’do while’,

when iterated Value used in Conditional test,

to control execution, but ’while’, or ’do while’,

better when Entry Condition not regularly updated.

26

Page 27: C or Not C

To C or not to C - Flow Control and Logic - Part 9

===================================================

- 9/ Loop Control - Given iterations of Conditional Entry Blocks,

or whole iterative Conditional execution,

may be abandoned part way,

with ’continue ’,

to abort current iteration,

and proceed to test whether more needed,

or ’break ;’,

to abort current iteration,

and any other iterations in Loop,

so with ’long *la ; ’,

’long *lb ; ’,

Loop : ’for ( la = lb - 100 ; ’,

’ la < lb ; ’,

’ la++ ; ) { ’,

’ if ( *la < 0 ) ; ’,

’ break ; ’,

’ elseif ( *la == 0 ) ; ’,

’ continue ; ’,

’ printf ( "Data %d", *la ) ; ’,

’} ’,

terminates Loop when either ’la’ same as ’lb’,

or Value addressed by ’la’ becomes Negative,

and only execute ’printf’ when Value non Zero.

27

Page 28: C or Not C

To C or not to C - Flow Control and Logic - Part 10

===================================================

- 9/ Exit Control - At level of current Routine (Program or Function),

immediate termination forced by ’exit ( Retcode )’,

where ’Retcode’ Optional, but Parenthesis needed.

-10/ Branches Seldom seen in modern practise, ’goto Label ;’,

forces unconditional Jump to a given Statement,

where ’Label :’ prefixed to desired Statement,

like ’goto lab ; ’,

...

’lab : la++ ; ’.

-11/ Case Conditions - As an alternative to serial ’else if’ Blocks,

may use ’switch’ Block, with Integer Expression,

and ’case’ Clauses testing it against set Values,

like ’switch ( ex ) { ’,

’ case ex_val_1 : ’,

’ ... Statements ... break; ’,

’ case ex_val_2 : ’,

’ ... Statements ... break; ’,

’ default : ’,

’ ... Statements ... break; ’,

’} ’.

Note, Once a ’case’ Blocks entered,

need a ’break;’ to force completion of ’switch’,

as when omitted, next ’case’ Block executed,

irrespective of Entry condition, and so on,

till a ’break;’ found. Using serial ’if else’,

and ’else’ for ’default’ thus safer usage.

28

Page 29: C or Not C

To C or not to C - Program Units - Part 1

==========================================

- 1/ Programs - Termed and labelled ’main’ in ’C’,

with so named initial Entry Statement,

like ’rtpe main ( ) { Program Code }’,

where ’rtpe’ Type of Return Code,

sent back to Operating System,

or ’void’ when none returned.

’{ }’ Brackets enclose all Statements (Code).

Statements ended by ’;’, can span several Lines,

and generally include any number of Spaces.

- Can use ’exit ( nn );’, at any stage,

to leave a Program there and then,

and provide Return Code ’nn’ to Calling Unit,

likely to be Operating System for Programs,

where ’nn’ Type should match ’rtpe’ above.

- Comments may show anywhere,

between ’/*’ Start and ’*/’ End Markers,

which may span several Lines in File,

like ’/* Variable Declarations */’,

or ’/* Variable Declarations ’,

’ */ ’.

29

Page 30: C or Not C

To C or not to C - Program Units - Part 2

==========================================

- 2/ Directives - Pre-Compiler Directives, flagged with ’#’ Prefix,

may show anywhere, preferably near top of Files.

- Most common Pre-Compiler Directives :

’include’, like ’#include src_file.c’,

to expand additional Source Files,

at this position in Code,

’define’, like ’#define MEMBK 1024’,

normally with Mnemonics in Capitals,

so given Value placed in Code proper,

whenever Mnemonic (Constant) appears,

like ’long l1 [MEMBK] ;’,

or ’long l2 = MEMBK ;’.

- 3/ Prog. Arguments - Can present Command Line Arguments to Programs,

in special Array of (’char’) Strings ’argv [ ]’,

leading it with its Item Count (’int’) ’argc’,

of which ’argv [0]’ File Name of Module.

In that case, Syntax differs between ANSI ’C’,

and Traditional, Kernighan & Ritchie (’K&R’) ’C’,

ANSI ’C’ : ’void main ( int argc, ’,

’ char *argv [ ] ) { } ’,

K&R ’C’ : ’void main ( argc , ’,

’ argv ) ’,

’ int argc ; ’,

’ char *argv [ ] ; { } ’.

Once ’argv’ and ’argc’ included in ’main’,

any number of Arguments allowed on Command Line,

but ’main’ Code need not use any of them,

or can selectively use or ignore some of them.

30

Page 31: C or Not C

To C or not to C - Program Units - Part 3

==========================================

- 4/ Sub-Programs - Internal (nests of) Pairs of ’{ }’

define Local (Inline) Sub-Program Units,

as distinct from Function Sub-Programs,

where Variable Declarations allowed,

local to Statements in Unit (not advised).

Bracing statements executed in Loops,

or as result of ’if’ and ’else’ Clauses,

represents case of this. When Blocks long,

may detach them into separate Functions,

though this implies computational overheads.

Conversely, Function may be turned inline,

to simplify Code and improve execution time,

an optimisation called "Procedure Inlining".

- External Programs invoked from Main, or "called",

always of Function form in ’C’,

in schematic terms, a "Many to One" Mapping,

where "Many" may be Zero, and "One" optional,

so Functions allowed with no passed Arguments,

or (and) no Value returned to calling Unit.

- Functions can call themselves in ’C’,

called "Recursion", needing careful coding,

to avoid infinite self call series.

- Many tasks implemented via Functions in ’C’,

often substituting for Intrinsic facilities,

as found in other Programming languages,

like Fortran or COBOL.

For instance, all Data Input, Output and display,

or basic Character String manipulations,

effected via (standard) Function Call,

as well as all common Mathematical Functions.

31

Page 32: C or Not C

To C or not to C - Program Units - Part 4

==========================================

- 5/ Function Entries

and Prototypes - Entry and First Statement to a Function,

sets Type of returned Value, names Function,

and Declares any (Optional) passed Arguments.

Syntax same as for ’main’ Program Entries,

thus differs in ANSI Standard ’C’ and ’K&R’ ’C’,

ANSI ’C’ : ’long func ( int arg_1, ’,

’ double arg_2 ) { } ’,

K&R ’C’ : ’long func ( arg_1, ’,

’ arg_2 ) ’,

’ int arg_1 ; ’,

’ double arg_2 ; { } ’,

- Called Functions require a Header, or "Prototype",

a Declaration making them known to Compiler,

in all Source Files where they get invoked.

Prototypes same as Entry Statement to Function,

but with ’{ }’ and Code therein replaced by ’;’,

so effectively forming stand alone Statements.

- Prototypes should show outside all Routines,

in Source File(s) where used, including ’main’.

Often copied by ’#define’ Pre-Compiler Directives,

from Outside "Header" Files with ’h’ Extensions.

- Prototype Syntax differs in ANSI Standard ’C’,

and Traditional, Kernighan & Ritchie (’K&R’) ’C’,

ANSI ’C’ : ’long func ( int arg_1, ’,

’ double arg_2 ); ’,

K&R ’C’ : ’long func ( ); ’.

32

Page 33: C or Not C

To C or not to C - Program Units - Part 5

==========================================

- 6/ Ending Functions - Can use ’return ( nn );’

to leave a Function there and then,

where ’ nn ’ optional Returned Value or Code,

passed back to calling Program or Function,

though Function Type should be ’void’ when none.

Likewise, ’exit ( nn );’,

stops whole Program (’main’) and any Functions,

providing Return Code ’nn’ to Calling Unit,

likely to be Operating System for Programs.

- After Function completes Execution,

Resumption of execution of calling Unit,

at Statement following Function call,

unless ’exit’ invoked from inside Function,

to terminate itself, and all Functions,

back up call path to ’main’ Program.

- When End of Code (trailing ’}’ Brace) reached,

without a ’return’ or ’exit’ Statement in Path,

Function terminates, and Calling Unit resumes,

as usual at Statement following Function call,

but with Return Code of unpredictable nature,

unless Function was of ’void’ Type,

where no Return Code then expected.

33

Page 34: C or Not C

To C or not to C - Program Units - Part 6

==========================================

- 7/ Libraries - With Functions providing most facilities in ’C’,

sets, or "Standard Libraries" available,

so via single ’include’ Pre-Compiler Directive,

entire Function sets made known to Programs.

Such ’include’ Directives make Prototypes

for all Functions in a Library available,

with no need to enter them explicitly.

Four major Function Libraries exist, for :

Character String handling (’string’) :

Quite often, but not necessarily,

distinct from lone ’char’ operation.

Allow whole String copying,

or finding Lengths of Strings.

Mathematical Functions (’math’) :

Include Exponentiation (’pow’),

and Trigonometric Functions.

Standard Input and Output (’stdio’) :

Include all File related operations,

as well as Screen Input and Output.

General Functions (’stdlib’) :

Any Function not found in above.

These Libraries may need flagging,

on Command Line, when compiling Source Code,

for example -’lm’ frequently required,

to enable use of Mathematical Library.

Programmers may set additional Libraries,

specific to given Programs, or Packages,

which always need being flagged to Compilers.

34

Page 35: C or Not C

To C or not to C - Program Units - Part 7

==========================================

- 8/ Lib. Inclusion - With basic tasks implemented with Functions,

and no computational cost involved,

useful to provide all Standard Libraries,

with ’include’ Directives, in any Program,

for example with Code :

’/* Called Functions Prototypes ’,

’ * --------------------------- ’,

’ * ’,

’ * Standard Libraries : ’,

’ * ’,

’ * For Maths, Input - Output, ’,

’ * Generics and Char. Strings. ’,

’ */ ’,

’#include <math.h> ’,

’#include <stdio.h> ’,

’#include <stdlib.h> ’,

’#include <string.h> ’,

’/* Specific Libraries : ’,

’ * ’,

’ * Note Names Double Quoted, ’,

’ * rather than between ’< >’, ’,

’ * reserved for Standard Libs. ’,

’ */ ’,

’#include "inacn_.h" ’,

’/* Program Itself Begins. ’,

’ */ ’,

’void main ( int argc , ’,

’ char *argv [] ) ’,

’{ ’,

’ Declarations and Source Code } ’.

35

Page 36: C or Not C

To C or not to C - Program Units - Part 8

==========================================

- 9/ Func. Arguments - Functions usually expect a set total Arguments,

that is, passed Values, when invoked (called),

and these cannot be changed inside Functions,

so called "by value" passing.

However, Arguments may be Pointers (Addresses),

as well as Values of actual Data Variables.

- 10/ Function Result - Functions not forced to return a Result,

with special Type of ’void’ used when no Result,

ANSI ’C’ : ’void func ( long larg ) ’,

’ { Code } ’,

K&R ’C’ : ’void func ( larg ) ’,

’ long arg_1; ’,

’ { Code } ’.

- Function’s Returned Result may go to Variable,

be ignored, or examined in a Conditional Test,

in which case no later use of it possible :

Storing Function Result in Variable ’pw2’,

leaving ’pw1’ unchanged :

’pw2 = pow ( 2.0, (double) pw1 )’.

Testing and discarding Function Result,

(Code from ’fprintf’,

checking Output failure) :

’if ( fprintf ( stderr, "Data :" ) != 0 )’.

As above ignoring and discarding Result :

’fprintf ( stderr, "Data :" )’.

36

Page 37: C or Not C

To C or not to C - Program Units - Part 9

==========================================

- 11/ Pointer usage - To achieve many to many Argument Assignments,

Pass Pointers (Addresses) rather than Values,

so called "by reference" Argument Passing,

where Arguments, that is, Data Addresses fixed,

but contents can be changed inside Function :

so, for Single Arguments :

like ’int arg_1 ; ’,

’double arg_2 ; ’,

’long retv ; ’,

Header :

ANSI ’long func ( int *arg_1, ’,

’ double *arg_2 ); ’,

K&R ’long func ( );’,

Call : ’retv = func ( &arg_1, ’,

’ &arg_2 ); ’.

or, for Array Arguments :

like ’int *arg_1 ; ’,

’double *arg_2 ; ’,

’long retv ; ’,

or ’int arg_1 [NN] ; ’,

’double arg_2 [NN] ; ’,

’long retv ; ’,

Header :

ANSI ’long func ( int *arg_1, ’,

’ double *arg_2 ); ’,

K&R ’long func ( ); ’,

Call : ’retv = func ( arg_1,

’ arg_2 ); ’.

37

Page 38: C or Not C

To C or not to C - Program Units - Part 10

==========================================

- 12/ Memory, Files - Even with Pointers declared in calling Unit,

and presented ’by reference’, with ’&pntr’,

any Memory obtained from Dynamic Allocations,

or Arrays locally declared in a Function,

or Data Files opened inside a Function,

remain purely local to that Function.

So, best to handle Memory Allocations,

and opening and closing Files in Main Programs,

or lower level nested Routines (Functions),

possibly passing attached Pointers to Functions,

where storage or Files to be accessed by them.

- 13/ Array Bounds - When Array bound checks, or Loop processing,

to be carried in called Functions,

should pass Array Size, as well as Data Pointers.

like ’int arg_1 [NN] ; ’,

’double arg_2 [NN] ; ’,

’long retv ; ’,

and : ’retv = func ( arg_1, ’,

’ arg_2, ’,

’ NN ); ’.

38

Page 39: C or Not C

To C or not to C - Dynamic Memory Handling - Part 1

===================================================

- 1/ Pointers only - Memory, by definition is allocated at an Address,

so Targets of Calls must be Pointers.

- 2/ Test outcome - ’NULL’ Valued Pointer Returned when Calls fail.

Must be tested as Location Zero Reserved,

so attempting to set it would fails Program.

When Memory request call successful,

Pointer with Address of allocated Memory Slice.

- 3/ Scope - Same rules as Variables,

only available in Local Routine (’{ }’ Set)

where Memory obtained, and for that given Run,

unless Pointer ’static’ or ’extern’.

- 4/ Size - Dynamic Memory allocation requests (Calls)

involve large Operating System overhead,

as well as programming complications,

so only worthwhile for sizable amounts.

Operating System reserves Memory in Pages,

with a minimum ranging from 512 to 4096 Bytes,

so any lesser request still means a Page given,

though end not formally allocated to Program.

Picking Power of two a good default scheme,

so would have 512, 1024, 2048, 4096 and so on.

On these lines, can pick such multiples,

but of Size of appropriate Data Element,

say a Double Variable, as in examples below,

or a higher level Structure, like an Array.

39

Page 40: C or Not C

To C or not to C - Dynamic Memory Handling - Part 2

===================================================

- 5/ Functions - ’calloc’ - Gets Continuous Slice,

Initialised to Binary Zeros.

- ’free’ - Releases Allocated Slice.

- ’malloc’ - Gets Memory, may be in many Extents.

- ’realloc’ - Can extend Slice off ’malloc’ Call,

in effect ’free’ then ’malloc’,

but copies old contents over.

- 6/ General Method - Best to Declare Pointer of appropriate Data Type,

for receiving actual Address of allocated Memory,

and Integer for size, at start of Source Code,

before any logic or Executable Statements.

This makes it easier to later change them.

- Nevertheless, in Memory request Call,

present Pointer as a Cast (like ’(type *)’),

so reader in no doubt, and additional safety.

- Best code request as an ’if’ Logic Clause,

testing Value of Pointer after Function Call,

entering Conditional when request fails,

and gives Null (Binary or Hexadecimal Zero).

Normal Code execution can thus continue after.

- When request fails,

and this means processing cannot continue,

should Terminate complete Program Unit,

back to Operating System, passing non Zero Value,

often called Return Code. In Programs involving

Data Files, these should be closed, and that

operation checked before abandoning Execution.

- Allocated but not released Memory freed at end,

by Operating System.

40

Page 41: C or Not C

To C or not to C - Dynamic Memory Handling - Part 3

===================================================

- 6/ Function ’calloc’ - Memory, Continuous Slice Allocation, like :

/* Double Precision typed Pointer, to get Address of Storage,

* and (long) Integer to hold actual Units of Memory Allocation.

*/

double *mat ;

long tot_mat = 512 ;

/* Eventual other Declarations, before executable Statements ...

*/

/* Test Result of attempting Contiguous Memory Allocation.

* Pointer Cast here redundant, as Pointer declared as Double,

* but informative for reader, and additional safety.

*/

if ( ( mat = (double *)

calloc ( tot_mat, sizeof (double) ) ) == NULL ) {

/* Send Error Message to Default Output Unit (usually Screen).

*/

fprintf ( stderr,

"\n\nProgram : %s, Contig. Memory Allocate failed",

argv [0] );

/* Terminate complete Program Unit, back to Operating System,

* usually with a non Zero Value (often called Return Code),

* eventually attempting to Close any Data Files still open.

*/

exit ( 9 );

}

/* Normal execution of Program continues from here ...

*/

41

Page 42: C or Not C

To C or not to C - Dynamic Memory Handling - Part 4

===================================================

- 7/ Function ’free’ - Memory, Previously allocated Slice release.

/* Double Precision typed Pointer, for Address of Storage,

* which must be non Null, and result of previous Allocation.

*/

double *mat ;

/* Eventual other Declarations, before executable Statements ...

*/

/* Free previous allocation (result of ’calloc’ or ’malloc’).

*

* Note return value implementation dependent, not worth testing,

* as System should anyway recover Memory at Program completion.

*

* Allocated but not released Memory also released at Completion,

* or upon abnormal termination, again via Operating System.

*/

(double *) free ( mat );

/* Execution of Program continues from here anyway ...

*/

42

Page 43: C or Not C

To C or not to C - Dynamic Memory Handling - Part 5

===================================================

- 8/ Function ’malloc’ - Memory, Slice allocation.

/* Double Precision typed Pointer, to get Address of Storage,

* and (long) Integer to hold actual Units of Memory Allocation.

*/

double *mat ;

long tot_mat = 512 ;

/* Eventual other Declarations, before executable Statements ...

*/

/* Test Result of attempting Memory Allocation.

*

* Note allocated Memory need not be contiguous, but,

* most likely to be when up to a Page and no more asked.

* Use ’calloc’ Function for guaranteed continuous allocation.

*/

if ( ( mat = (double *)

malloc ( tot_mat * sizeof (double) ) ) == NULL ) {

/* Send Error Message to Default Output Unit (usually Screen).

*/

fprintf ( stderr,

"\n\nProgram : %s, Memory Allocate failed",

argv [0] );

/* Terminate complete Program Unit, back to Operating System,

* usually with a non Zero Value (often called Return Code),

* eventually attempting to Close any Data Files still open.

*/

exit ( 9 );

}

/* Normal execution of Program continues from here ...

*/

43

Page 44: C or Not C

To C or not to C - Dynamic Memory Handling - Part 6

===================================================

- 9/ Funct. ’realloc’ - Memory, Slice reallocation (amendment).

/* Double Precision typed Pointer, for Address of Storage,

* and (long) Integer to hold revised Units of Memory Allocation.

*/

double *mat ;

long tot_mat = 512 ;

/* Eventual other Declarations, before executable Statements ...

*/

/* Test Result of attempting Memory Reallocation.

* Note Memory Address either previously allocated and non Null,

* or Null, to in effect make call same as ’malloc’ (new Memory).

*

* Like for ’malloc’ allocation, need not be contiguous.

* Existing Memory contents kept (truncated when reduction).

* Use ’calloc’ Function for guaranteed continuous allocation.

*/

if ( ( mat = (double *)

realloc ( mat,

tot_mat * sizeof (double) ) ) == NULL ) {

/* Send Error Message to Default Output Unit (usually Screen).

*/

fprintf ( stderr,

"\n\nProgram : %s, Memory Reallocate failed",

argv [0] );

/* Terminate complete Program Unit, back to Operating System.

*/

exit ( 9 );

}

/* Normal execution of Program continues from here ...

*/

44

Page 45: C or Not C

To C or not to C - Files And I/O (Input/Output) - Part 1

=========================================================

- 1/ Functions needed - All File handling, Input and Output (I/O),

to Files or otherwise, effected via Functions.

Programs require Standard Libraries,

made known with Pre-Compiler Directives,

before calling I/O Functions possible,

like ’#include <stdio.h>’,

’#include <stdlib.h>’,

’#include <string.h>’.

Strictly, only ’stdio’ (Standard I/O) needed,

but in practice many useful Functions elsewhere.

45

Page 46: C or Not C

To C or not to C - Files And I/O (Input/Output) - Part 2

=========================================================

- 2/ Files - Files accessed via ’FILE’ Data Type,

always attached to Pointer Variables,

representing current Position in open Files,

or result of last operation on File otherwise.

like ’FILE *pfname ;’.

Name given to a ’FILE’ Pointer local to Program,

need not relate to File Name in Operating System,

as these linked when File actually opened.

- Any access to contents, or writing to Files,

conditional on successfully opening Files,

with appropriate Access Mode(s),

except Default Files described below.

On some systems, File Access Rights,

as set on Operating System, may prevent opening,

even when Program not directly violating Rights,

for example "Read Only" Files, may not open,

when "Read Write" specified or implied,

even when Program makes no attempt at Writing.

- Once no more access expected for Files,

good practice to explicitly close them,

this eventually releasing them for other use.

Operating System closes all Files left open,

when Program completes normally or otherwise.

- Once Files opened, Access Modes fixed,

so closing and reopening required to change them.

Any File may be opened and closed many times,

in any given Program run, either explicitly,

or using special ’reopen’ File Function.

46

Page 47: C or Not C

To C or not to C - Files And I/O (Input/Output) - Part 3

=========================================================

- 3 Default Files - As an exception to Files needing opening,

before operations on, or insertion of, contents,

three Default Files (Channels) always available :

’stdin’ = "Standard Input",

’stdout’ = "Standard Output",

’stderr’ = "Standard Error".

- Standard Input usually from User Terminal,

Standard Output and Error to User Terminal,

from which Program itself run when Interactive,

or Batch (Job control) Script controlled Files.

Some Operating Systems allow Channel Redirection,

where a File may be used instead, in which case,

Operating System will open File as required.

- Standard Channels may be assumed open,

Input in "Read" Mode, Output and Error in "Write",

whenever Programs begin execution.

- Standard Channels may be closed,

and sometimes, but not always easily, reopened.

Rewind Operations, and likely repositioning,

illegal, and attempts should produce Error.

- As both Standard Output and Error go to Terminal,

systems which send data via a buffering relay,

only when a given buffer has filled up,

may show Data out of Program sending sequence.

Facilities exist to force Buffer emptying,

or bypassing Buffers when writing to Channels,

but these can prove cumbersome, so using one,

but not both of Standard Output and Error simpler.

47

Page 48: C or Not C

To C or not to C - Files And I/O (Input/Output) - Part 4

=========================================================

- 4/ Basic File

Functions - All File handling Functions use File Pointer,

as first Argument, with eventual Access Code,

as second Argument, when opening File :

’fopen’ - Open File with desired Access Mode,

to get File Pointer to Data Records,

giving File Name as Argument 1,

and Access Mode as Argument 2,

both Char. Strings, where latter :

’r’ for Read (not allowing Write),

’w’ " Write (extant Data lost),

’a’ " Append (Write Data at Tail),

’r+’ for Update (Read and Write),

’w+’ " Update, Read back possible,

’a+’ " Append, Read and Write,

but only at Tail.

Sometimes, ’b’ Suffix Modes supported,

for raw Binary (unformatted) Access,

appended to any of above Modes.

Pointer Value ’NULL’ back when Error,

Data Pointer returned when successful,

like ’pfinp = fopen ( file_name, "r" ) ;’,

’pfout = fopen ( "out.dat", "w" ) ;’.

- ’freopen’ - Close and immediately reopen File,

with same Syntax and Args. as ’fopen’.

- ’fclose’ - Close and release File.

Status Value ’EOF’ back when Error,

Zero when operation successful,

like ’ fclose ( pfinp ) ;’,

’irtc = fclose ( pfout ) ;’.

48

Page 49: C or Not C

To C or not to C - Files And I/O (Input/Output) - Part 5

=========================================================

- 5/ File Position

Functions (1) - Functions allow changes in place of next access,

or query on current Position (Offset) in File,

in terms of Byte Counts from a given Reference :

- ’fseek’ - Set current Position (Offset) in File,

thus allowing Random Access.

Two Arguments following File Pointer,

namely an Offset (possibly Negative),

and a Base Position, which may be :

’SEEK_CUR’ for Current Pos. in File,

’SEEK_SET’ " Top (Start) of Data,

’SEEK_END’ " End (Tail) " " .

Offset (Bytes) added to Base Position,

File Pointer moved, and Zero returned,

or -1 sent back after Error detected,

like ’irtc = fseek

( pfinp, 10, SEEK_CUR ) ;’,

’irtc = fseek

( pfinp, -10, SEEK_END ) ;’.

- ’rewind’ - Rewind File to Top,

as in ’fseek ( fpt, 0, SEEK_SET ) ;’,

like ’ rewind ( pfinp ); ’, or,

’irtc = fseek

( pfinp, 0, SEEK_SET ) ;’.

- ’ftell’ - Obtain current Offset in Bytes,

from Zero at beginning (Top) of File,

for eventual use as ’fseek’ Offset,

like ’offs = ftell ( pfinp ) ;’,

to save current Byte Offset to ’offs’,

but -1 returned when not possible.

49

Page 50: C or Not C

To C or not to C - Files And I/O (Input/Output) - Part 6

=========================================================

- 5/ File Position

Functions (2) - Similarly to ’fseek’, ’rewind’ and ’ftell’,

Function allow changes in place of next access,

but in terms of File Pointer Absolute Value :

- ’fgetpos’ - Get Absolute Pos. (Pointer) in File.

One Argument following File Pointer,

which must be Long (Integer) Pointer,

to receive File Pointer Value,

like ’irtc = fgetpos ( pfinp, fptr ) ;’,

with Zero returned when Pos. obtained,

or a Non Zero Code otherwise.

- ’fsetpos’ - Set Absolute Pos. (Pointer) in File,

for instance to Value from ’fgetpos’,

in effect allowing raw Level Access.

One Argument following File Pointer,

which must be Long (Integer) Pointer,

as provided by ’fgetpos’ Function,

containing Value to set Pointer to,

like ’irtc = fgetpos ( pfinp, fptr ) ;’,

with Zero returned when Pos. achieved,

or a Non Zero Code otherwise.

50

Page 51: C or Not C

To C or not to C - Files And I/O (Input/Output) - Part 7

=========================================================

- 6/ File Status

Functions - Functions allow tests against File states :

- ’feof’ - Checks last Read or Write attempt,

effectively last File Data access,

left File Position at Bottom,

like ’irtc = feof ( pfinp ) ;’,

sending back Non Zero Code when so,

or Zero when not at Tail, or Error.

- ’ferror’ - Checks status of last Data Access,

that is Record Read or Write attempt,

like ’irtc = ferror ( pfinp ) ;’,

giving Non Zero Code when failed,

or Zero when no error in Data I/O.

File Error State, and End Flag,

can be reset with ’clearerr’ Function,

called with ’clearerr’ ( file_ptr );’,

but this not normally recommended,

unless confident problem resolved.

- ’fflush’ - Force any Buffers to be written out,

that is, Data being sent to Hardware,

like ’irtc = fflush ( pfout ) ;’,

giving Error Code ’EOF’ when failed,

or Zero when Buffer(s) emptied out.

51

Page 52: C or Not C

To C or not to C - Files And I/O (Input/Output) - Part 8

=========================================================

- 7/ I/O Categories

and Modes - I/O Function allow Data exchange, with Files,

either a Byte (Character) at a time, or in Batch,

in Raw (Binary) and Formatted Modes with latter.

In Formatted Mode, Char. Strings can act as Files,

allowing Internal Conversions and Data movements.

- 8/ Raw Character

I/O Functions - In Raw Character I/O, Data handled Byte by Byte,

getting or sending out Data via a Char. Variable.

- ’fgetc’

’getc’ : Read 1 Character from File,

like ’fgetc ( "stdin" ) ;’,

to pick 1 Byte (Char.) from ’stdin’.

- ’fputc’

’putc’ : Write 1 Character to File (at End),

like ’fputc ( ’a’, "stdout" ) ;’,

to send Character ’a’ to "stdout".

- ’getchar’ : As per ’fgetc ( "stdin" ) ;’.

- ’putchar’ : As per ’fputc ( "stdout" ) ;’.

- For all Character I/O, Integer Value may be given,

instead of Char. Variable, or Quoted Character,

and Integer Value of Bits in Byte, unsigned,

returned when operation successful, otherwise,

Zero or End of File (’EOF’) results.

52

Page 53: C or Not C

To C or not to C - Files And I/O (Input/Output) - Part 9

=========================================================

- 9/ Raw Batch

I/O Functions - In Raw or Binary Mode, Data handled as Arrays,

or Character Strings of consecutive Bytes (Block),

obtained off, or sent to File without conversion.

- ’fread’ : Obtain Block of Bytes from File,

and assign them to Array, or String,

at Address given as First Argument,

like ’fread ( pntr, itln, totl, file ) ;’,

to pick Block of Length ’itln * totl’,

of ’totl’ Array Items of Size ’itln’,

assigned to Array at Address ’pntr’.

Item Size and Total must be Integers,

and no Data conversions carried out.

- ’fwrite’ : As per ’fread’, but sending out Data,

so copying Array or String to File,

like ’fwrite ( pntr, itln, totl, file ) ;’,

to send Block used in above ’fread’.

- Raw (Binary) I/O Functions return Total Items,

either obtained or sent, which, in case or Error,

becomes less than expected (’totl’) Total.

53

Page 54: C or Not C

To C or not to C - Files And I/O (Input/Output) - Part 10

=========================================================

-10/ String Batch

I/O Functions - In String Character I/O, Data handled with Arrays,

effectively getting or sending out Char. Arrays.

- ’fgets’ : Read ( nn - 1 ) Characters off File,

or to an End of Line or End of File,

whichever comes first,

and append Null String Terminator,

after eventual End of Line or File,

like ’fgets ( pntr, nn, file ) ;’,

to fill Array at ’pntr’ from ’file’.

- ’gets’ : Read Characters from Standard Input,

to first End of Line or End of File,

and append Null String Terminator,

returning Number of Characters read,

like ’fgets ( pntr ) ;’,

to fill Array at ’pntr’ from ’stdin’.

- ’fputs’ : Write Chars. in Array or String,

to first Null which is not sent.

like ’fputs ( pntr, file ) ;’,

to send off ’pntr’ Array to ’file’.

- ’puts’ : Write Characters in Array or String,

to Standard Output, till first Null,

but send End of Line Mark instead,

like ’puts ( pntr ) ;’,

to send Array at ’pntr’ to ’stdout’.

54

Page 55: C or Not C

To C or not to C - Files And I/O (Input/Output) - Part 11

=========================================================

-11/ Formatted Batch

I/O Functions - In Formatted Mode, Data conversions possible,

with assignments to some Variables when reading,

or from Values of some Variables, or Strings,

when writing, in both cases via special Flags,

one for each Variable in Data List.

- ’fscanf’ : Extract Data at current File Position,

where Data Items must be Pointers :

’fscanf ( FILE, "Consts and Format", *List ) ;’,

like ’fscanf ( fileptr,

"%d %d", *dat1, *dat2 ) ;’,

- ’fprintf’ : Send Data at End of File :

’fprintf ( FILE, "Consts and Format", List ) ;’,

like ’fprintf ( fileptr,

"%d %d", dat1, dat2 ) ;’,

- ’sscanf’ : As per ’fscanf’ but off Char. String,

given as Arg. 1, instead of File.

- ’sprintf’ : As per ’fprintf’ but to Char. String,

given as Arg. 1, instead of File.

55

Page 56: C or Not C

To C or not to C - Files And I/O (Input/Output) - Part 12

=========================================================

-12/ Data Format

Descriptors (1) - In Formatted Mode, describe each Variable Value,

and its position in Record sent or read in File,

where Verbatim Text can be intermixed.

Descriptors consist of Percent Prefix,

then one of more Code letters and digits,

telling Data Type (required) and Field layout :

Type Codes : ’c’ = Single Character,

’d’ = Decimal Integer,

’e’, ’E’ = Floating Point Number,

with Exponent,

’f’ = Floating Point Number,

without Exponent,

’g’, ’G’ = Floating Point Number,

shorter of ’e’ or ’f’,

’i’ = Decimal Integer,

’o’ = Octal Integer,

’u’ = Unsigned Decimal Integer,

’x’ = Hexadecimal Integer,

’p’ = Pointer (Address) Value,

’s’ = Character String,

’%’ = Percent Sign itself.

56

Page 57: C or Not C

To C or not to C - Files And I/O (Input/Output) - Part 13

=========================================================

-12/ Data Format

Descriptors (2) - Field layout set by 3, all optional Flags :

Sign Codes : ’+’ = Prepend Plus Sign,

to any Positive Number,

’ ’ = Prepend Space,

to any Positive Number,

’0’ = Zeros, not Spaces,

leading small Numbers,

’-’ = Left Align Numbers.

Minus signs always mark

all Negative Numbers.

Size Codes : ’w.p’ = Field Width at least ’w’,

at least ’p’ Digits sent,

’w’ = As above, without ’p’,

’.p’ = " " , " ’w’.

Long Codes : ’l’ = Long Octal, Int. or Hex,

’L’ = Long Float (Double).

Examples : ’%+6.3d’ = Sign, at least 6 Chars,

and at least 3 Digits,

’% 10Lf’ = Minus or Space,

and 10 Space Double,

so 9 Digit and Dec. Point,

’%.12s’ = First 12 Chars of String.

Special facilities exist to restrict input,

using Character Sets in Square Brackets (’[ ]’),

to only those Characters. Can be confusing,

and best left to special Filter Function.

57

Page 58: C or Not C

To C or not to C - Files And I/O (Input/Output) - Part 14

=========================================================

-13/ Character String

Functions (1) - String Copy, comparison and searches possible,

and also length queries and data transformations.

- ’strcat’ : Concatenates two Strings,

just like appending Arg. 2 to Arg. 1,

like ’strcat ( chst1, chst2 ) ;’,

where ’chst1’, ’chst2’ Char. Pointers.

- ’strcmp’ : Compares two Character Strings,

returning Zero when both same,

Negative when Arg. 1 less than Arg. 2,

in System’s lexicographical terms,

Positive when the reverse.

like ’strcmp ( chst1, chst2 ) ;’,

to test String ’chst1’ versus ’chst2’,

relative to Collating Sequence.

- ’strcpy’ : Copy Second String Arg. to First one,

like ’strcpy ( chst1, chst2 ) ;’,

to copy ’chst2’ Data over to ’chst1’.

- Length limited Functions for above tasks exist,

with ’strn’ Prefixes, to pick at most ’nn’ Chars,

as set by third (Integer) Arg. to Syntax above,

like ’strncat ( chst1, chst2, nn ) ;’,

’strncmp ( chst1, chst2, nn ) ;’,

’strncpy ( chst1, chst2, nn ) ;’,

to use only ’nn’ Chars. from ’chstr2’.

58

Page 59: C or Not C

To C or not to C - Files And I/O (Input/Output) - Part 15

=========================================================

-13/ Character String

Functions (2) - ’strchr’ : Get Address of a Character in String,

like ’strchr ( chst1, ’c’ ) ;’,

for Address of first ’c’ in ’chst1’,

or a Null when no Char. ’c’ found.

- ’strlen’ : Obtain Data Length in String,

not counting Terminating Null,

like ’strlen ( chst1 ) ;’,

to get Total Chars. up to first Null,

in String at Address Pointer ’chst1’.

- ’strpbrk’ : Get Address of first of a Char. Set,

like ’strpbrk ( chst1, chst2 ) ;’,

for Addr. of first Char. from ’chst2’,

whatever its position, in ’chst1’.

- ’strspn’ : Length in String with Chars. in Set,

like ’strspn ( chst1, chst2 ) ;’,

for Length of ’chst1’ portion,

with only Chars. found in ’chst2’,

or Pos. of first Char. not in ’chst2’,

with 1 subtracted.

Use ’strcspn’ to get same as ’strspn’,

but considering Chars. not in a Set.

- ’strstr’ : Check one String found in another,

like ’strstr ( chst1, chst2 ) ;’,

for Addr. of first ’chst2’ in ’chst1’,

or a Null when ’chst2’ not in ’chst1’.

59

Page 60: C or Not C

To C or not to C - Files And I/O (Input/Output) - Part 16

=========================================================

-14/ I/O Redundancies - Lots of redundancy, and Formats in I/O Functions,

so better to use ’File’ (’f’ Prefixed) Functions,

even for Standard Channels, to retain consistency.

Also, invoke only one of ’stdou’ and ’stderr’,

to avoid eventual synchronisation problems,

which equates ’scanf’ and ’printf’ to :

’fscanf ( stdin, "Consts, Format", *List ) ;’,

’fprintf ( stderr, "Consts, Format", List ) ;’,

like ’fscanf ( stderr, %ld", &irtc ) ;’.

’fprintf ( stderr,

"\nRet = %ld", irtc ) ;’.

Note even with Standard Channel (’stdin’),

Data input Variable(s) List must be Pointers.

- Note ’fscanf’ locks in loop with invalid Numerics,

so Input Data as ’char’ String(s),

then invoke ’sscanf’ against Validated Data.

-15/ Data Validation - Numeric Data first Input to Character Strings,

then Converted, once checked for validity.

In File I/O Example below, Data file scanned,

for expected Double Precision (’double’) contents.

Additionally, basic File Statistics computed.

Each Field checked to hold Numerics,

and to contain only valid Characters.

When no more Fields, check File Pointer at End,

then Rewind File for eventual use in calling Unit.

60

Page 61: C or Not C

To C or not to C - Files I/O Example - Part 1

=============================================

/* Function : Scan and Basic Statistics for Real Data File

* *******************************************************

*

* Function reads through Data File passed in Open State at call,

* checking all Data of expected Floating Point (Real) Format,

* and then computing Basic Statistics (Average, Sample Variance,

* Minimum and Maximum), of which Addresses part of Call Args.

*

* End of File consistency check carried out, before rewinding,

* so File Pointer returned as found, at beginning of Data File.

* When no more Data can be read, but File not found at Bottom,

* direct Termination of Program, with Negative Code to System.

*

* When File not found at beginning Offset before Data checks,

* warning issued, and Rewind to Top then attempted by Function.

* Message sent to Standard Error Channel, at first Data Error,

* or when Rewind fails, before ending with Negative Ret. Code.

*

* Arguments : Values from Calling Unit :

*

* - 11/ ’*pfinp’ = Data File Pointer,

* - 12/ ’*descrip’ = String for File description,

* to identify File in Messages.

*

* Pointers for Values set in Function :

*

* - 21/ ’*tot_val’ = Count of Values in File,

*

* - 22/ ’*val_min’ = Minimum Value found in File,

* - 23/ ’*val_max’ = Maximum " " " " ,

* - 24/ ’*avg_val’ = Average of File Data Values,

* - 25/ ’*var_val’ = Sample Variance of File Data,

*

* - 26/ ’**mess’ = Error Message Address.

*

* Function conforms to ANSI Standard ’C’ definition,

* but for "Traditional" (K. and R. ’C’) style, sole change,

* in Entry Line, to Arg. specifications before opening ’{’.

*/

61

Page 62: C or Not C

To C or not to C - Files I/O Example - Part 2

=============================================

/* Constant and Library Directives :

* ---------------------------------

*/

/* Constant, for Input String Length and Messages.

*/

#define LL 80

/* Standard ’C’ Libraries for Input/Output.

*/

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

62

Page 63: C or Not C

To C or not to C - Files I/O Example - Part 3

=============================================

/* Function : Scan Real Data File, for Format and Range checks

* -----------------------------------------------------------

*/

int fckdou ( FILE *pfinp ,

char *descrip ,

long *tot_val ,

double *val_min ,

double *val_max ,

double *avg_val ,

double *var_val ,

char **mess )

{

/* Local Variables for File Check Function :

* -----------------------------------------

*/

/* Error Message and Data Input Strings.

*/

char errms [LL] ,

inpt [LL] ;

/* Local Variables for File Statistics,

* namely Sum and Sum of Squares of Data Values,

* current Value and transient for computations.

*/

double in_sum ,

in_ssq ,

in_val ,

tv_dou ;

/* Return Code for Local I/O Function Calls.

*/

int irtc ;

63

Page 64: C or Not C

To C or not to C - Files I/O Example - Part 4

=============================================

/* Executable Part for Data File Check Function :

* ----------------------------------------------

*/

/* Find out Current (Byte) Offset in Data File,

* which should be Zero when at Top, as expected,

* and when different, report with Message, then,

* attempt Rewind of File to beginning of Data.

*/

if ( irtc = ftell ( pfinp ) != 0 ) {

fprintf ( stderr,

"\n\nData File not at start (Zero Offset)" );

fprintf ( stderr,

"\n\nData File repositioned to beginning" );

if ( irtc = fseek ( pfinp, 0L, SEEK_SET ) != 0 ) {

fprintf ( stderr,

"\n\nPre-check File Rewind failed" );

return ( 01 );

}

}

/* Initialise Total (number of) Values Input from File.

*/

*tot_val = 0;

64

Page 65: C or Not C

To C or not to C - Files I/O Example - Part 5

=============================================

/* Request and Check single String, and check valid Number,

* exiting verification process when error or end of file.

*/

while ( irtc = fscanf ( pfinp, "%s", inpt ) == 1 ) {

/* First, get Pointer to First Digit in Data String,

* in effect checking some Digits present in Data,

* and implying Value not Numeric when no Digits found.

*/

if ( strpbrk ( inpt, "0123456789" ) == NULL ) {

sprintf ( errms,

"%s : Non numeric data at value %ld",

descrip, ( *tot_val + 1 ) );

*mess = errms;

return ( 11 );

}

else {

/* Once (some) Digits found in Input Data String,

* check no invalid Characters mixed in, that is,

* no non Digits, Sign, Dec. Point, Space or Tabs.

*/

if ( strspn ( inpt, "0123456789-. \t" )

< ( strlen ( inpt ) - 1 ) ) {

sprintf ( errms,

"%s : Illegal chars in value %ld",

descrip, ( *tot_val + 1 ) );

*mess = errms;

return ( 12 );

}

}

/* ’while’ Loop continued on next Page ...

*/

65

Page 66: C or Not C

To C or not to C - Files I/O Example - Part 6

=============================================

/* ’while’ Loop continued from previous Page ...

*/

/* Valid Numeric Data converted to (Double) Floating Point.

*/

sscanf ( inpt, "%lf", &in_val );

/* With valid numeric value, increment total, then,

* add to sum and squares sum, and check for Range extremes,

* but when only on First Value in File, initialise these.

*/

(*tot_val)++;

if ( *tot_val > 1 ) {

in_sum += in_val;

in_ssq += in_val * in_val;

if ( in_val > *val_max ) *val_max = in_val;

if ( in_val < *val_min ) *val_min = in_val;

}

else {

in_sum = in_val;

in_ssq = in_val * in_val;

*val_max = *val_min = in_val;

}

}

66

Page 67: C or Not C

To C or not to C - Files I/O Example - Part 7

=============================================

/* Once all Data input, must be at end of File.

* Direct Termination when not, as File inconsistency.

*/

if ( irtc = feof ( pfinp ) == 0 ) {

fprintf ( stderr,

"\n\nData File not at end after all Input\n" );

exit ( -1 );

}

/* Once all Data Points input, rewind Data File,

* by placing pointer, with offset zero, at top of File.

* When Error, send Error signal back to calling Routine,

* which may reattempt Rewind, or Terminate Program.

*/

if ( irtc = fseek ( pfinp, 0L, SEEK_SET ) != 0 ) {

fprintf ( stderr,

"\n\nData File Rewind error after Data Check" );

return ( 21 );

}

67

Page 68: C or Not C

To C or not to C - Files I/O Example - Part 8

=============================================

/* Compute Mean and Sample Variance of values in Data File.

*/

if ( *tot_val > 0 ) {

tv_dou = (double) *tot_val;

*avg_val = ( in_sum / tv_dou );

/* Variance only computed when several Values in File.

*/

if ( *tot_val > 1 ) {

*var_val = ( ( in_ssq

- tv_dou * *avg_val * *avg_val )

/ ( tv_dou - 1.0 ) );

}

else {

*var_val = 0.0;

}

}

else {

/* All File Statistics Zero when no Data in File.

*/

*val_max = *val_min

= *avg_val

= *var_val = 0.0;

}

/* Return to calling Routine once File processed.

*/

return ( 0 );

}

68

Page 69: C or Not C

To C or not to C - Program Example - Part 1

============================================

/* Program reformats Yield Curve Points Data.

*

* Yield Curve Data from U.S. Federal Reserve Board shows Dates,

* and gives associated Maturities of U.S. Government Bonds (debt),

* but only in computationally inconvenient plain text Headings.

* So, delete those Dates and write out Maturities in Output File,

* in numeric decimal format and preceding each interest rate Value,

* as read in second Input File. Heading Lines Input also cleared.

*

* Program, first passes through Data to check Format as expected,

* operation being carried with special Check Routine ’fckdou’,

* which also presents basic Data Statistics when all Data valid.

*

* Output then in form usable by graphics or statistical utilities.

*

* Files : -1/ Input (Federal Reserve) Interest Rate Data,

* -2/ Output reformatted Maturities and Rates Data,

* -3/ U.S. Bond Maturities Data (Input).

*

* Routines : ’fckdou’ = Pass and Check Double Precision Data,

* and compute basic File Statistics.

*

* Standard : Program written as per ANSI (1989) ’C’ Standard,

* but so only Entry (’main’) Statement needs changing,

* to compile under "Traditional" ("K & R") ’C’ Style.

*/

69

Page 70: C or Not C

To C or not to C - Program Example - Part 2

============================================

/* Definitions and Libraries :

* ---------------------------

*/

/* Default Input, Maturities and Output File Names.

*/

#define DEF_INP "ycvinp.dat"

#define DEF_MAT "ycvmat.dat"

#define DEF_OUT "ycvout.dat"

/* Default Input and other Text String Length (Bytes).

*/

#define LL 80

/* Standard ’C’ Programming Libraries.

*/

#include <math.h>

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

/* Called Functions Prototypes (Headers).

*/

#include "fckdou.h"

70

Page 71: C or Not C

To C or not to C - Program Example - Part 3

============================================

/* Program : Yield Curve Data reformat

* ***********************************

*/

void main ( int argc ,

char *argv [] )

{

/* File Pointers for Input, Maturities and Output.

*/

FILE *pfinp ,

*pfmat ,

*pfout ;

/* File Name Strings for Input, Maturities and Output.

*/

char finp_name [LL] ,

fmat_name [LL] ,

fout_name [LL] ;

/* Generic File Name Input, Prompt Reply and Error Strings.

*/

char *fptr_name ,

inpt [LL] ,

*mess = "" ;

71

Page 72: C or Not C

To C or not to C - Program Example - Part 4

============================================

/* Maturities Array Pointer and individual Yield Variable.

*/

double *mat ,

yel ;

/* Input (Interest Rate) Data File Basic Statistics,

* with Average, Maximum and Minimum and Sample Variance.

*/

double avg_mat ,

max_mat ,

min_mat ,

var_mat ;

/* Generic Function Return Code (for checking for Errors).

*/

int irtc ;

/* Generic Loop Counter, Total Maturities and Yield Curves.

*/

long ii ,

tot_mat = 0 ,

tot_yel = 0 ;

72

Page 73: C or Not C

To C or not to C - Program Example - Part 5

============================================

/* Mark beginning of execution.

*/

fprintf ( stderr, "\n\nYield Curve Data reformat" );

fprintf ( stderr, "\n*************************" );

fprintf ( stderr, "\nTo Quit at any point Hit CTRL/C" );

/* When first Command Argument, Input Data File Name.

* Otherwise, request name Entry and check for Default.

*/

if ( argc > 1 ) {

fptr_name = argv [1];

}

else {

fprintf ( stderr, "\n\nEnter Input Data File Name " );

fprintf ( stderr, "\n (Default = "DEF_INP") : " );

fgets ( inpt, LL, stdin );

if ( strlen ( inpt ) <= 1 ) {

fptr_name = DEF_INP;

}

else {

fptr_name = strtok ( inpt, " \t\n" );

}

}

/* Assign Input File Name off Generic Name Input String.

*/

sprintf ( finp_name, "%s", fptr_name );

73

Page 74: C or Not C

To C or not to C - Program Example - Part 6

============================================

/* When second Command Argument, Output Data File Name.

* Otherwise, request name Entry. Then open named File.

*/

if ( argc > 2 ) {

fptr_name = argv [2];

}

else {

fprintf ( stderr, "\n\nEnter Output Data File Name " );

fprintf ( stderr, "\n (Default = "DEF_OUT") : " );

fgets ( inpt, LL, stdin );

if ( strlen ( inpt ) <= 1 ) {

fptr_name = DEF_OUT;

}

else {

fptr_name = strtok ( inpt, " \t\n" );

}

}

/* Assign Output File Name off Generic Name Input String.

*/

sprintf ( fout_name, "%s", fptr_name );

74

Page 75: C or Not C

To C or not to C - Program Example - Part 7

============================================

/* When third Command Argument, Maturities Data File Name.

* Otherwise, request name Entry. Then open named File.

*/

if ( argc > 3 ) {

fptr_name = argv [3];

}

else {

fprintf ( stderr, "\n\nEnter Maturities File Name " );

fprintf ( stderr, "\n (Default = "DEF_MAT") : " );

fgets ( inpt, LL, stdin );

if ( strlen ( inpt ) <= 1 ) {

fptr_name = DEF_MAT;

}

else {

fptr_name = strtok ( inpt, " \t\n" );

}

}

/* Assign Maturities File Name off Generic Name Input String.

*/

sprintf ( fmat_name, "%s", fptr_name );

75

Page 76: C or Not C

To C or not to C - Program Example - Part 8

============================================

/* Attempt opening Input Data File,

* with immediate termination when Error.

*/

if ( ( pfinp = fopen ( finp_name, "r" ) ) == NULL ) {

fprintf ( stderr, "\n\nInput Data File Open failed," );

fprintf ( stderr, " check File exists\n" );

exit ( 01 );

}

/* Attempt opening Output Data and Maturities Files,

* with Input closure and immediate termination when Error.

*

* Once Termination Block entered, Input File closed directly,

* while Output File needs no closure as opening failed.

*/

if ( ( pfout = fopen ( fout_name, "w" ) ) == NULL ) {

fprintf ( stderr, "\n\nOutput Data File Open failed," );

fprintf ( stderr, " check creation possible\n" );

fclose ( pfinp );

exit ( 02 );

}

76

Page 77: C or Not C

To C or not to C - Program Example - Part 9

============================================

/* Attempt opening Input Maturities File,

* with other Files closed and immediate termination when Error.

*/

if ( ( pfmat = fopen ( fmat_name, "r" ) ) == NULL ) {

fprintf ( stderr, "\n\nMaturities File Open failed," );

fprintf ( stderr, " check File exists\n" );

fclose ( pfinp );

fclose ( pfout );

exit ( 03 );

}

/* Scan and check Maturities (expected in Years) before input,

* with outside Function (all values must be valid numbers).

* Total values, min. max. average and variance returned, but,

* Output message and quit when non Zero Code flags an Error.

*/

irtc = fckdou ( pfmat , "Maturities File",

&tot_mat, &min_mat, &max_mat,

&avg_mat, &var_mat, &mess );

if ( irtc != 0 ) {

fprintf ( stderr, "\n\nMaturities File Data error : " );

fprintf ( stderr, "\n\n%s",

mess );

fclose ( pfinp );

fclose ( pfout );

fclose ( pfmat );

exit ( 04 );

}

77

Page 78: C or Not C

To C or not to C - Program Example - Part 10

============================================

/* Get Memory for Maturities.

*/

if ( ( mat = (double *)

malloc ( tot_mat * sizeof (double) ) ) == NULL ) {

fprintf ( stderr, "\n\nMaturities Memory Alloc. error\n" );

fclose ( pfinp );

fclose ( pfout );

fclose ( pfmat );

exit ( 11 );

}

/* Copy valid Maturities from File to Local Array.

*

* Note use of Array Notation with Pointer to Array.

*/

for ( ii = 0; ii < tot_mat; ii++ ) {

if ( ( irtc = fscanf ( pfmat, "%lf", &mat [ii] ) ) != 1 ) {

fprintf ( stderr,

"\n\nMaturity Value No. %ld input error\n",

( ii + 1 ) );

fclose ( pfinp );

fclose ( pfout );

fclose ( pfmat );

exit ( 12 );

}

}

78

Page 79: C or Not C

To C or not to C - Program Example - Part 11

============================================

/* Once Data held in array, release Maturities File.

*/

if ( ( irtc = fclose ( pfmat ) ) == EOF ) {

fprintf ( stderr, "\n\nMaturities File close failed\n" );

fclose ( pfinp );

fclose ( pfout );

exit ( 13 );

}

/* Present Maturities summary after successful scan and Input.

*/

fprintf ( stderr, "\n\nMaturities Summary :" );

fprintf ( stderr, "\n--------------------" );

fprintf ( stderr, "\n\nFile : %s ",

fmat_name );

fprintf ( stderr, "\nTotal Values : % 6ld",

tot_mat );

/* When no valid Maturities, exit with error message.

*/

if ( tot_mat <= 0 ) {

fprintf ( stderr, "\n\nNo valid Maturity Values found\n" );

fclose ( pfinp );

fclose ( pfout );

exit ( 14 );

}

79

Page 80: C or Not C

To C or not to C - Program Example - Part 12

============================================

/* Bypass Header Lines in Input Yield Data File.

*/

for ( ii = 0; ii < 2; ii++ ) {

irtc = ’ ’;

while ( irtc != ’\n’ ) {

irtc = fgetc ( pfinp );

}

}

/* Pick successive Yield Curves (one per Line).

*

* End of File used as Loop repeat Condition,

* but exit likely with trying Input of fresh Line,

* so at stage of discarding unwanted Date Field.

*/

while ( irtc != EOF ) {

/* Bypass ’DD/MM/YY’ Date Field, by picking Char. String,

* which Date Field represents due to Slashes (’/’) present,

* and not assigning it, thus merely advancing File Pointer,

* ready to read in Numeric (Interest) Values following.

* Hitting End of File forces File Input Loop to end.

*/

if ( ( irtc = fscanf ( pfinp, "%*s" ) ) == EOF ) {

break;

}

/* Loop (’while’) continued ...

*/

80

Page 81: C or Not C

To C or not to C - Program Example - Part 13

============================================

/* ... Yield Curves processing, continued Loop (’while’).

*/

/* Pick each Yield Curve Data Point from File,

* and copy Maturity and Yield to Output File.

*/

for ( ii = 0; ii < tot_mat; ii++ ) {

if ( ( irtc = fscanf ( pfinp, "%lf", &yel ) ) != 1 ) {

fprintf ( stderr,

"\n\nYield Curve point input error\n" );

fclose ( pfinp );

fclose ( pfout );

exit ( 21 );

}

if ( ( irtc = fprintf ( pfout,

"% 6.2lf % 6.2lf ",

mat [ii], yel ) ) < 0 ) {

fprintf ( stderr,

"\n\nYield Curve point output error\n" );

fclose ( pfinp );

fclose ( pfout );

exit ( 22 );

}

}

/* Loop (’while’) continued ...

*/

81

Page 82: C or Not C

To C or not to C - Program Example - Part 14

============================================

/* ... Yield Curves processing, continued Loop (’while’).

*/

/* Output Carriage Return on Completed Yield Curve Line.

*/

if ( ( irtc = fprintf ( pfout, "\n" ) ) < 0 ) {

fprintf ( stderr,

"\n\nYield Curve Line end output error\n" );

fclose ( pfinp );

fclose ( pfout );

exit ( 23 );

}

/* Once Current Yield Curve successfully written to Output,

* add to Total Curves processed (and Current Curve number).

*/

tot_yel++;

}

82

Page 83: C or Not C

To C or not to C - Program Example - Part 15

============================================

/* Once Yield Curve Data copied to output with Maturities,

* close and (thus) release Input Data and Output Files.

*/

if ( ( irtc = fclose ( pfinp ) ) == EOF ) {

fprintf ( stderr, "\n\nInput File close failed\n" );

fclose ( pfout );

exit ( 31 );

}

if ( ( irtc = fclose ( pfout ) ) == EOF ) {

fprintf ( stderr, "\n\nOutput File close failed\n" );

exit ( 32 );

}

/* Present Data summary after successful copy to Output File.

*/

fprintf ( stderr, "\n\nInput Yield Curve Data Summary :" );

fprintf ( stderr, "\n--------------------------------" );

fprintf ( stderr, "\n\nInput File : %s ",

finp_name );

fprintf ( stderr, "\nOutput File : %s ",

fout_name );

fprintf ( stderr, "\nTotal Lines : % 6ld ",

tot_yel );

/* Send completion message before exit.

*/

fprintf ( stderr, "\n\n**** Reformat completed ****\n\n" );

}

83

Page 84: C or Not C

To C or not to C - Program Example - Part 16

============================================

Input (Interest Rates in per cent) Data File to Program :

---------------------------------------------------------

TREASURY YIELD CURVE RATES FOR JAN 1991

Date 3-mo 6-mo 1-yr 2-yr 3-yr 5-yr 7-yr 10-yr 30-yr

01/02/91 6.66 6.73 6.74 7.08 7.30 7.59 7.90 7.97 8.14

01/03/91 6.64 6.71 6.72 7.08 7.27 7.56 7.86 7.93 8.11

01/04/91 6.73 6.82 6.83 7.17 7.37 7.65 7.94 8.02 8.20

01/07/91 6.71 6.84 6.84 7.20 7.43 7.75 8.04 8.13 8.32

01/08/91 6.64 6.74 6.75 7.15 7.39 7.74 8.06 8.16 8.37

01/09/91 6.44 6.61 6.68 7.10 7.46 7.81 8.12 8.25 8.46

01/10/91 6.40 6.57 6.64 7.14 7.39 7.76 8.02 8.16 8.37

01/11/91 6.34 6.55 6.62 7.14 7.40 7.79 8.06 8.20 8.39

01/14/91 6.24 6.47 6.60 7.18 7.44 7.82 8.09 8.23 8.41

01/15/91 6.23 6.44 6.60 7.16 7.43 7.79 8.07 8.22 8.41

01/16/91 6.22 6.46 6.61 7.21 7.47 7.83 8.09 8.24 8.40

01/17/91 6.30 6.56 6.66 7.19 7.42 7.71 7.93 8.05 8.18

01/18/91 6.24 6.51 6.61 7.14 7.38 7.68 7.92 8.03 8.17

01/22/91 6.24 6.48 6.59 7.13 7.37 7.70 7.94 8.07 8.23

01/23/91 6.32 6.49 6.59 7.08 7.36 7.67 7.91 8.04 8.21

01/24/91 6.31 6.47 6.54 7.04 7.32 7.61 7.88 8.00 8.18

01/25/91 6.35 6.52 6.61 7.10 7.36 7.67 7.93 8.06 8.24

01/28/91 6.44 6.55 6.64 7.12 7.38 7.67 7.93 8.06 8.23

01/29/91 6.41 6.55 6.59 7.10 7.35 7.64 7.90 8.03 8.20

01/30/91 6.39 6.53 6.56 7.07 7.34 7.64 7.90 8.05 8.23

01/31/91 6.37 6.49 6.51 7.05 7.30 7.62 7.89 8.03 8.21

84

Page 85: C or Not C

To C or not to C - Program Example - Part 17

============================================

Input (Bond) Maturities (in Years) Data File to Program :

---------------------------------------------------------

0.25

0.5

1

2

3

5

7

10

30

Output (Maturity and Rate Pairs) Data from Program

(only top 4 Lines shown, split after 3 Year Point for clarity) :

-----------------------------------------------------------------------

0.25 6.66 0.50 6.73 1.00 6.74 2.00 7.08 3.00 7.30

5.00 7.59 7.00 7.90 10.00 7.97 30.00 8.14

0.25 6.64 0.50 6.71 1.00 6.72 2.00 7.08 3.00 7.27

5.00 7.56 7.00 7.86 10.00 7.93 30.00 8.11

0.25 6.73 0.50 6.82 1.00 6.83 2.00 7.17 3.00 7.37

5.00 7.65 7.00 7.94 10.00 8.02 30.00 8.20

0.25 6.71 0.50 6.84 1.00 6.84 2.00 7.20 3.00 7.43

5.00 7.75 7.00 8.04 10.00 8.13 30.00 8.32

85

Page 86: C or Not C

To C or not to C - Program Example - Part 18

============================================

Output Log (as sent to Screen) from Program :

---------------------------------------------

Yield Curve Data reformat

*************************

To Quit at any point Hit CTRL/C

Enter Input Data File Name

(Default = ycvinp.dat) : ../msc/ycv/y91/ycv9101.dat

Enter Output Data File Name

(Default = ycvout.dat) :

Enter Maturities Data File Name

(Default = ycvmat.dat) : ../msc/ycv/matur09.dat

Maturities Summary :

--------------------

File : ../msc/ycv/matur09.dat

Total Values : 9

Input Yield Curve Data Summary :

--------------------------------

Input File : ../msc/ycv/y91/ycv9101.dat

Output File : ycvout.dat

Total Lines : 21

**** Reformat completed ****

86

Page 87: C or Not C

To C or not to C - Program Example - Part 19

============================================

Observations, from top down through Source Code :

-------------------------------------------------

- 1/ Some Comments at Top can describe process.

Also good to give details of :-Input and Output (Disk) Files.

-Called Routines (Functions in ’C’),

with Language when not ’C’.

-Reports and Error or Run Logs.

-Standards (say ANSI) and limitations.

- 2/ After 1/ above, and before body of ’C’ Code itself in Source File,

set Defaults (File Names, Constants) with ’#define’ Directives,

for Pre-Compiler to replace all instances in Source Code proper,

an easy way to tell reader about them and eventually change them.

’C’ Naming convention for Constants is Upper Case.

like ’#define LL 80’, sets up ’LL’ Line Length Constant,

so ’if ( ii < LL )’

becomes ’if ( ii < 80 )’ before Compilation.

- 3/ Follow 1/ and 2/ above with ’#include’ Pre-Compiler Directives,

for all Libraries and Function Headers (prototypes),

Standard ones between ’< >’ Angled Brackets,

User ones (usually Functions) between ’" "’ Double Quotes.

like ’#include <math.h>’ (Standard Mathematical Library),

’#include "fckdou.h" (User Called Sub Program ).

- 4/ Include Argument Count (’int argc’) and Array (’char *argv []’),

in ’main’ Statement, so it takes a uniform syntax.

- 5/ Put all Data declarations at Top of Source Code,

best in Alphabetical Order of Types, and Names within Type,

Can Present one variable per line, in Column fashion,

Pointers ’*’ standing out, Array Sizes or Initial Values on Right.

Avoid Single Letter Names, overly long ones, clashes with Language,

like ’int if’, and, possibly, common English and Mathematical terms.

Can be useful for first Letter to indicate Type (say ’i’ for ’int’).

87

Page 88: C or Not C

To C or not to C - Program Example - Part 20

============================================

- 6/ Mark start of Executable Statements with Screen Message or Header,

so user knows which Program Unit currently running.

- 7/ All Screen Output via ’fprintf’ and ’stderr’,

so no Buffer caused disordering, likely when ’stdou’ also used,

or System generated Error Messages sent as well as Program’s.

Likewise, all Screen Input via ’fscanf’ and ’stdin’,

so common Syntax with Disk File I/O in all scenarios.

- 8/ Check Arguments (’char’ Array ’*argv [ ]’ in ’main’) in Order.

stopping process when no more (tested using ’argc’ Value).

- 9/ Request File Names in consistent way, with Prompt and Defaults.

When Default Disk Files used, indicate their Names,

so user can easily find them outside scope of Program.

-10/ All File ’fopen’ Calls should test Outcome (’FILE’ Pointer ’NULL’),

in following Statement, or encapsulating ’( pntr = fopen )’ in ’if’.

Same for all Memory Allocations (’calloc’, ’malloc’, ’realloc’).

-11/ Validate all Numeric Variable Input, via ’char’ String Input,

and Copy off String to Numeric Fields with ’sscanf’,

so Numeric ’%’ ’fscanf’ Descriptors not used when risk or Errors.

-12/ Check Outcome of Data File Output (write operations),

where Return Code of ’fprintf’ gives Number of Items sent out.

-13/ Present Screen and File ASCII Input/Output as laid in File,

that is one String of ’fprintf’ "... output ..." per Line,

and isolate Variable Names on separate Line at Bottom.

-14/ Release Disk File (with ’fclose’) as soon as no more I/O to them,

and Check Outcome (’EOF’ Return Code), at least for Output Files.

88

Page 89: C or Not C

To C or not to C - Program Example - Part 21

============================================

-15/ Can use ’while ( ( irtc = fscanf ( ... ) ) != EOF ) { ...’,

to run through Data File, leaving Loop upon hitting End of File.

-16/ Avoid Statements not controlling Loop Start or End in Loop Entries.

Like ’for ( ii = 0, xx = 0.0; ii < 100; ii++ ) { ...’.

Better to Nest Loops than use many Control Variables on same Loop.

-17/ Avoid ’switch’/’case :’ blocks, use ’if’/else’ sequences instead.

Former requires Integer Variables, and omission of end ’break;’,

after each ’case :’ Clause means next one entered, and so on.

-18/ Write any implicit Casts explicitly to clarify any conversions.

Like ’dres = dval * (double) ll;’ for ’double * long’ to ’double’.

-19/ Give basic feedback (Results summary) Report at completion,

and send ’End of Program’ Note to Screen, to inform user of Exit.

-20/ Use common form for all Aborts, possibly calling Function,

passing it Message and Program (name in ’argv [0] at least) Details.

-21/ Indent Code at each Level of Nesting,

by 4 or 6 Spaces, not Tabs as these expand in non standard manner.

-22/ Space out Code Keywords, Symbols, Operators and Variable Names,

especially in Calculations, which can be spread over several Lines.

-23/ Shift Code fragments of potential value elsewhere to Functions,

unless too short (below 10 to 15 Statements) to warrant complexity.

89

Page 90: C or Not C

To C or not to C - Program Example - Part 22

============================================

General Guidelines :

--------------------

- 1/ Use consistent Style and Syntax,

in effect set up a ’C’ Coding Paradigm,

to minimise risks or errors and achieve clear, easy to read Code.

- 2/ Small (single or few Characters) Symbols can have great impact,

so space out items like ’( )’, ’{ }’, or Arithmetic Operators,

also enclosing secondary Calculations in nested Brackets.

- 3/ Use only a subset of Statements,

even at cost of more Source Code (but not necessarily less speed),

and keep them to their simplest form (like Loops with one Variable).

- 4/ Split Large Programs, or computations of potential outside use,

to separate Sub-Programs (Functions), unless very small.

- 5/ Avoid Extensions, and use one or other of ANSI Standard,

or K & R ("traditional" ’C’) throughout a Program Module.

- 6/ Be generous with Comments.

90

Page 91: C or Not C

TO C OR NOT TO C, THE LITERATURE

********************************

By the yardstick of numbers, the ’C’ literature is well endowed. Alas,

its scope hasn’t quite expanded as far as the language’s use. Most so

called general books present a view more suited to systems programmers

or database designers than to commercial or scientific applications. An

inordinate amount of pages explain linked lists, of little use in most

cases, and not many detail how to handle multi dimensional arrays.

Likewise, few titles suggest a simplified approach to programming in ’C’,

where some performance and subtlety is sacrificed to legibility.

Still, it comes very useful to get a solid introductory tome, which

includes a formal list of the many functions in the standard libraries.

’A Book on C’ (Kelly A.L. & Pohl I.) has proved quite useful.

The tome by H. Shildt, ’C: The Complete Reference (4th Edition)’,

has attracted some fine reviews, and seems to keep selling well.

However, the best remains in my mind the ’C Primer Plus’ by Prata,

with excellent explanations and examples on multi dimensional Arrays.

The Microsoft ’Code Complete’ by McConnell makes afine read on good

programming practise, and has attracted excellent reviews, from even

readers not particularly fanatical about its publisher. Discussing ’C’,

Fortran, Pascal and generalities, ’Imperative Programming Languages’,

the second volume of the ’Handbook of Programming Languages’ set,

offers an interesting discussion of the merits and faults in ’C’,

together with a review of its development and usage. Well worth a

read for those after more than mere ability to write ’C’ Programs.

91

Page 92: C or Not C

Some ’C’ (Book) Titles

======================

General Introductions and Descriptions :

----------------------------------------

N. Barkakati,

The Waite Group’s Microsoft C Bible (3rd Edition),

Howard W. Sams & Co. (Mc Millan), ISBN 0-672-22736-3, 1990.

A.L. Kelly, I. Pohl I.,

A Book on C, Programming in C (4th Edition),

Benjamin/Cummings Publishing Co., ISBN 0-2011-8399-4, 1997.

B.W. Kernighan, D.M. Ritchie,

The C Programming Language (2nd Edition),

Prentice Hall, ISBN 0-13-110362-8, 1988.

P. Prinz, T. Crawford,

C in a Nutshell,

O’Reilly & Associates, ISBN 0-596-00697-7, 2005.

P. Prinz, U. Kirch-Prinz,

C Pocket Reference,

O’Reilly & Associates, 0-596-00436-2, 2002.

S. Oualline,

Practical C Programming (3rd Edition),

O’Reilly & Associates, ISBN 1-56592-306-5, 1997.

S. Prata,

C Primer Plus (4 th Edition, 5th coming),

Howard W. Sams & Co. (Mc Millan), ISBN 0-672-32222-6, 2001.

H. Shildt,

C: The Complete Reference (4th Edition),

Osborne Mc Graw Hill, ISBN 0-07-212124-6, 2000.

C.L. Tondo, S.E. Gimpel,

The C Answer Book (2nd Edition),

Prentice Hall, ISBN 0-13-028277-4, 1988.

92

Page 93: C or Not C

For General Programming and Interest :

--------------------------------------

W. Brainerd, R. Cytron, R.E. Griswold, G. Grotzinger,

D.M. Ritchie, S. Summit,

Handbook of Programming Languages (P.H. Salus Editor),

Volume II, Imperative Programming Languages,

Macmillan Technical Publishing, ISBN 1-57870-009-4, 1998.

S. McConnell,

Code Complete (2nd Edition),

Microsoft Press, ISBN 0-735-61967-0, 2004.

93