C Notes Full

You might also like

Download as pdf or txt
Download as pdf or txt
You are on page 1of 61

Notes on

C Programming

Prepared by
Dr. M Naresh Babu
Contents
C Programming Introduction ......................................................................................................................... 1
Algorithm ................................................................................................................................................... 1
Why to use C ? ........................................................................................................................................... 2
History of C ................................................................................................................................................ 3
Characteristics of C .................................................................................................................................... 3
C Program Structure .................................................................................................................................. 3
Identifiers and Keywords ........................................................................................................................... 4
Variables .................................................................................................................................................... 5
Defining Global Variables ...................................................................................................................... 5
Operators........................................................................................................................................................ 6
Arithmetic Operations ............................................................................................................................... 6
Relational Operators .................................................................................................................................. 8
Logical Operators ....................................................................................................................................... 9
Bitwise Operators ...................................................................................................................................... 9
Assignment Operators .............................................................................................................................10
Misc Operators ↦ sizeof & ternary .........................................................................................................11
Operators Precedence in C...........................................................................................................................11
Implicit Type Conversion ............................................................................................................................13
Explicit Type Conversion ............................................................................................................................13
Conditionals .................................................................................................................................................14
The ‘if’ statement.....................................................................................................................................14
The ? : operator .......................................................................................................................................15
The switch statement ..............................................................................................................................16
LOOPs .........................................................................................................................................................17
The for loop..............................................................................................................................................23
The while loop .........................................................................................................................................24
The do while loop ....................................................................................................................................25
Break and continue ..................................................................................................................................26
Arrays and Strings .......................................................................................................................................27
Single and Multi-dimensional Arrays .......................................................................................................27
Strings ......................................................................................................................................................28
Pointers ........................................................................................................................................................30
C Pointer Syntax .......................................................................................................................................31
Pointing to Something: Retrieving an Address .......................................................................................32
Functions......................................................................................................................................................35
Parameters in C functions........................................................................................................................36
Pass by Value .......................................................................................................................................36
Pass by Reference ................................................................................................................................36
Structures .....................................................................................................................................................39
Defining New Data Types.........................................................................................................................40
Unions ......................................................................................................................................................41
Enumerated Types ...................................................................................................................................42
Coercion or Type-Casting............................................................................................................................43
Static Variables ............................................................................................................................................44
Files..............................................................................................................................................................45
Reading and writing files .........................................................................................................................46
sprintf and sscanf .....................................................................................................................................47
Stream Status Enquiries ...........................................................................................................................48
Low Level I/O ...........................................................................................................................................48
Closing Files..............................................................................................................................................51
Direct input function: the fread function ................................................................................................54
Exercises.......................................................................................................................................................55
References ...................................................................................................................................................58
C Programming Introduction
Computer is an electronic device that stores, processes, inputs, and outputs data to produce a
result. Computer contains electronic components. Every operation will be done in terms
voltages. Computer/ Machine can understand only 0s and 1s (may be 0v to represent 0 and +5v
to represent 1).

A computer is a general purpose device that can be programmed to carry out a set of arithmetic
or logical operations automatically.

Can we say calculator is computer? yes, in calculator we can give input, we can
perform arithmetic operations like +,-, * etc., we can also store using M+. But calculator has its
own limitation. Like that mobile is also a computer.
Now days modern computer comes with 4 GB RAM, 500GB Harddisk to store and Intel Core i7
processor, for input keyboard with 108 keys etc.,
As machine can understand 0s and 1s, as a human it is difficult to write complex programs in 0s
and 1s. There is something needed to convert human understandable program to machine
understandable called complier.

Algorithm

A step-by-step problem-solving procedure, especially an established, recursive computational


procedure for solving a problem in a finite number of steps.

Algorithms are essential to the way computers process data. Many computer programs contain
algorithms that detail the specific instructions a computer should perform (in a specific order) to
carry out a specified task.

Algorithm for constructing a magic square of odd order

• The method prescribes starting in the central column of the first row with the number 1.
• After that, the fundamental movement for filling the squares is diagonally up and right,
one step at a time.
• If a filled square is encountered, one moves vertically down one square instead, then
continues as before.
• When an "up and to the right" move would leave the square, it is wrapped around to the
last row or first column, respectively.

Flowchart
The flowchart is a means of visually presenting the flow of data through an information
processing systems, the operations performed within the system and the sequence in which they
are performed.

Page 1 of 58
A flowchart is a diagrammatic representation that illustrates the sequence of operations to be
performed to get the solution of a problem.

Off page connector is used to show that the flow is on a different page.

Why to use C ?

C was initially used for system development work, in particular the programs that make-up the
operating system. C was adoped as a system development language because it produces code that
runs nearly as fast as code written in assembly language. Some examples of the use of C might
be:
• Operating Systems
• Language Compilers
• Assemblers
• Text Editors
• Print Spoolers
• Network Drivers
• Modern Programs

Page 2 of 58
• Data Bases
• Language Interpreters
• Utilities

History of C
The milestones in C's development as a language are listed below:
• UNIX developed c. 1969 -- DEC PDP-7 Assembly Language
• BCPL -- a user friendly OS providing powerful development tools developed from
BCPL. Assembler tedious long and error prone.
• A new language ``B'' a second attempt. c. 1970.
• A totally new language ``C'' a successor to ``B''. c. 1971
• By 1973 UNIX OS almost totally written in ``C''.

Characteristics of C
We briefly list some of C's characteristics that define the language and also have lead to its
popularity as a programming language. Naturally we will be studying many of these aspects
throughout the course.
• Small size
• Extensive use of function calls
• Loose typing -- unlike PASCAL
• Structured language
• Low level (BitWise) programming readily available
• Pointer implementation - extensive use of pointers for memory, array, structures and
functions.
C has now become a widely used professional language for various reasons.
• It has high-level constructs.
• It can handle low-level activities.
• It produces efficient programs.
• It can be compiled on a variety of computers.
Its main drawback is that it has poor error detection which can make it off putting to the
beginner.

C Program Structure
A C program basically has the following form:
• Preprocessor Commands
• Type definitions
• Function prototypes -- declare function types and variables passed to function.

Page 3 of 58
• Variables
• Functions
We must have a main() function.

A function has the form:


type function_name (parameters)
{
local variables

C Statements
}

C requires a semicolon at the end of every statement.

Identifiers and Keywords


The rules for the construction of identifiers are simple: you may use the 52 upper and lower case
alphabetic characters, the 10 digits and finally the underscore ‘_’, which is considered to be an
alphabetic character for this purpose. The only restriction is the usual one; identifiers must start
with an alphabetic character. C is a case sensitive language.

C keeps a small set of keywords for its own use. These keywords cannot be used as identifiers in
the program — a common restriction with modern languages.

1. auto 9. double 17. int 25. struct


2. break 10. else 18. long 26. switch
3. case 11. enum 19. register 27. typedef
4. char 12. extern 20. return 28. union
5. const 13. float 21. short 29. unsigned
6. continue 14. for 22. signed 30. void
7. default 15. goto 23. sizeof 31. volatile
8. do 16. if 24. static 32. while

Page 4 of 58
Variables
C has the following simple data types:

Defining Global Variables

Global variables are defined above main() in the following way:-

short number,sum;
int bignumber,bigsum;
char letter;

main()
{

It is also possible to pre-initialise global variables using the = operator for assignment.

C also allows multiple assignment statements using =, for example:

a=b=c=d=3;

...which is the same as, but more efficient than:

a=3;
b=3;
c=3;
d=3;

This kind of assignment is only possible if all the variable types in the statement are the same.

You can define your own types use typedef. This will have greater relevance later in the course
when we learn how to create more complex data structures.

Page 5 of 58
As an example of a simple use let us consider how we may define two new types real and letter.
These new types can then be used in the same way as the pre-defined C types:

typedef real float;


typedef letter char;

Variables declared:
real sum=0.0;
letter nextletter;

C uses formatted output. The printf function has a special formatting character (%) -- a character
following this defines a certain format for a variable:

%c -- characters
%d -- integers
%f – floats
%s -- string

e.g. printf("%c %d %f",ch,i,x);

Operators
An operator is a symbol that tells the compiler to perform specific mathematical or logical
manipulations. C language is rich in built-in operators and provides the following types of
operators:

• Arithmetic Operators
• Relational Operators
• Logical Operators
• Bitwise Operators
• Assignment Operators
• Misc Operators

Arithmetic Operations
As well as the standard arithmetic operators (+ - * /) found in most languages, C provides some
more operators. There are some notable differences with other languages, such as Pascal.

Assignment is = i.e. i = 4; ch = `y';

Page 6 of 58
Increment ++, Decrement -- which are more efficient than their long hand equivalents, for
example:-- x++ is faster than x=x+1.

The ++ and -- operators can be either in post-fixed or pre-fixed. With pre-fixed the value is
computed before the expression is evaluated whereas with post-fixed the value is computed after
the expression is evaluated.

In the example below, ++z is pre-fixed and the w-- is post-fixed:

int x,y,w;

main()
{

x=((++z)-(w--)) % 100;

This would be equivalent to:

int x,y,w;

main()
{

z++;
x=(z-w) % 100;
w--;

The % (modulus) operator only works with integers.

Division / is for both integer and float division. So be careful.

The answer to: x = 3 / 2 is 1 even if x is declared a float!!

RULE: If both arguments of / are integer then do integer division.

So make sure you do this. The correct (for division) answer to the above is x = 3.0 / 2 or x= 3 /
2.0 or (better) x = 3.0 / 2.0.

There is also a convenient shorthand way to express computations in C.

Page 7 of 58
It is very common to have expressions like: i = i + 3 or x = x*(y + 2)

This can written in C (generally) in a shorthand form like this:

which is equivalent to (but more efficient than):

So we can rewrite i = i + 3 as i += 3

and x = x*(y + 2) as x *= y + 2.

NOTE: that x *= y + 2 means x = x*(y + 2) and NOT x = x*y + 2.

Following table shows all the arithmetic operators supported by C language. Assume variable A
holds 10 and variable B holds 20 then:

Operat Description Example


or
+ Adds two operands A + B will give 30
- Subtracts second operand from the first A - B will give -10
* Multiplies both operands A * B will give 200
/ Divides numerator by de-numerator B / A will give 2
% Modulus Operator and remainder of after an B % A will give 0
integer division
++ Increments operator increases integer value by one A++ will give 11
-- Decrements operator decreases integer value by A-- will give 9
one

Relational Operators
Following table shows all the relational operators supported by C language. Assume variable A
holds 10 and variable B holds 20, then:

Operator Description Example


== Checks if the values of two operands are equal or (A == B) is not true.

Page 8 of 58
not, if yes then condition becomes true.
!= Checks if the values of two operands are equal or (A != B) is true.
not, if values are not equal then condition becomes
true.
> Checks if the value of left operand is greater than (A > B) is not true.
the value of right operand, if yes then condition
becomes true.
< Checks if the value of left operand is less than the (A < B) is true.
value of right operand, if yes then condition
becomes true.
>= Checks if the value of left operand is greater than (A >= B) is not true.
or equal to the value of right operand, if yes then
condition becomes true.
<= Checks if the value of left operand is less than or (A <= B) is true.
equal to the value of right operand, if yes then
condition becomes true.

Logical Operators
Following table shows all the logical operators supported by C language. Assume variable A
holds 1 and variable B holds 0, then:

Operator Description Example


&& Called Logical AND operator. If both the operands (A && B) is false.
are non-zero, then condition becomes true.
|| Called Logical OR Operator. If any of the two (A || B) is true.
operands is non-zero, then condition becomes true.
! Called Logical NOT Operator. Use to reverses the !(A && B) is true.
logical state of its operand. If a condition is true
then Logical NOT operator will make false.

Bitwise Operators
Bitwise operator works on bits and perform bit-by-bit operation. The truth tables for &, |, and ^
are as follows:

p q p&q p|q p^q


0 0 0 0 0
0 1 0 1 1
1 1 1 1 0
1 0 0 1 1

Assume if A = 60; and B = 13; now in binary format they will be as follows:

Page 9 of 58
A = 0011 1100

B = 0000 1101

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

A&B = 0000 1100

A|B = 0011 1101

A^B = 0011 0001

~A = 1100 0011

The Bitwise operators supported by C language are listed in the following table. Assume variable
A holds 60 and variable B holds 13, then:

Operator Description Example


& Binary AND Operator copies a bit to the result if it (A & B) will give 12, which is
exists in both operands. 0000 1100
| Binary OR Operator copies a bit if it exists in (A | B) will give 61, which is
either operand. 0011 1101
^ Binary XOR Operator copies the bit if it is set in (A ^ B) will give 49, which is
one operand but not both. 0011 0001
~ Binary Ones Complement Operator is unary and (~A ) will give -61, which is
has the effect of 'flipping' bits. 1100 0011 in 2's complement
form.
<< Binary Left Shift Operator. The left operands value A << 2 will give 240 which is
is moved left by the number of bits specified by 1111 0000
the right operand.
>> Binary Right Shift Operator. The left operands A >> 2 will give 15 which is
value is moved right by the number of bits 0000 1111
specified by the right operand.

Assignment Operators
There are following assignment operators supported by C language:

Operator Description Example


= Simple assignment operator, Assigns values from C = A + B will assign value of
right side operands to left side operand A + B into C
+= Add AND assignment operator, It adds right C += A is equivalent to C = C

Page 10 of 58
operand to the left operand and assign the result to +A
left operand
-= Subtract AND assignment operator, It subtracts C -= A is equivalent to C = C -
right operand from the left operand and assign the A
result to left operand
*= Multiply AND assignment operator, It multiplies C *= A is equivalent to C = C
right operand with the left operand and assign the *A
result to left operand
/= Divide AND assignment operator, It divides left C /= A is equivalent to C = C /
operand with the right operand and assign the A
result to left operand
%= Modulus AND assignment operator, It takes C %= A is equivalent to C = C
modulus using two operands and assign the result %A
to left operand
<<= Left shift AND assignment operator C <<= 2 is same as C = C << 2
>>= Right shift AND assignment operator C >>= 2 is same as C = C >> 2
&= Bitwise AND assignment operator C &= 2 is same as C = C & 2
^= bitwise exclusive OR and assignment operator C ^= 2 is same as C = C ^ 2
|= bitwise inclusive OR and assignment operator C |= 2 is same as C = C | 2

Misc Operators ↦ sizeof & ternary


There are few other important operators including sizeof and ? : supported by C Language.

Operator Description Example


sizeof() Returns the size of an variable. sizeof(a), where a is integer,
will return 4.
& Returns the address of an variable. &a; will give actual address of
the variable.
* Pointer to a variable. *a; will pointer to a variable.
?: Conditional Expression If Condition is true ? Then
value X : Otherwise value Y

Operators Precedence in C
Operator precedence determines the grouping of terms in an expression. This affects how an
expression is evaluated. Certain operators have higher precedence than others; for example, the
multiplication operator has higher precedence than the addition operator.

For example x = 7 + 3 * 2; here, x is assigned 13, not 20 because operator * has higher
precedence than +, so it first gets multiplied with 3*2 and then adds into 7.

Page 11 of 58
Here, operators with the highest precedence appear at the top of the table, those with the lowest
appear at the bottom. Within an expression, higher precedence operators will be evaluated first.

Category Operator Associativity


Postfix () [] -> . ++ - - Left to right
Unary + - ! ~ ++ - - (type)* & sizeof Right to left
Multiplicative */% Left to right
Additive +- Left to right
Shift << >> Left to right
Relational < <= > >= Left to right
Equality == != Left to right
Bitwise AND & Left to right
Bitwise XOR ^ Left to right
Bitwise OR | Left to right
Logical AND && Left to right
Logical OR || Left to right
Conditional ?: Right to left
Assignment = += -= *= /= %=>>= <<= &= ^= |= Right to left
Comma , Left to right

Operators higher in the chart have a higher precedence, meaning that the C compiler evaluates
them first. Operators on the same line in the chart have the same precedence, and the
"Associativity" column on the right gives their evaluation order.

Operator Precedence Chart


Operator Type Operator Associativity
Primary Expression () [] . -> expr++ expr-- left-to-right
Operators
Unary Operators * & + - ! ~ ++expr --expr (typecast) sizeof right-to-left
Binary Operators */% left-to-right
+-
>> <<
< > <= >=
== !=
&
^
|
&&
||
Ternary Operator ?: right-to-left
Assignment Operators = += -= *= /= %= >>= <<= &= ^= |= right-to-left
Comma , left-to-right

Page 12 of 58
When variables and constants of different types are combined in an expression then they are
converted to same data type. The process of converting one predefined type into another is called
type conversion.

Type conversion in c can be classified into the following two types:

Implicit Type Conversion


When the type conversion is performed automatically by the compiler without programmers
intervention, such type of conversion is known as implicit type conversion or type promotion.

The compiler converts all operands into the data type of the largest operand.

The sequence of rules that are applied while evaluating expressions are given below:

All short and char are automatically converted to int, then,

1. If either of the operand is of type long double, then others will be converted to long
double and result will be long double.
2. Else, if either of the operand is double, then others are converted to double.
3. Else, if either of the operand is float, then others are converted to float.
4. Else, if either of the operand is unsigned long int, then others will be converted to
unsigned long int.
5. Else, if one of the operand is long int, and the other is unsigned int, then
1. if a long int can represent all values of an unsigned int, the unsigned int is
converted to long int.
2. otherwise, both operands are converted to unsigned long int.
6. Else, if either operand is long int then other will be converted to long int.
7. Else, if either operand is unsigned int then others will be converted to unsigned int.

It should be noted that the final result of expression is converted to type of variable on left side
of assignment operator before assigning value to it.

Also, conversion of float to int causes truncation of fractional part, conversion of double to float
causes rounding of digits and the conversion of long int to int causes dropping of excess higher
order bits.

Explicit Type Conversion


The type conversion performed by the programmer by posing the data type of the expression of
specific type is known as explicit type conversion.

The explicit type conversion is also known as type casting.

Type casting in c is done in the following form:

Page 13 of 58
(data_type)expression;

where, data_type is any valid c data type, and expression may be constant, variable or
expression.

For example,

1x=(int)a+b*d;

The following rules have to be followed while converting the expression from one type to
another to avoid the loss of information:

1. All integer types to be converted to float.


2. All float types to be converted to double.

All character types to be converted to integer.

Conditionals
Various methods that C can control the flow of logic in a program. Apart from slight
syntactic variation they are similar to other languages.

As we have seen following logical operations exist in C:

==, !=, , &&.

One other operator is the unitary - it takes only one argument - not !.

These operators are used in conjunction with the following statements.

The ‘if’ statement


The if statement has the same function as other languages. It has three basic forms:

if (expression)
statement

...or:

Page 14 of 58
if (expression)
statement1
else
statement2

...or:

if (expression)
statement1
else if (expression)
statement2
else
statement3

For example:-

int x,y,w;

main()
{

if (x>0)
{
z=w;
........
}
else
{
z=y;
........
}

The ? : operator
The ? (ternary condition) operator is a more efficient form for expressing simple if statements. It
has the following form:

expression1 ? expression2: expression3

Page 15 of 58
It simply states:

if expression1 then expression2 else expression3

For example to assign the maximum of a and b to z:

z = (a>b) ? a : b;

which is the same as:

if (a>b)
z = a;
else
z=b;

The switch statement


The C switch is similar to Pascal's case statement and it allows multiple choice of a selection of
items at one level of a conditional where it is a far neater way of writing multiple if statements:

switch (expression) {
case item1:
statement1;
break;
case item2:
statement2;
break;

statementn;
break;
default:
statement;
break;
}

In each case the value of itemi must be a constant, variables are not allowed.

The break is needed if you want to terminate the switch after execution of one choice. Otherwise
the next case would get evaluated. Note: This is unlike most other languages.

We can also have null statements by just including a ; or let the switch statement fall through by
omitting any statements (see e.g. below).

Page 16 of 58
The default case is optional and catches any other cases.

For example:-

switch (letter)
{
case `A':
case `E':
case `I':
case `O':
case `U':
numberofvowels++;
break;

case ` ':
numberofspaces++;
break;

default:
numberofconstants++;
break;
}

In the above example if the value of letter is `A', `E', `I', `O' or `U' then numberofvowels is
incremented.

If the value of letter is ` ' then numberofspaces is incremented.

If none of these is true then the default condition is executed, that is numberofconstants is
incremented.

LOOPs
FOR - for loops are the most useful type. The syntax for a for loop is

for ( variable initialization; condition; variable update ) {

Code to execute while the condition is true

Page 17 of 58
The variable initialization allows you to either declare a variable and give it a value or give a
value to an already existing variable. Second, the condition tells the program that while the
conditional expression is true the loop should continue to repeat itself. The variable update
section is the easiest way for a for loop to handle changing of the variable. It is possible to do
things like x++, x = x + 10, or even x = random ( 5 ), and if you really wanted to, you could call
other functions that do nothing to the variable but still have a useful effect on the code. Notice
that a semicolon separates each of these sections, that is important. Also note that every single
one of the sections may be empty, though the semicolons still have to be there. If the condition is
empty, it is evaluated as true and the loop will repeat until something else stops it.

Example:

#include <stdio.h>

int main()

int x;

/* The loop goes while x < 10, and x increases by one every loop*/

for ( x = 0; x < 10; x++ ) {

/* Keep in mind that the loop condition checks

the conditional statement before it loops again.

consequently, when x equals 10 the loop breaks.

x is updated before the condition is checked. */

printf( "%d\n", x );

getchar();

Page 18 of 58
This program is a very simple example of a for loop. x is set to zero, while x is less than 10 it
calls printf to display the value of the variable x, and it adds 1 to x until the condition is met.
Keep in mind also that the variable is incremented after the code in the loop is run for the first
time.

WHILE - WHILE loops are very simple. The basic structure is

while ( condition ) { Code to execute while the condition is true } The true represents a boolean
expression which could be x == 1 or while ( x != 7 ) (x does not equal 7). It can be any
combination of boolean statements that are legal. Even, (while x ==5 || v == 7) which says
execute the code while x equals five or while v equals 7. Notice that a while loop is like a
stripped-down version of a for loop-- it has no initialization or update section. However, an
empty condition is not legal for a while loop as it is with a for loop.

Example:

#include <stdio.h>

int main()

int x = 0; /* Don't forget to declare variables */

while ( x < 10 ) { /* While x is less than 10 */

printf( "%d\n", x );

x++; /* Update x so the condition can be met eventually */

getchar();

Page 19 of 58
This was another simple example, but it is longer than the above FOR loop. The easiest way to
think of the loop is that when it reaches the brace at the end it jumps back up to the beginning of
the loop, which checks the condition again and decides whether to repeat the block another time,
or stop and move to the next statement after the block.

DO..WHILE - DO..WHILE loops are useful for things that want to loop at least once. The
structure is

do {

} while ( condition );

Notice that the condition is tested at the end of the block instead of the beginning, so the block
will be executed at least once. If the condition is true, we jump back to the beginning of the
block and execute it again. A do..while loop is almost the same as a while loop except that the
loop body is guaranteed to execute at least once. A while loop says "Loop while the condition is
true, and execute this block of code", a do..while loop says "Execute this block of code, and then
continue to loop while the condition is true".

Example:

#include <stdio.h>

int main()

int x;

x = 0;

Page 20 of 58
do {

/* "Hello, world!" is printed at least one time

even though the condition is false */

printf( "Hello, world!\n" );

} while ( x != 0 );

getchar();

Keep in mind that you must include a trailing semi-colon after the while in the above example. A
common error is to forget that a do..while loop must be terminated with a semicolon (the other
loops should not be terminated with a semicolon, adding to the confusion). Notice that this loop
will execute once, because it automatically executes before checking the condition.

Break and Continue

Two keywords that are very important to looping are break and continue. The break command
will exit the most immediately surrounding loop regardless of what the conditions of the loop
are. Break is useful if we want to exit a loop under special circumstances. For example, let's say
the program we're working on is a two-person checkers game. The basic structure of the program
might look like this:

while (true)

take_turn(player1);

take_turn(player2);

Page 21 of 58
This will make the game alternate between having player 1 and player 2 take turns. The only
problem with this logic is that there's no way to exit the game; the loop will run forever! Let's try
something like this instead:

while(true)

if (someone_has_won() || someone_wants_to_quit() == TRUE)

{break;}

take_turn(player1);

if (someone_has_won() || someone_wants_to_quit() == TRUE)

{break;}

take_turn(player2);

This code accomplishes what we want--the primary loop of the game will continue under normal
circumstances, but under a special condition (winning or exiting) the flow will stop and our
program will do something else.

Continue is another keyword that controls the flow of loops. If you are executing a loop and hit a
continue statement, the loop will stop its current iteration, update itself (in the case of for loops)
and begin to execute again from the top. Essentially, the continue statement is saying "this
iteration of the loop is done, let's continue with the loop without executing whatever code comes
after me." Let's say we're implementing a game of Monopoly. Like above, we want to use a loop
to control whose turn it is, but controlling turns is a bit more complicated in Monopoly than in
checkers. The basic structure of our code might then look something like this:

for (player = 1; someone_has_won == FALSE; player++)

if (player > total_number_of_players)

{player = 1;}

Page 22 of 58
if (is_bankrupt(player))

{continue;}

take_turn(player);

This way, if one player can't take her turn, the game doesn't stop for everybody; we just skip her
and keep going with the next player's turn.

The for loop


The “for loop” loops from one number to another number and increases by a specified value each
time.
The “for loop” uses the following structure:

for (Start value; continue or end condition; increase value)


statement;

Look at the example below:

#include<stdio.h>

int main()
{
int i;
for (i = 0; i < 10; i++)
{
printf ("Hello\n");
printf ("World\n");
}
return 0;
}

Note: A single instruction can be placed behind the “for loop” without the curly brackets.

Let’s look at the “for loop” from the example: We first start by setting the variable i to 0. This
is where we start to count. Then we say that the for loop must run if the counter i is smaller then
ten. Last we say that every cycle i must be increased by one (i++).

Page 23 of 58
In the example we used i++ which is the same as using i = i + 1. This is called incrementing. The
instruction i++ adds 1 to i. If you want to subtract 1 from i you can use i--. It is also possible to
use ++i or --i. The difference is is that with ++i (prefix incrementing) the one is added before the
“for loop” tests if i < 10. With i++ (postfix incrementing) the one is added after the test i < 10. In
case of a for loop this make no difference, but in while loop test it makes a difference. But before
we look at a postfix and prefix increment while loop example, we first look at the while loop.

The while loop


The while loop can be used if you don’t know how many times a loop must run. Here is an
example:

#include<stdio.h>

int main()

{
int counter, howmuch;

scanf("%d", &howmuch);
counter = 0;
while ( counter < howmuch)
{
counter++;
printf("%d\n", counter);
}
return 0;
}

Let’s take a look at the example: First you must always initialize the counter before the while
loop starts ( counter = 1). Then the while loop will run if the variable counter is smaller then the
variable “howmuch”. If the input is ten, then 1 through 10 will be printed on the screen. A last
thing you have to remember is to increment the counter inside the loop (counter++). If you forget
this the loop becomes infinitive.

As said before (after the for loop example) it makes a difference if prefix incrementing (++i) or
postfix incrementing (i++) is used with while loop. Take a look at the following postfix and
prefix increment while loop example:

#include<stdio.h>

int main(void) {
int i;

Page 24 of 58
i = 0;
while(i++ < 5) {
printf("%d\n", i);
}
printf("\n");
i = 0;
while(++i < 5) {
printf("%d\n", i);
}
return 0;
}

The output of the postfix and prefix increment example will look like this:

1
2
3
4
5

1
2
3
4

i++ will increment the value of i, but is using the pre-incremented value to test against < 5.
That’s why we get 5 numbers.
++i will increment the value of i, but is using the incremented value to test against < 5. That’s
why we get 4 numbers.

The do while loop


The “do while loop” is almost the same as the while loop. The “do while loop” has the following
form:

do
{
do something;
}
while (expression);

Do something first and then test if we have to continue. The result is that the loop always runs
once. (Because the expression test comes afterward). Take a look at an example:

#include<stdio.h>

Page 25 of 58
int main()
{
int counter, howmuch;
scanf("%d", &howmuch);
counter = 0;
do
{
counter++;
printf("%d\n", counter);
}
while ( counter < howmuch);
return 0;
}

Note: There is a semi-colon behind the while line.

Break and continue


To exit a loop you can use the break statement at any time. This can be very useful if you want to
stop running a loop because a condition has been met other than the loop end condition. Take a
look at the following example:

#include<stdio.h>

int main()
{
int i;

i = 0;
while ( i < 20 )
{
i++;
if ( i == 10)
break;
}
return 0;
}

In the example above, the while loop will run, as long i is smaller then twenty. In the while loop
there is an if statement that states that if i equals ten the while loop must stop (break).

With “continue;” it is possible to skip the rest of the commands in the current loop and start from
the top again. (the loop variable must still be incremented). Take a look at the example below:

#include<stdio.h>

int main()
{

Page 26 of 58
int i;

i = 0;
while ( i < 20 )
{
i++;
continue;
printf("Nothing to see\n");
}
return 0;
}

Note: printf is never called because of continue.

Arrays and Strings


In principle arrays in C are similar to those found in other languages. As we shall
shortly see arrays are defined slightly differently and there are many subtle differences
due the close link between array and pointers.

Single and Multi-dimensional Arrays


Let us first look at how we define arrays in C:

int listofnumbers[50];

BEWARE: In C Array subscripts start at 0 and end one less than the array size. For example, in
the above case valid subscripts range from 0 to 49. This is a BIG difference between C and other
languages and does require a bit of practice to get in the right frame of mind.

Elements can be accessed in the following ways:-

thirdnumber=listofnumbers[2];
listofnumbers[5]=100;

Multi-dimensional arrays can be defined as follows:

int tableofnumbers[50][50];

for two dimensions.

For further dimensions simply add more [ ]:

int bigD[50][50][40][30]......[50];

Page 27 of 58
Elements can be accessed in the following ways:

anumber=tableofnumbers[2][3];
tableofnumbers[25][16]=100;

Strings
In C Strings are defined as arrays of characters. For example, the following defines a string of 50
characters:

char name[50];
C has no string handling facilities built in and so the following are all illegal:

char firstname[50],lastname[50],fullname[100];

firstname= "Arnold"; /* Illegal */


lastname= "Schwarznegger"; /* Illegal */
fullname= "Mr"+firstname
+lastname; /* Illegal */

However, there is a special library of string handling routines which we will come across later.

To print a string we use printf with a special %s control character:

printf("s",name);

NOTE: We just need to give the name of the string.

In order to allow variable length strings the 0 character is used to indicate the end of a string.

So we if we have a string, char NAME[50]; and we store the ``DAVE'' in it its contents will look
like:

Strings

The string in C programming language is actually a one-dimensional array of characters which is


terminated by a null character '\0'. Thus a null-terminated string contains the characters that
comprise the string followed by a null.

Page 28 of 58
The following declaration and initialization create a string consisting of the word "Hello". To
hold the null character at the end of the array, the size of the character array containing the string
is one more than the number of characters in the word "Hello."

char greeting[6] = {'H', 'e', 'l', 'l', 'o', '\0'};

If you follow the rule of array initialization then you can write the above statement as follows:

char greeting[] = "Hello";

Following is the memory presentation of above defined string in C/C++:

Actually, you do not place the null character at the end of a string constant. The C compiler
automatically places the '\0' at the end of the string when it initializes the array. Let us try to print
above mentioned string:

#include <stdio.h>

int main ()
{
char greeting[6] = {'H', 'e', 'l', 'l', 'o', '\0'};

printf("Greeting message: %s\n", greeting );

return 0;
}

When the above code is compiled and executed, it produces result something as follows:

Greeting message: Hello

C supports a wide range of functions that manipulate null-terminated strings:

S.N. Function & Purpose


1 strcpy(s1, s2);
Copies string s2 into string s1.
2 strcat(s1, s2);

Page 29 of 58
Concatenates string s2 onto the end of string s1.
3 strlen(s1);
Returns the length of string s1.
4 strcmp(s1, s2);
Returns 0 if s1 and s2 are the same; less than 0 if s1<s2; greater than 0 if s1>s2.
5 strchr(s1, ch);
Returns a pointer to the first occurrence of character ch in string s1.
6 strstr(s1, s2);
Returns a pointer to the first occurrence of string s2 in string s1.

Following example makes use of few of the above-mentioned functions:

#include <stdio.h>
#include <string.h>

int main ()
{
char str1[12] = "Hello";
char str2[12] = "World";
char str3[12];
int len ;

/* copy str1 into str3 */


strcpy(str3, str1);
printf("strcpy( str3, str1) : %s\n", str3 );

/* concatenates str1 and str2 */


strcat( str1, str2);
printf("strcat( str1, str2): %s\n", str1 );

/* total lenghth of str1 after concatenation */


len = strlen(str1);
printf("strlen(str1) : %d\n", len );

return 0;
}

When the above code is compiled and executed, it produces result something as follows:

strcpy( str3, str1) : Hello


strcat( str1, str2): HelloWorld
strlen(str1) : 10

You can find a complete list of c string related functions in C Standard Library

Pointers
Pointers are aptly name: they "point" to locations in memory. Think of a row of safety deposit
boxes of various sizes at a local bank. Each safety deposit box will have a number associated
with it so that you can quickly look it up. These numbers are like the memory addresses of

Page 30 of 58
variables. A pointer in the world of safety deposit box would simply be anything that stored the
number of another safety deposit box. Perhaps you have a rich uncle who stored valuables in his
safety deposit box, but decided to put the real location in another, smaller, safety deposit box that
only stored a card with the number of the large box with the real jewelry. The safety deposit box
with the card would be storing the location of another box; it would be equivalent to a pointer. In
the computer, pointers are just variables that store memory addresses, usually the addresses of
other variables.

The cool thing is that once you can talk about the address of a variable, you'll then be able to go
to that address and retrieve the data stored in it. If you happen to have a huge piece of data that
you want to pass into a function, it's a lot easier to pass its location to the function than to copy
every element of the data! Moreover, if you need more memory for your program, you can
request more memory from the system--how do you get "back" that memory? The system tells
you where it is located in memory; that is to say, you get a memory address back. And you need
pointers to store the memory address.

A note about terms: the word pointer can refer either to a memory address itself, or to a variable
that stores a memory address. Usually, the distinction isn't really that important: if you pass a
pointer variable into a function, you're passing the value stored in the pointer--the memory
address. When I want to talk about a memory address, I'll refer to it as a memory address; when I
want a variable that stores a memory address, I'll call it a pointer. When a variable stores the
address of another variable, I'll say that it is "pointing to" that variable.

C Pointer Syntax
Pointers require a bit of new syntax because when you have a pointer, you need the ability to
both request the memory location it stores and the value stored at that memory location.
Moreover, since pointers are somewhat special, you need to tell the compiler when you declare
your pointer variable that the variable is a pointer, and tell the compiler what type of memory it
points to.

The pointer declaration looks like this:


<variable_type> *<name>;
For example, you could declare a pointer that stores the address of an integer with the following
syntax:
int *points_to_integer;
Notice the use of the *. This is the key to declaring a pointer; if you add it directly before the
variable name, it will declare the variable to be a pointer. Minor gotcha: if you declare multiple
pointers on the same line, you must precede each of them with an asterisk:
/* one pointer, one regular int */
int *pointer1, nonpointer1;

/* two pointers */
int *pointer1, *pointer2;
As I mentioned, there are two ways to use the pointer to access information: it is possible to have
it give the actual address to another variable. To do so, simply use the name of the pointer
without the *. However, to access the actual memory location and the value stored there, use the

Page 31 of 58
*. The technical name for this doing this is dereferencing the pointer; in essence, you're taking
the reference to some memory address and following it, to retrieve the actual value. It can be
tricky to keep track of when you should add the asterisk. Remember that the pointer's natural use
is to store a memory address; so when you use the pointer:
call_to_function_expecting_memory_address(pointer);
then it evaluates to the address. You have to add something extra, the asterisk, in order to retrieve
the value stored at the address. You'll probably do that an awful lot. Nevertheless, the pointer
itself is supposed to store an address, so when you use the bare pointer, you get that address
back.

Pointing to Something: Retrieving an Address


In order to have a pointer actually point to another variable it is necessary to have the memory
address of that variable also. To get the memory address of a variable (its location in memory),
put the & sign in front of the variable name. This makes it give its address. This is called the
address-of operator, because it returns the memory address. Conveniently, both ampersand and
address-of start with a; that's a useful way to remember that you use & to get the address of a
variable.

For example:
#include <stdio.h>

int main()
{
int x; /* A normal integer*/
int *p; /* A pointer to an integer ("*p" is an integer, so p
must be a pointer to an integer) */

p = &x; /* Read it, "assign the address of x to p" */


scanf( "%d", &x ); /* Put a value in x, we could also use p here */
printf( "%d\n", *p ); /* Note the use of the * to get the value */
getchar();
}
The printf outputs the value stored in x. Why is that? Well, let's look at the code. The integer is
called x. A pointer to an integer is then defined as p. Then it stores the memory location of x in
pointer by using the address operator (&) to get the address of the variable. Using the ampersand
is a bit like looking at the label on the safety deposit box to see its number rather than looking
inside the box, to get what it stores. The user then inputs a number that is stored in the variable x;
remember, this is the same location that is pointed to by p. In fact, since we use an ampersand to
pass the value to scanf, it should be clear that scanf is putting the value in the address pointed to
by p. (In fact, scanf works because of pointers!)

The next line then passes *p into printf. *p performs the "dereferencing" operation on p; it looks
at the address stored in p, and goes to that address and returns the value. This is akin to looking
inside a safety deposit box only to find the number of (and, presumably, the key to ) another box,
which you then open.

Notice that in the above example, the pointer is initialized to point to a specific memory address

Page 32 of 58
before it is used. If this was not the case, it could be pointing to anything. This can lead to
extremely unpleasant consequences to the program. For instance, the operating system will
probably prevent you from accessing memory that it knows your program doesn't own: this will
cause your program to crash. If it let you use the memory, you could mess with the memory of
any running program--for instance, if you had a document opened in Word, you could change the
text! Fortunately, Windows and other modern operating systems will stop you from accessing
that memory and cause your program to crash. To avoid crashing your program, you should
always initialize pointers before you use them.

It is also possible to initialize pointers using free memory. This allows dynamic allocation of
memory. It is useful for setting up structures such as linked lists or data trees where you don't
know exactly how much memory will be needed at compile time, so you have to get memory
during the program's execution. We'll look at these structures later, but for now, we'll simply
examine how to request memory from and return memory to the operating system.

The function malloc, residing in the stdlib.h header file, is used to initialize pointers with
memory from free store (a section of memory available to all programs). malloc works just like
any other function call. The argument to malloc is the amount of memory requested (in bytes),
and malloc gets a block of memory of that size and then returns a pointer to the block of memory
allocated.

Since different variable types have different memory requirements, we need to get a size for the
amount of memory malloc should return. So we need to know how to get the size of different
variable types. This can be done using the keyword sizeof, which takes an expression and returns
its size. For example, sizeof(int) would return the number of bytes required to store an integer.
#include <stdlib.h>

int *ptr = malloc( sizeof(int) );


This code set ptr to point to a memory address of size int. The memory that is pointed to
becomes unavailable to other programs. This means that the careful coder should free this
memory at the end of its usage lest the memory be lost to the operating system for the duration of
the program (this is often called a memory leak because the program is not keeping track of all of
its memory).

Note that it is slightly cleaner to write malloc statements by taking the size of the variable
pointed to by using the pointer directly:
int *ptr = malloc( sizeof(*ptr) );
What's going on here? sizeof(*ptr) will evaluate the size of whatever we would get back from
dereferencing ptr; since ptr is a pointer to an int, *ptr would give us an int, so sizeof(*ptr) will
return the size of an integer. So why do this? Well, if we later rewrite the declaration of ptr the
following, then we would only have to rewrite the first part of it:
float *ptr = malloc( sizeof(*ptr) );
We don't have to go back and correct the malloc call to use sizeof(float). Since ptr would be
pointing to a float, *ptr would be a float, so sizeof(*ptr) would still give the right size!

This becomes even more useful when you end up allocating memory for a variable far after the
point you declare it:

Page 33 of 58
float *ptr;
/* hundreds of lines of code */
ptr = malloc( sizeof(*ptr) );

The free function returns memory to the operating system.


free( ptr );
After freeing a pointer, it is a good idea to reset it to point to 0. When 0 is assigned to a pointer,
the pointer becomes a null pointer, in other words, it points to nothing. By doing this, when you
do something foolish with the pointer (it happens a lot, even with experienced programmers),
you find out immediately instead of later, when you have done considerable damage.

The concept of the null pointer is frequently used as a way of indicating a problem--for instance,
malloc returns 0 when it cannot correctly allocate memory. You want to be sure to handle this
correctly--sometimes your operating system might actually run out of memory and give you this
value!

There are few important operations, which we will do with the help of pointers very frequently. (a) we
define a pointer variable (b) assign the address of a variable to a pointer and (c) finally access the value at
the address available in the pointer variable. This is done by using unary operator * that returns the value
of the variable located at the address specified by its operand. Following example makes use of these
operations:

#include <stdio.h>

int main ()

int var = 20; /* actual variable declaration */

int *ip; /* pointer variable declaration */

ip = &var; /* store address of var in pointer variable*/

printf("Address of var variable: %x\n", &var );

/* address stored in pointer variable */

printf("Address stored in ip variable: %x\n", ip );

Page 34 of 58
/* access the value using the pointer */

printf("Value of *ip variable: %d\n", *ip );

Functions
In C, all functions must be written to return a specific TYPE of information and to take in
specific types of data (parameters). This information is communicated to the compiler via a
function prototype.

RETURN_TYPE name_of_function ( PARAMETER_TYPE


name_of_param,PARAMETER_TYPE name_of_param, etc);

// here are some examples of prototypes used at the top of a file:


float sqrt( float x );

float average( int grades[], int length );

A Prototype can occur at the top of a C source code file to describe what the function returns
and what it takes (return type and parameter list). When this is the case (occuring at the top of the
file), the function prototype should be followed by a semi-colon

The function prototype is also used at the beginning of the code for the function. Thus the
prototype can occur twice in a C source code file. When the prototype occurs with the code NO
semicolon is used.

Void Functions

If a function does not return a value, then a special "TYPE" is used to tell the computer this. The
return type is "void" (all lower case).

Void functions are mostly used in two classes of functions.

The first is a function that prints information for the user to read. For example (for our purposes),
the printf function is treated as a void function. (In actuality, printf returns an integer which is the
number of characters printed... but we almost always ignore this value.)

Page 35 of 58
The second use of void functions is with "reference" parameters (e.g., Arrays). A reference
parameter is not a copy of the input data, as is so often the case. A reference parameter is an
"alias" for the same bucket in memory as the input data. Thus any change made to a reference
parameter is in fact made to the original variable!

#include <stdio.h>

int mult ( int x, int y );

int main()
{
int x;
int y;

printf( "Please input two numbers to be multiplied: " );


scanf( "%d", &x );
scanf( "%d", &y );
printf( "The product of your two numbers is %d\n", mult( x, y ) );
getchar();
}

int mult (int x, int y)


{
return x * y;
}

Parameters in C functions
A Parameter is the symbolic name for "data" that goes into a function. There are two types of
parameters in C: Pass by Value, Pass by Reference.

Pass by Value

Pass by Value, means that a copy of the data is made and stored by way of the name of
the parameter. Any changes to the parameter have NO affect on data in the calling
function.

Pass by Reference

A reference parameter "refers" to the original data in the calling function. Thus any
changes made to the parameter are ALSO MADE TO THE ORIGINAL variable.

There are two ways to make a pass by reference parameter:

1. ARRAYS

Arrays are always pass by reference in C. Any change made to the parameter
containing the array will change the value of the original array.

Page 36 of 58
2. The ampersand used in the function prototype.

function ( & parameter_name )

To make a normal parameter into a pass by reference parameter, we use the "&
param" notation. The ampersand (&) is the syntax to tell C that any changes made
to the parameter also modify the original variable containing the data.

Pass by Value Example:

In C, the default is to pass by value. For example:

//

// C function using pass by value. (Notice no &)

//

void

doit( int x )

x = 5;

//

// Test function for passing by value (i.e., making a copy)

//

int

main()

int z = 27;

doit( z );

Page 37 of 58
printf("z is now %d\n", z);

return 0;

Pass by Reference Example:

Again, remember the Syntax is to use the '&' in front of the variable. For example:

//
// C using Reference Parameter!
//
void
doit( int & x )
{
x = 5;
}

//
// Test code for passing by a variable by reference
//
int
main()
{
int z = 27;
doit( z );
printf(“z is now %d\n”, z);

return 0;
}
Array Parameter Example

Arrays are always passed by reference in C. They do not use the '&' notation, but are pass by
reference none the less. For example:

void
build_array( int array_variable[], int length_of_array )
{
for (int i=0; i<length_of_array; i++)
{
array_variable[i] = i;
}
}

//
// Test code for passing an array by reference
//

Page 38 of 58
int
main()
{
int values[50];

printf(“the value at location 7 starts as %d\n”, values[7]);

build_array(values, 50);

printf(“the value at location 7 is now %d\n”, values[7]);

return 0;
}

Structures
Structures in C are similar to records in Pascal. For example:

struct gun
{
char name[50];
int magazinesize;
float calibre;
};

struct gun arnies;

defines a new structure gun and makes arnies an instance of it.

NOTE: that gun is a tag for the structure that serves as shorthand for future declarations. We
now only need to say struct gun and the body of the structure is implied as we do to make
the arnies variable. The tag is optional.

Variables can also be declared between the } and ; of a struct declaration, i.e.:

struct gun
{
char name[50];
int magazinesize;
float calibre;
} arnies;

Page 39 of 58
struct's can be pre-initialised at declaration:

struct gun arnies={"Uzi",30,7};

which gives arnie a 7mm. Uzi with 30 rounds of ammunition.

To access a member (or field) of a struct, C provides the . operator. For example, to
give arnie more rounds of ammunition:

arnies.magazineSize=100;

Defining New Data Types


typedef can also be used with structures. The following creates a new type agun which is of
type struct gun and can be initialised as usual:

typedef struct gun


{
char name[50];
int magazinesize;
float calibre;
} agun;

agun arnies={"Uzi",30,7};

Here gun still acts as a tag to the struct and is optional. Indeed since we have defined a new data
type it is not really of much use,

agun is the new data type. arnies is a variable of type agun which is a structure.

C also allows arrays of structures:

typedef struct gun


{
char name[50];
int magazinesize;
float calibre;
} agun;

agun arniesguns[1000];

This gives arniesguns a 1000 guns. This may be used in the following way:

Page 40 of 58
arniesguns[50].calibre=100;

gives Arnie's gun number 50 a calibre of 100mm, and:

itscalibre=arniesguns[0].calibre;
assigns the calibre of Arnie's first gun to itscalibre.

Unions
A union is a variable which may hold (at different times) objects of different sizes and types. C
uses the union statement to create unions, for example:

union number
{
short shortnumber;
long longnumber;
double floatnumber;
} anumber

defines a union called number and an instance of it called anumber. number is a union tag and
acts in the same way as a tag for a structure.

Members can be accessed in the following way:

printf("%ld n",anumber.longnumber);

This clearly displays the value of longnumber.

When the C compiler is allocating memory for unions it will always reserve enough room for the
largest member (in the above example this is 8 bytes for the double).

In order that the program can keep track of the type of union variable being used at a given time
it is common to have a structure (with union embedded in it) and a variable which flags the union
type:

An example is:

typedef struct

Page 41 of 58
{ int maxpassengers;
} jet;

typedef struct
{ int liftcapacity;
} helicopter;

typedef struct
{ int maxpayload;
} cargoplane;

typedef union
{ jet jetu;
helicopter helicopteru;
cargoplane cargoplaneu;
} aircraft;

typedef struct
{ aircrafttype kind;
int speed;
aircraft description;
} an_aircraft;

This example defines a base union aircraft which may either be jet, helicopter, or
cargoplane.

In the an_aircraft structure there is a kind member which indicates which structure is being held
at the time.

Enumerated Types
Enumerated types contain a list of constants that can be addressed in integer values.

We can declare types and variables as follows.

enum days {mon, tues, ..., sun} week;

enum days week1, week2;

NOTE: As with arrays first enumerated name has index value 0. So mon has value 0, tues 1, and
so on.

week1 and week2 are variables.

Page 42 of 58
We can define other values:

enum escapes { bell = `\a’,


backspace = `\b', tab = `\t',
newline = `\n', vtab = `\v',
return = `\r'};

We can also override the 0 start value:

enum months {jan = 1, feb, mar, ......, dec};

Here it is implied that feb = 2 etc.

Coercion or Type-Casting
C is one of the few languages to allow coercion, that is forcing one variable of one type to be
another type. C allows this using the cast operator (). So:

int integernumber;
float floatnumber=9.87;

integernumber=(int)floatnumber;

assigns 9 (the fractional part is thrown away) to integernumber.

And:

int integernumber=10;
float floatnumber;

floatnumber=(float)integernumber;

assigns 10.0 to floatnumber.

Coercion can be used with any of the simple data types including char, so:

Page 43 of 58
int integernumber;
char letter='A';

integernumber=(int)letter;

assigns 65 (the ASCII code for `A') to integernumber.

Some typecasting is done automatically -- this is mainly with integer compatibility.

A good rule to follow is: If in doubt cast.

Another use is the make sure division behaves as requested: If we have two
integers internumber and anotherint and we want the answer to be a float then :

e.g.
floatnumber =
(float) internumber / (float) anotherint;

ensures floating point division.

Static Variables
A static variable is local to particular function. However, it is only initialised once (on the first
call to function).

Also the value of the variable on leaving the function remains intact. On the next call to the
function the the static variable has the same value as on leaving.

To define a static variable simply prefix the variable declaration with the static keyword. For
example:

void stat(); /* prototype fn */

main()
{ int i;

for (i=0;i<5;++i)
stat();
}

Page 44 of 58
stat()

{ int auto_var = 0;

static int static_var = 0;

printf( "auto = %d, static = %d \n",

auto_var, static_var);

++auto_var;

++static_var;

Output is:

auto_var = 0, static_var= 0
auto_var = 0, static_var = 1
auto_var = 0, static_var = 2
auto_var = 0, static_var = 3
auto_var = 0, static_var = 4

Clearly the auto_var variable is created each time. The static_var is created once and remembers its value.

Files
Files are the most common form of a stream.

The first thing we must do is open a file. The function fopen() does this:

FILE *fopen(char *name, char *mode)

fopen returns a pointer to a FILE. The name string is the name of the file on disc that we wish to
access. The mode string controls our type of access. If a file cannot be accessed for any reason
a NULL pointer is returned.

Modes include: "r" -- read,


"w" -- write and
"a" -- append.

Page 45 of 58
To open a file we must have a stream (file pointer) that points to a FILE structure.

So to open a file, called myfile.dat for reading we would do:

FILE *stream, *fopen();


/* declare a stream and prototype fopen */

stream = fopen("myfile.dat","r");

it is good practice to to check file is opened

correctly:

if ( (stream = fopen( "myfile.dat",

"r")) == NULL)

{ printf("Can't open %s\n"",

"myfile.dat");

exit(1);

......

Reading and writing files


The functions fprintf and fscanf a commonly used to access files.

int fprintf(FILE *stream, char *format, args..)


int fscanf(FILE *stream, char *format, args..)

These are similar to printf and scanf except that data is read from the stream that must have been
opened with fopen().
Page 46 of 58
The stream pointer is automatically incremented with ALL file read/write functions. We do
not have to worry about doing this.

char *string[80]
FILE *stream, *fopen();

if ( (stream = fopen(...)) != NULL)


fscanf(stream,"%s", string);

Other functions for files:

int getc(FILE *stream), int fgetc(FILE *stream)

int putc(char ch, FILE *s), int fputc(char ch, FILE *s)

These are like getchar, putchar.

getc is defined as preprocessor MACRO in stdio.h. fgetc is a C library function. Both achieve the
same result!!

fflush(FILE *stream) -- flushes a stream.

fclose(FILE *stream) -- closes a stream.

We can access predefined streams with fprintf etc.

fprintf(stderr,"Cannot Compute!!\n");

fscanf(stdin,"%s",string);

sprintf and sscanf


These are like fprintf and fscanf except they read/write to a string.

int sprintf(char *string, char *format, args..)

int sscanf(char *string, char *format, args..)

For Example:

float full_tank = 47.0; /* litres */


float miles = 300;
char miles_per_litre[80];

Page 47 of 58
sprintf( miles_per_litre,"Miles per litre
= %2.3f", miles/full_tank);

Stream Status Enquiries


There are a few useful stream enquiry functions, prototyped as follows:

int feof(FILE *stream);


int ferror(FILE *stream);
void clearerr(FILE *stream);
int fileno(FILE *stream);

Their use is relatively simple:

feof()
-- returns true if the stream is currently at the end of the file. So to read a stream,fp, line
by line you could do:
while ( !feof(fp) )
fscanf(fp,"%s",line);
ferror()
-- reports on the error state of the stream and returns true if an error has occurred.
clearerr()
-- resets the error indication for a given stream.
fileno()
-- returns the integer file descriptor associated with the named stream.

Low Level I/O


This form of I/O is UNBUFFERED -- each read/write request results in accessing disk (or
device) directly to fetch/put a specific number of bytes.

There are no formatting facilities -- we are dealing with bytes of information.

This means we are now using binary (and not text) files.

Instead of file pointers we use low level file handle or file descriptors which give a unique
integer number to identify each file.

To Open a file use:

int open(char *filename, int flag, int perms) -- this returns a file descriptor or -1 for a fail.

Page 48 of 58
The flag controls file access and has the following predefined in fcntl.h:

O_APPEND, O_CREAT, O_EXCL, O_RDONLY, O_RDWR, O_WRONLY + others see


online man pages or reference manuals.

perms -- best set to 0 for most of our applications.

The function:

creat(char *filename, int perms)

can also be used to create a file.

int close(int handle) -- close a file

int read(int handle, char *buffer,


unsigned length)

int write(int handle, char *buffer, unsigned length)

are used to read/write a specific number of bytes from/to a file (handle) stored or to be put in the
memory location specified by buffer.

The sizeof() function is commonly used to specify the length.

read and write return the number of bytes read/written or -1 if they fail.

/* program to read a list of floats from a binary file */


/* first byte of file is an integer saying how many */
/* floats in file. Floats follow after it, File name got from */
/* command line */

#include<stdio.h>
#include<fcntl.h>

float bigbuff[1000];

main(int argc, char **argv)

{ int fd;
int bytes_read;
int file_length;

if ( (fd = open(argv[1],O_RDONLY)) = -1)


{ /* error file not open */....

Page 49 of 58
perror("Datafile");
exit(1);
}
if ( (bytes_read = read(fd,&file_length,
sizeof(int))) == -1)
{ /* error reading file */...
exit(1);
}
if ( file_length > 999 ) {/* file too big */ ....}
if ( (bytes_read = read(fd,bigbuff,
file_length*sizeof(float))) == -1)
{ /* error reading open */...
exit(1);
}
}

fopen and freopen opens the file whose name is in the string pointed to by filename and
associates a stream with it. Both return a pointer to the object controlling the stream, or if the
open operation fails a null pointer. The error and end-of-file indicators are cleared, and if the
open operation fails error is set. freopen differs from fopen in that the file pointed to by stream is
closed first when already open and any close errors are ignored.

mode for both functions points to a string consisting of one of the following sequences:
r open a text file for reading
w truncate to zero length or create a text file for writing
a append; open or create text file for writing at end-of-file
rb open binary file for reading
wb truncate to zero length or create a binary file for writing
ab append; open or create binary file for writing at end-of-file
r+ open text file for update (reading and writing)
w+ truncate to zero length or create a text file for update
a+ append; open or create text file for update
r+b or open binary file for update (reading and writing)
rb+
w+b or truncate to zero length or create a binary file for update
wb+

a+b or append; open or create binary file for update


ab+

Page 50 of 58
Opening a file with read mode ('r' as the first character in the mode argument) fails if the file
does not exist or cannot be read.

Opening a file with append mode ('a' as the first character in the mode argument) causes all
subsequent writes to the file to be forced to the then-current end-of-file, regardless of intervening
calls to the fseek function. In some implementations, opening a binary file with append mode ('b'
as the second or third character in the above list of mode arguments) may initially position the
file position indicator for the stream beyond the last data written, because of null character
padding.

When a file is opened with update mode ('+' as the second or third character in the above list of
mode argument values), both input and output may be performed on the associated stream.
However, output may not be directly followed by input without an intervening call to the fflush
function or to a file positioning function (fseek, fsetpos, or rewind), and input may not be
directly followed by output without an intervening call to a file positioning function, unless the
input operation encounters end-of-file. Opening (or creating) a text file with update mode may
instead open (or create) a binary stream in some implementations.

When opened, a stream is fully buffered if and only if it can be determined not to refer to an
interactive device.

Closing Files
#include <stdio.h>

int fclose(FILE *stream);

The fclose function causes the stream pointed to by stream to be flushed and the associated file
to be closed. Any unwritten buffered data for the stream are delivered to the host environment to
be written to the file; any unread buffered data are discarded. The stream is disassociated from
the file. If the associated buffer was automatically allocated, it is deallocated. The function
returns zero if the stream was successfully closed or EOF if any errors were detected.

Page 51 of 58
Other file access functions

The fflush function

#include <stdio.h>

int fflush(FILE *stream);

If stream points to an output stream or an update stream in which the most recent operation was
not input, the fflush function causes any unwritten data for that stream to be deferred to the host
environment to be written to the file. The behavior of fflush is undefined for input stream.

If stream is a null pointer, the fflush function performs this flushing action on all streams for
which the behavior is defined above.

The fflush functions returns EOF if a write error occurs, otherwise zero.

The reason for having a fflush function is because streams in C can have buffered input/output;
that is, functions that write to a file actually write to a buffer inside the FILE structure. If the
buffer is filled to capacity, the write functions will call fflush to actually "write" the data that is
in the buffer to the file. Because fflush is only called every once in a while, calls to the operating
system to do a raw write are minimized.

int fclose(FILE *stream);

The fclose function causes the stream pointed to by stream to be flushed and the associated file
to be closed. Any unwritten buffered data for the stream are delivered to the host environment to
be written to the file; any unread buffered data are discarded. The stream is disassociated from
the file. If the associated buffer was automatically allocated, it is deallocated. The function
returns zero if the stream was successfully closed or EOF if any errors were detected.

int fflush(FILE *stream);

Page 52 of 58
If stream points to an output stream or an update stream in which the most recent operation was
not input, the fflush function causes any unwritten data for that stream to be deferred to the host
environment to be written to the file. The behavior of fflush is undefined for input stream.

If stream is a null pointer, the fflush function performs this flushing action on all streams for
which the behavior is defined above.

The fflush functions returns EOF if a write error occurs, otherwise zero.

int fseek(FILE *stream, long int offset, int whence);


long int ftell(FILE *stream);

The fseek function sets the file position indicator for the stream pointed to by stream.

For a binary stream, the new position, measured in characters from the beginning of the file, is
obtained by adding offset to the position specified by whence. Three macros in stdio.h called
SEEK_SET, SEEK_CUR, and SEEK_END expand to unique values. If the position specified by
whence is SEEK_SET, the specified position is the beginning of the file; if whence is SEEK_END, the
specified position is the end of the file; and if whence is SEEK_CUR, the specified position is the
current file position. A binary stream need not meaningfully support fseek calls with a whence
value of SEEK_END.

For a text stream, either offset shall be zero, or offset shall be a value returned by an earlier call to
the ftell function on the same stream and whence shall be SEEK_SET.

The fseek function returns nonzero only for a request that cannot be satisfied.

The ftell function obtains the current value of the file position indicator for the stream pointed to
by stream. For a binary stream, the value is the number of characters from the beginning of the
file; for a text stream, its file position indicator contains unspecified information, usable by the
fseek function for returning the file position indicator for the stream to its position at the time of
the ftell call; the difference between two such return values is not necessarily a meaningful
measure of the number of characters written or read.

Page 53 of 58
If successful, the ftell function returns the current value of the file position indicator for the
stream. On failure, the ftell function returns -1L and stores an implementation-defined positive
value in errno.

void rewind(FILE *stream);


The rewind function sets the file position indicator for the stream pointed to by stream to the beginning of
the file. It is equivalent to

fseek(stream, 0L, SEEK_SET)


except that the error indicator for the stream is also cleared.

int feof(FILE *stream);


The feof function tests the end-of-file indicator for the stream pointed to by stream and returns nonzero if
and only if the end-of-file indicator is set for stream, otherwise it returns zero.

The stdio.h library has a variety of functions that do some operation on files besides reading and writing.

int remove(const char *filename);

The remove function causes the file whose name is the string pointed to by filename to be no longer
accessible by that name. A subsequent attempt to open that file using that name will fail, unless it
is created anew. If the file is open, the behavior of the remove function is implementation-defined.

The remove function returns zero if the operation succeeds, nonzero if it fails.

int rename(const char *old_filename, const char *new_filename);

The rename function causes the file whose name is the string pointed to by old_filename to be
henceforth known by the name given by the string pointed to by new_filename. The file named
old_filename is no longer accessible by that name. If a file named by the string pointed to by
new_filename exists prior to the call to the rename function, the behavior is implementation-defined.

The rename function returns zero if the operation succeeds, nonzero if it fails, in which case if the
file existed previously it is still known by its original name.

Direct input function: the fread function


size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);

Page 54 of 58
The fread function reads, into the array pointed to by ptr, up to nmemb elements whose size is
specified by size, from the stream pointed to by stream. The file position indicator for the stream
(if defined) is advanced by the number of characters successfully read. If an error occurs, the
resulting value of the file position indicator for the stream is indeterminate. If a partial element is
read, its value is indeterminate.

The fread function returns the number of elements successfully read, which may be less than
nmemb if a read error or end-of-file is encountered. If size or nmemb is zero, fread returns zero and
the contents of the array and the state of the stream remain unchanged.

size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream);

The fwrite function writes, from the array pointed to by ptr, up to nmemb elements whose size is specified
by size to the stream pointed to by stream. The file position indicator for the stream (if defined) is
advanced by the number of characters successfully written. If an error occurs, the resulting value of the
file position indicator for the stream is indeterminate. The function returns the number of elements
successfully written, which will be less than nmemb only if a write error is encountered.

Exercises
1. Input two numbers and work out their sum, average and sum of the squares of the
numbers.
2. Write a program that works out the largest and smallest values from a set of 10 inputted
numbers.
3. Write a program to read a "float" representing a number of degrees Celsius, and print as a
"float" the equivalent temperature in degrees Fahrenheit. Print your results in a form such
as 100.0 degrees Celsius converts to 212.0 degrees Fahrenheit.
4. Write a program to read a number of units of length (a float) and print out the area of a
circle of that radius. Assume that the value of pi is 3.14159

Page 55 of 58
5. Given as input a floating (real) number of centimeters, print out the equivalent number of
feet (integer) and inches (floating, 1 decimal), with the inches given to an accuracy of one
decimal place.
Assume 2.54 centimeters per inch, and 12 inches per foot.
If the input value is 333.3, the output format should be:
333.3 centimeters is 10 feet 11.2 inches.

6. Given as input an integer number of seconds, print as output the equivalent time in hours,
minutes and seconds. Recommended output format is something like
7. 7322 seconds is equivalent to 2 hours 2 minutes 2 seconds.
8. Write a program to read two characters, and print their value when interpreted as a 2-digit
hexadecimal number. Accept upper case letters for values from 10 to 15.
9. Read an integer value. Assume it is the number of a month of the year; print out the name
of that month.
10. Given as input three integers representing a date as day, month, year, print out the
number day, month and year for the following day's date.
11. Typical input: 28 2 1992 Typical output: Date following 28:02:1992 is 29:02:1992
12. Read a positive integer value, and compute the following sequence: If the number is
even, halve it; if it's odd, multiply by 3 and add 1. Repeat this process until the value is 1,
printing out each value. Finally print out how many of these operations you performed.

Typical output might be:

Inital value is 9
Next value is 28
Next value is 14
Next value is 7
Next value is 22
Next value is 11
Next value is 34
Next value is 17
Next value is 52
Next value is 26
Next value is 13
Next value is 40
Next value is 20
Next value is 10
Next value is 5

Page 56 of 58
Next value is 16
Next value is 8
Next value is 4
Next value is 2
Final value 1, number of steps 19
If the input value is less than 1, print a message containing the word
Error
and perform an
exit( 0 );
13. Calculate simple interest.
14. Write a program to print the multiplication table for the given number.
15. Find whether a given number is even or odd.
16. Find the large number from the given three numbers.
17. Write a program to find the number of vowels, length of string, reverse of string
18. Write a program to find the reverse of given number
19. Write a program to find the largest and smallest element in an array.
20. Write a program to sort an array.
21. Write a program to find whether a given number is Prime or not.
22. Find whether given two strings are anagram or not.
23. Write a program to perform matrix addition, multiplication.
24. Write a program to accept a string and display its alternate characters in reverse.
25. Write a program to find factorial of given number
26. Write program to find Fibonacci series.
27. Write a program to copy the contents of one file to another file.
28. Write a program to display number in binary format.
29. Write a program to rotate, shift by n bit position right of a given unsigned char.
30. Write a program to solve the system of linear equations.
31. Convert a number in one base to another base
32. Write a program for multiple precision integer arithmetic.
33. Develop a game in which the use has to guess whether the next number is greater than the
previous number or not, if his guess is correct he won the game.
34. Write a program to maintain the data of the students.

Page 57 of 58
References
1. Brian W. Kernighan and Dennis M. Ritchie The C programming Language, Published by
Prentice-Hall in 1988 , ISBN 0-13-110362-8 (paperback), ISBN 0-13-110370-9
2. Paul Deitel, Harvey Deitel C: How to Program, 7th Edition, ISBN-13: 978-0132990448,
Deitel & Associates, Inc.
3. Balaguruswamy, Programming in ANSI C, Tata McGraw-Hill Education, 2008, ISBN
978-0-07-064822-7
4. http://www.cs.cf.ac.uk/Dave/C/CE.html
5. http://www.cprogramming.com/tutorial.html
6. http://www.tutorialspoint.com/cprogramming/

Page 58 of 58

You might also like