MC0061
MC0061
The link section provides instructions to the compiler to link functions from the system library.
The definition section defines all symbolic constants.
There are some variables that are used in more than one function. Such variables are called
global variables and are declared in the global declaration section that is outside of all the
functions.
Every C program must have one main function section. This section contains two parts,
declaration part and executable part. The declaration part declares all the variables used in the
executable part. There is at least one statement in the executable part. These two parts must
appear between opening and closing braces ({ and }). The program execution begins at the
opening brace and ends at the closing brace. The closing brace of the main function section is
the logical end of the program. All statements in the declaration and executable parts end with a
semicolon (;).
The subprogram section contains all the user-defined functions that are called in the main
function. User-defined functions are generally placed immediately after the main function,
although they may appear in any order.
All sections, except the main function section may be absent when they are not required.
#include<stdio.h>
int main(){
int a,b,c,big;
printf("\nEnter 3 numbers:");
scanf("%d %d %d",&a,&b,&c);
big=(a>b&&a>c?a:b>c?b:c);
printf("\nThe biggest number is:%d",big);
return 0;
}
1. Integer int
2. Character char
5. Void void
The size and range of each data type is given in the table below
Integers are whole numbers with a machine dependent range of values. A good programming
language as to support the programmer by giving a control on a range of numbers and storage
space. C has 3 classes of integer storage namely short int, int and long int. All of these data
types have signed and unsigned forms. A short int requires half the space than normal integer
values. Unsigned numbers are always positive and consume all the bits for the magnitude of the
number. The long and unsigned integers are used to declare a longer range of values.
Floating point number represents a real number with 6 digits precision. Floating point numbers
are denoted by the keyword float. When the accuracy of the floating point number is
insufficient, we can use the double to define the number. The double is same as float but with
longer precision. To extend the precision further we can use long double which consumes 80
bits of memory space.
Void Type :
Using void data type, we can specify the type of a function. It is a good practice to avoid
functions that does not return any values to the calling function.
Character Type :
A single character can be defined as a defined as a character type of data. Characters are
usually stored in 8 bits of internal storage. The qualifier signed or unsigned can be explicitly
applied to char. While unsigned characters have values between 0 and 255, signed characters
have values from –128 to 127.
Declaration of Variables
Every variable used in the program should be declared to the compiler. The declaration does
two things.
Where v1, v2, v3 are variable names. Variables are separated by commas. A declaration statement
must end with a semicolon.
Example:
Int sum;
Int number, salary;
Double average, mean;
Character char
Signed Short Integer signed short int (or) short int (or) short
Signed Long Integer signed long int (or) long int (or) long
In C language a user can define an identifier that represents an existing data type. The user
defined datatype identifier can later be used to declare variables. The general syntax is
typedef type identifier;
here type represents existing data type and ‘identifier’ refers to the ‘row’ name given to the data
type.
Example:
Here salary symbolizes int and average symbolizes float. They can be later used to declare
variables as follows:
Therefore dept1 and dept2 are indirectly declared as integer datatype and section1 and
section2 are indirectly float data type.
The second type of user defined datatype is enumerated data type which is defined as
follows.
The identifier is a user defined enumerated datatype which can be used to declare
variables that have one of the values enclosed within the braces. After the definition we
can declare variables to be of this ‘new’ type as below.
The enumerated variables V1, V2, ….. Vn can have only one of the values value1, value2
….. value n
Example:
week_st = Monday;
week_end = Friday;
if(wk_st == Tuesday)
week_en = Saturday;
Variables in C have not only the data type but also storage class that provides information
about their location and visibility. The storage class divides the portion of the program within
which the variables are recognized.
auto : It is a local variable known only to the function in which it is declared. Auto is the
default storage class.
static : Local variable which exists and retains its value even after the control is transferred to
the calling function.
A symbolic constant value can be defined as a preprocessor statement and used in the program
as any other constant value. The general form of a symbolic constant is
# define symbolic_name value of constant
# define total 50
# define pi 3.14159
These values may appear anywhere in the program, but must come before it is referenced in the
program.
The values of some variable may be required to remain constant through-out the program. We
can do this by using the qualifier const at the time of initialization.
Example:
The const data type qualifier tells the compiler that the value of the int variable class_size may
not be modified in the program.
Example:
char c;
c=getchar();
The first statement declares that c is a character-type variable. The second statement causes a
single character to be entered from the keyboard and then assign to c.
A companion function is putchar(), which writes one character to the “standard output.” (The
standard output is usually the user’s screen).
putchar(character variable)
Example:
char c;
…
putchar(c);
The first statement declares that c is a character-type variable. The second statement causes the
current value of c to be transmitted to the user monitor where it will be displayed.
Using these two functions, we can write a very basic program to copy the
input, a character at a time, to the output:
#include <stdio.h>
main()
int c;
c = getchar();
while(c != EOF)
putchar(c);
c = getchar();
return 0;
It reads one character, and if it is not the EOF code, enters a while loop, printing one character
and reading another, as long as the character read is not EOF. A char variable could hold
integers corresponding to character set values, and that an int could hold integers of more
arbitrary values(from -32768 to + 32767). Since most character sets contain a few hundred
characters (nowhere near 32767), an int variable can in general comfortably hold all char
values, and then some. Therefore, there’s nothing wrong with declaring c as an int. But in fact,
it’s important to do so, because getchar() can return every character value, plus that special,
non-character value EOF, indicating that there are no more characters. Type char is only
guaranteed to be able to hold all the character values; it is not guaranteed to be able to hold
EOF value without possibly mixing it up with some actual character value. Therefore, you
should always remember to use an int for anything you assign getchar()’s return value to.
When you run the character copying program, and it begins copying its input (you’re typing) to
its output (your screen), you may find yourself wondering how to stop it. It stops when it
receives end-of-file (EOF), but how do you send EOF? The answer depends on what kind of
computer you’re using. On Unix and Unix-related systems, it’s almost always control-D. On
MS-DOS machines, it’s control-Z followed by the RETURN key.
(Note, too, that the character you type to generate an end-of-file condition from the keyboard is
not the same as the special EOF value returned by getchar(). The EOF value returned by
getchar() is a code indicating that the input system has detected an end-of-file condition,
whether it’s reading the keyboard or a file or a magnetic tape or a network connection or
anything else. In a disk file, at least, there is not likely to be any character in the file
corresponding to EOF; as far as your program is concerned, EOF indicates the absence of any
more characters to read.)
Another excellent thing to know when doing any kind of programming is how to terminate a
runaway program. If a program is running forever waiting for input, you can usually stop it by
sending it an end-of-file, as above, but if it’s running forever not waiting for something, you’ll
have to take more drastic measures. Under Unix, control-C (or, occasionally, the DELETE key)
will terminate the current program, almost no matter what. Under MS-DOS, control-C or
control-BREAK will sometimes terminate the current program.
When one of the operands is real and the other is integer, the expression is called a mixed-mode
arithmetic expression. If either operand is of the real type, then only the real operation is
performed and the result is always real number. Thus
25 / 10.0 = 2.5
Where as 25 / 10 =2
C performs type conversions automatically. However, there are instances when we want to
force a type conversion in a way that is different from the automatic conversion. Consider, for
example, the calculation of ratio of doctors to engineers in a town.
Since doctor _number and engineer_number are declared as integers in the program, the
decimal part of the result of the division would be lost and Ratio would represent a wrong
figure. This problem can be solved by converting locally one of the variables to the floating
point as shown below:
The operator (float) converts the doctor_number to floating point for the purpose of evaluation
of the expression. Then using the rule of automatic conversion, the division is performed in
floating point mode, thus retaining the fractional part of the result. Note that in no way does the
operator (float) affect the value of the variable doctor_number. And also, the type of
doctor_number remains as int in the other parts of the program.
The process of such local conversion is known as casting a value. The general form of cast is:
(type-name) expression
where type-name is one of the standard C data types. The expression may be a constant,
variable or an expression. The Table 4.2 shows some examples of casts and their actions:
Example Action
8.5 is converted to integer by truncation.
X=(int) 8.5
Use of Casts
main()
{ �
float avg;
int n=2,n1,n2;
scanf(”%d %d”,&n1,&n2);
avg=(n1+n2)/(float)n;
Casting can be used to round-off a given value. Consider the following statement:
X= (int)
(y+0.5);
If y is 37.7, y+0.5 is 38.2 and on casting, the result becomes 38, the value that is assigned to X.
Of course, the expression , being cast is not changed.
When combining two different types of variables in an expression, never assume the rules of
automatic conversion. It is always a good practice to explicitly force the conversion. It is more
safer and more portable. For example, when y and p are double and m is int , the following two
statements are equivalent.
y = p + m;
y = p + (double)m;
However, the second statement is preferable. It will work the same way on all machines and is
more readable.
A single character can be defined as a character(char) type data. Characters are usually stored
in 8 bits (one byte) of internal storage. The qualifier signed or unsigned may be explicitly
applied to char. While unsigned chars have values between 0 and 255, signed chars have
values from -128 to 127.
A character constant is formed by enclosing the character within a pair of single quote marks.
So ‘b’, ‘.’ and ‘5′ are all valid examples of character constants. Note that a character constant,
which is a single character enclosed in single quotes is different from a character string, which
is any number of characters enclosed in double quotes.
The format characters %c can be used in a printf statement to display the value of a char
variable at the terminal.
Program 4.5: The following program illustrates how to use char data type.
#include<stdio.h>
main()
char c=’A';
int a=65;
printf(”%c\n”, c);
printf(”%d\n”, c);
printf(”%c\n”,a);
Output
65
Note that with the format characters %d, the ASCII number of the character is displayed. With
the format character %c, the character corresponding to the given ASCII number is displayed.
Like other variables pointer variables can be used in expressions. For example if p1 and p2 are
properly declared and initialized pointers, then the following statements are valid.
y=*p1**p2;
sum=sum+*p1;
z= 5* - *p2/p1;
*p2= *p2 + 10;
C allows us to add integers to or subtract integers from pointers as well as to subtract one
pointer from the other. We can also use short hand operators with the pointers p1+=;
sum+=*p2; etc.,
we can also compare pointers by using relational operators the expressions such as p1 >p2 ,
p1==p2 and p1!=p2 are allowed.
Arrays are used to store large set of data and manipulate them but the disadvantage is
that all the elements stored in an array are to be of the same data type. If we need to
use a collection of different data type items it is not possible using an array. When we
require using a collection of different data items of different data types we can use a
structure. Structure is a method of packing data of different types. A structure is a
convenient method of handling a group of related data items of different data types.
structure definition:
general format:
struct tag_name
{
data type member1;
data type member2;
…
…
}
Example:
struct lib_books
{
char title[20];
char author[15];
int pages;
float price;
};
the keyword struct declares a structure to holds the details of four fields namely title,
author pages and price. These are members of the structures. Each member may
belong to different or same data type. The tag name can be used to define objects that
have the tag names structure. The structure we just declared is not a variable by itself
but a template for the structure.
We can declare structure variables using the tag name any where in the program. For
example the statement,
struct lib_books
{
char title[20];
char author[15];
int pages;
float price;
};
We can also combine both template declaration and variables declaration in one
statement, the declaration
struct lib_books
{
char title[20];
char author[15];
int pages;
float price;
} book1,book2,book3;
is valid. The use of tag name is optional for example
struct
{
…
…
…
}
A structure is usually defines before main along with macro definitions. In such cases
the structure assumes global status and all the functions can access the structure.
For example:
Book1.price
Is the variable representing the price of book1 and can be treated like any other
ordinary variable. We can use scanf statement to assign values like
scanf(“%s”,book1.file);
scanf(“%d”,& book1.pages);
strcpy(book1.title,”basic”);
strcpy(book1.author,”Balagurusamy”);
book1.pages=250;
book1.price=28.50;
Initializing structure:
Like other data type we can initialize structure when we declare them. As for
initalization goes structure obeys the same set of rules as arrays we initalize the fields
of a structure by the following structure declaration with a list containing values for
weach fileds as with arrays these values must be evaluate at compile time.
Example:
this initializes the id_no field to 12345, the name field to “kapildev”, the address field to
“pes college” the field combination to “cse” and the age field to 19.
in the declaration of structure type, emp_id and name have been declared as integer
and character array. When we call the function display() using
display(emp1.emp_id,emp1.name);
we are sending the emp_id and name to function display(0);
it can be immediately realized that to pass individual elements would become more
tedious as the number of structure elements go on increasing a better way would be to
pass the entire structure variable at a time.
# include stdio.h>
{
int emp_id;
char name[25];
char department[10];
float salary;
};
void main()
{
static struct employee emp1=
{
12,
“sadanand”,
“computer”,
7500.00
};
Arrays of structure:
It is possible to define a array of structures for example if we are maintaining
information of all the students in the college and if 100 students are studying in the
college. We need to use an array than single variables. We can define an array of
structures as shown in the following example:
structure information
{
int id_no;
char name[20];
char address[20];
char combination[3];
int age;
}
student[100];
An array of structures can be assigned initial values just as any other array can.
Remember that each element is a structure that must be assigned corresponding
initial values as illustrated below.
the sturucture student constains another structure date as its one of its members.
Union:
Unions like structure contain members whose individual data types may differ from
one another. However the members that compose a union all share the same storage
area within the computers memory where as each member within a structure is
assigned its own unique storage area. Thus unions are used to observe memory. They
are useful for application involving multiple members. Where values need not be
assigned to all the members at any one time. Like structures union can be declared
using the keyword union as follows:
union item
{
int m;
float p;
char c;
}
code;
this declares a variable code of type union item. The union contains three members
each with a different data type. However we can use only one of them at a time. This
is because if only one location is allocated for union variable irrespective of size. The
compiler allocates a piece of storage that is large enough to access a union member
we can use the same syntax that we use to access structure members. That is
code.m
code.p
code.c
are all valid member variables. During accessing we should make sure that we are
accessing the member whose value is currently stored.
For example a statement such as
code.m=456;
code.p=456.78;
printf(“%d”,code.m);
Would prodece erroneous result.
#include<stdio.h>
#include<stdlib.h>
struct list
{
int month;
struct list *next;
};
typedef struct list node;
void init(node* record)
{
record->next NULL;
}
void addnode(node* record int d)
{
node* fresh;
fresh (node *)malloc(sizeof(node));
fresh->month d;
fresh->next record->next;
record->next fresh;
}
void print(node *record)
{
node* temp;
temp (node *)malloc(sizeof(node));
for(temp record->next;temp;temp temp->next)
printf(" d" temp->month);
}
Loops generally consist of two parts: one or more control expressions which control the
execution of the loop, and the body, which is the statement or set of statements which is
executed over and over.
The most basic loop in C is the while loop. A while loop has one control expression, and
executes as long as that expression is true. Here before executing the body of the loop, the
condition is tested. Therefore it is called an entry-controlled loop. The following example
repeatedly doubles the number 2 (2, 4, 8, 16, …) and prints the resulting numbers as long as
they are less than 1000:
int x = 2;
printf(”%d\n”, x);
x = x * 2;
}
(Once again, we’ve used braces {} to enclose the group of statements which are to be executed
together as the body of the loop.)
while( expression )
statement(s)
A while loop starts out like an if statement: if the condition expressed by the expression is true,
the statement is executed. However, after executing the statement, the condition is tested again,
and if it’s still true, the statement is executed again. (Presumably, the condition depends on
some value which is changed in the body of the loop.) As long as the condition remains true,
the body of the loop is executed over and over again. (If the condition is false right at the start,
the body of the loop is not executed at all.)
As another example, if you wanted to print a number of blank lines, with the variable n holding
the number of blank lines to be printed, you might use code like this:
while(n > 0)
printf(”\n”);
n = n – 1;
After the loop finishes (when control “falls out” of it, due to the condition being false), n will
have the value 0.
You use a while loop when you have a statement or group of statements which may have to be
executed a number of times to complete their task. The controlling expression represents the
condition “the loop is not done” or “there’s more work to do.” As long as the expression is true,
the body of the loop is executed; presumably, it makes at least some progress at its task. When
the expression becomes false, the task is done, and the rest of the program (beyond the loop)
can proceed. When we think about a loop in this way, we can see an additional important
property: if the expression evaluates to “false” before the very first trip through the loop, we
make zero trips through the loop. In other words, if the task is already done (if there’s no work
to do) the body of the loop is not executed at all. (It’s always a good idea to think about the
“boundary conditions” in a piece of code, and to make sure that the code will work correctly
when there is no work to do, or when there is a trivial task to do, such as sorting an array of one
number. Experience has shown that bugs at boundary conditions are quite common.)
main()
clrscr();
scanf(”%d”,&n);
large=0;
i=0;
while(i<n)
scanf(”%d”, &num);
if(large<num)
large=num;
i++;
}
printf(”\n large = %d”, large);
# include<stdio.h>
# include <math.h>
void main()
int n, i=1,count;
scanf(”%d”, &x);
x=x*3.1416/180.0;
scanf(”%f”, &acc);
sum=x;
term=x;
while ((fabs(term))>acc)
term=-term*x*x/((2*i)*(2*i+1));
sum+=term;
i++;
Do…While loop
The do…while loop is used in a situation where we need to execute the body of the loop before
the test is performed. Therefore, the body of the loop may not be executed at all if the condition
is not satisfied at the very first attempt. Where as while loop makes a test of condition before
the body of the loop is executed.
For above reasons while loop is called an entry-controlled loop and do..while loop is called an
exit-controlled loop.
do
while ( expression);
On reaching the do statement , the program proceeds to evaluate the body of the loop first. At
the end of the loop, the conditional expression in the while statement is evaluated. If the
expression is true, the program continues to evaluate the body of the loop once again. This
process continues as long as the expression is true. When the expression becomes false, the
loop will be terminated and the control goes to the statement that appears immediately after the
while statement.
On using the do loop, the body of the loop is always executed at least once irrespective of the
expression.
1 2 3 4 …………………… 10
2 4 6 8 …………………… 20
3 6 9 12 …………………… 30
4 …………………… 40
..
..
..�
10 100
main()
int rowmax=10,colmax=10,row,col,x;
printf(”………………………………..\n”);
row=1;
do
{
col=1;
do
x=row*col;
printf(”%4d”, x);
col=col+1;
while (col<=colmax);
printf(”\n”);;
row=row+1;
while(row<=rowmax);
Printf(”……………………………………………………………………………………………
…\n”);
}
Simple For loop
The for loop is used to repeat the execution of set of statements for a fixed number of times.
The for loop is also an entry-controlled loop.
(Here we see that the for loop has three control expressions. As always, the statement can be a
brace-enclosed block.)
Many loops are set up to cause some variable to step through a range of values, or, more
generally, to set up an initial condition and then modify some value to perform each succeeding
loop as long as some condition is true. The three expressions in a for loop encapsulate these
conditions: expr1 sets up the initial condition, expr 2 tests whether another trip through the loop
should be taken, and expr3 increments or updates things after each trip through the loop and
prior to the next one. Consider the following :
In the above example, we had i = 0 as expr1, i < 10 as expr2 , i = i + 1 as expr3, and the call to
printf as statement, the body of the loop. So the loop began by setting i to 0, proceeded as long
as i was less than 10, printed out i’s value during each trip through the loop, and added 1 to i
between each trip through the loop.
When the compiler sees a for loop, first, expr1 is evaluated. Then, expr2 is evaluated, and if it
is true, the body of the loop (statement) is executed. Then, expr3 is evaluated to go to the next
step, and expr2 is evaluated again, to see if there is a next step. During the execution of a for
loop, the sequence is:
expr1
expr2 �
statement
expr3
expr2
statement
expr3
expr2
statement
expr3
expr2
The first thing executed is expr1. expr3 is evaluated after every trip through the loop. The last
thing executed is always expr2, because when expr2 evaluates false, the loop exits.
All three expressions of a for loop are optional. If you leave out expr1, there simply is no
initialization step, and the variable(s) used with the loop had better have been initialized
already. If you leave out expr2, there is no test, and the default for the for loop is that another
trip through the loop should be taken (such that unless you break out of it some other way, the
loop runs forever). If you leave out expr3, there is no increment step.
The semicolons separate the three controlling expressions of a for loop. (These semicolons, by
the way, have nothing to do with statement terminators.) If you leave out one or more of the
expressions, the semicolons remain. Therefore, one way of writing a deliberately infinite loop
in C is
for(;;)
It’s also worth noting that a for loop can be used in more general ways than the simple, iterative
examples we’ve seen so far. The “control variable” of a for loop does not have to be an integer,
and it does not have to be incremented by an additive increment. It could be “incremented” by a
multiplicative factor (1, 2, 4, 8, …) if that was what you needed, or it could be a floating-point
variable, or it could be another type of variable which we haven’t met yet which would step,
not over numeric values, but over the elements of an array or other data structure. Strictly
speaking, a for loop doesn’t have to have a “control variable” at all; the three expressions can
be anything, although the loop will make the most sense if they are related and together form
the expected initialize, test, increment sequence.
int x;
printf(”%d\n”, x);
There is no earth-shaking or fundamental difference between the while and for loops. In fact,
given the general for loop
statement
you could usually rewrite it as a while loop, moving the initialize and increment expressions to
statements before and within the loop:
expr1;
while(expr2)
statement
expr3;
statement
for(; expr; )
statement
Another contrast between the for and while loops is that although the test expression (expr2) is
optional in a for loop, it is required in a while loop. If you leave out the controlling expression
of a while loop, the compiler will complain about a syntax error. (To write a deliberately
infinite while loop, you have to supply an expression which is always nonzero. The most
obvious one would simply be while(1) .)
If it’s possible to rewrite a for loop as a while loop and vice versa, why do they both exist?
Which one should you choose? In general, when you choose a for loop, its three expressions
should all manipulate the same variable or data structure, using the initialize, test, increment
pattern. If they don’t manipulate the same variable or don’t follow that pattern, wedging them
into a for loop buys nothing and a while loop would probably be clearer. (The reason that one
loop or the other can be clearer is simply that, when you see a for loop, you expect to see an
idiomatic initialize/test/increment of a single variable, and if the for loop you’re looking at
doesn’t end up matching that pattern, you’ve been momentarily misled.)
void main()
int M,N;
clrscr();
scanf(”%d”,&N);
if(N<=0)
F=1;
else
for(M=1;M<=N;M++)
F*=M;
getch();
2. Write a program that allows the user to enter a set of integers and
print their sum and products using break and continue statements.
Integers are whole numbers with a range of values supported by a particular machine.
Generally, integers occupy one word of storage, and since the word sizes of machines vary
(typically, 16 or 32 bits) the size of an integer that can be stored depends on the computer. If
we use 16 bit word length, the size of the integer value is limited to the range -32768 to +32767
(that is, -215 to +2 15 -1 ). A signed integer uses one bit for sign and 15 bits for the magnitude
of the number. Similarly, a 32 bit word length can store an integer ranging from -2,147,483,648
to 2,147,483,647.
In order to provide some control over the range of numbers and storage space, C has three
classes of integer storage, namely short int, int , and long int, in both signed and unsigned
forms. For example, short int represents fairly small integer values and requires half the amount
of storage as a regular int number uses. A signed integer uses one bit for sign and 15 bits for the
magnitude of the number, therefore, for a 16 bit machine, the range of unsigned integer
numbers will be from 0 to 65,535.
We declare long and unsigned integers to increase the range of values. The use of qualifier
signed on integers is optional because the default declaration assumes a signed number. The
Table 2.2 shows all the allowed combinations of basic types and qualifiers and their size and
range on a 16-bit machine.
Table 2.2
Informally, a variable (also called an object) is a place where you can store a value so that you
can refer to it unambiguously. A variable needs a name. You can think of the variables in your
program as a set of boxes, each with a label giving its name; you might imagine that storing a
value “in” a variable consists of writing the value on a slip of paper and placing it in the box.
A declaration tells the compiler the name and type of a variable you’ll be using in your
program. In its simplest form, a declaration consists of the type, the name of the variable, and a
terminating semicolon:
int i;
The above statement declares an integer variable i.
We can also declare several variables of the same type in one declaration, separating them with
commas as shown above.
The placement of declarations is significant. You can’t place them just anywhere (i.e. they
cannot be interspersed with the other statements in your program). They must either be placed
at the beginning of a function, or at the beginning of a brace-enclosed block of statements, or
outside of any function. Furthermore, the placement of a declaration, as well as its storage
class, controls several things about its visibility and lifetime, as we’ll see later.
You may wonder why variables must be declared before use. There are two reasons:
1. It makes things somewhat easier on the compiler; it knows right away what kind of
storage to allocate and what code to emit to store and manipulate each variable; it
doesn’t have to try to intuit the programmer’s intentions.
2. It forces a bit of useful discipline on the programmer: you cannot introduce variables
wherever you wish ; you must think about them enough to pick appropriate types for
them. (The compiler’s error messages to you, telling you that you apparently forgot to
declare a variable, are as often helpful as they are a nuisance: they’re helpful when they
tell you that you misspelled a variable, or forgot to think about exactly how you were
going to use it.)
Most of the time, it is recommended to write one declaration per line. For the most part, the
compiler doesn’t care what order declarations are in. You can order the declarations
alphabetically, or in the order that they’re used, or to put related declarations next to each other.
Collecting all variables of the same type together on one line essentially orders declarations by
type, which isn’t a very useful order (it’s only slightly more useful than random order).
A declaration for a variable can also contain an initial value. This initializer consists of an equal
sign and an expression, which is usually a single constant:
int i = 1;
#include <stdio.h>
02.#define SIZE 10
03.void main(){
04.
05. // demonstration of using break statement
06.
07. int items[SIZE] = {1,3,2,4,5,6,9,7,10,0};
08.
09. int number_found = 4,i;
10.
11. for(i = 0; i < SIZE;i++){
12.
13. if(items[i] == number_found){
14.
15. printf("number found at position %d\n",i);
16.
17. break;// break the loop
18.
19. }
20. printf("finding at position %d\n",i);
21. }
22.
23. // demonstration of using continue statement
24. for(i = 0; i < SIZE;i++){
25.
26. if(items[i] != number_found){
27.
28. printf("finding at position %d\n",i);
29.
30. continue;// break current iteration
31. }
32.
33. // print number found and break the loop
34.
35. printf("number found at position %d\n",i);
36.
37. break;
38. }
39.
40.}
Here is the output
finding at position 0
finding at position 1
finding at position 2
number found at position 3
finding at position 0
finding at position 1
finding at position 2
number found at position 3
Recursion is a process by which a function calls itself repeatedly, until some specified
condition has been met. The process is used for repetitive computations in which each action is
stated in terms of a previous result. Many repetitive problems can be written in this form.
In order to solve a problem recursively, two conditions must be satisfied. First, the problem
must be written in a recursive form, and the second, the problem statement must include a
stopping condition.
This can also be written as n!=n x (n-1)!. This is the recursive statement of the problem in
which the desired action(the calculation of n!) is expressed in terms of a previous result (the
value of (n-1)! which is assumed to be known). Also, we know that 0!=1 by definition. This
expression provides stopping condition for the recursion.
Thus the recursive definition for finding factorial of positive integer n can be written as:
fact(n)={ 1 if n=0
n x fact(n-1) otherwise}
Program to find factorial of a given positive integer
#include<stdio.h>
main()
int n;
scanf(”%d”, &n);
printf(”n!=%ld\n”, fact(n));
if(n==0)
return(1);
else
return (n*fact(n-1));
Example 8.4: The Towers of Hanoi. The Towers of Hanoi is a game played with three poles
and a number of different sized disks. Each disk has a hole in the center, allowing it to be
stacked around any of the poles. Initially, the disks are stacked on the leftmost pole in the order
of decreasing size, i.e, the largest on the bottom, and the smallest on the top as illustrated in
Figure 8.1.
The general strategy is to consider one of the poles to be the origin, and another to be the
destination. The third pole will be used for intermediate storage, thus allowing the disks to be
moved without placing a larger disk over a smaller one. Assume there are n disks, numbered
from smallest to largest as in Figure 8.1. If the disks are initially stacked on the left pole, the
problem of moving all n disks to the right pole can be stated in the following recursive manner:
1. Move the top n-1 disks from the left pole to the center pole.
2. Move the nth disk( the largest disk) to the right pole.
3. Move the n-1 disks on the center pole to the right pole.
The problem can be solved for any value of n greater than 0(n=0 represents a stopping
condition).
In order to program this game, we first label the poles, so that the left pole is represented as L,
the center pole as C and the right pole as R. Let us refer the individual poles with the char-type
variables from, to and temp for the origin, destination and temporary storage respectively.
4. Write a program in C to perform arithmetic functions using a menu
driven interface like 1. ADDITION, 2. SUBTRACTION, …, 5. EXIT
based on the user input.
The basic operators for performing arithmetic are the same in many computer languages:
+ addition
- subtraction
* multiplication
/ division
% modulus (remainder)
The – operator can be used in two ways: to subtract two numbers (as in
a – b), or to negate one number (as in -a + b or a + -b).
When applied to integers, the division operator / discards any remainder, so 1 / 2 is 0 and 7 / 4
is 1. But when either operand is a floating-point quantity (a real number), the division operator
yields a floating-point result, with a potentially nonzero fractional part. So 1 / 2.0 is 0.5, and 7.0
/ 4.0 is 1.75.
The modulus operator % gives you the remainder when two integers are divided: 1 % 2 is 1; 7
% 4 is 3. (The modulus operator can only be applied to integers.)
Multiplication, division, and modulus all have higher precedence than addition and subtraction.
The term “precedence” refers to how “tightly” operators bind to their operands (that is, to the
things they operate on). In mathematics, multiplication has higher precedence than addition, so
1 + 2 * 3 is 7, not 9. In other words, 1 + 2 * 3 is equivalent to 1 + (2 * 3). C is the same way.
All of these operators “group” from left to right, which means that when two or more of them
have the same precedence and participate next to each other in an expression, the evaluation
conceptually proceeds from left to right. For example, 1 – 2 – 3 is equivalent to (1 – 2) – 3 and
gives -4, not +2. (”Grouping” is sometimes called associativity, although the term is used
somewhat differently in programming than it is in mathematics. Not all C operators group from
left to right; a few groups from right to left.)
Whenever the default precedence or associativity doesn’t give you the grouping you want, you
can always use explicit parentheses. For example, if you want to add 1 to 2 and then multiply
the result by 3, you could write
(1 + 2) * 3.
Program that shows the use of integer arithmetic to convert a given number of days into
months and days.
main()
printf(”Enter days\n”);
scanf(”%d”,&days);
months=days/30;
days=days%30;
}
5. Describe the following concepts with the help of suitable code snippets:
a. Global Variables
A variable declared outside of any function is a global variable, and it is potentially visible
anywhere within the program. You use global variables when you do want to use the variable
in any part of the program. When you declare a global variable, you will usually give it a
longer, more descriptive name (not something generic like i) so that whenever you use it you
will remember that it’s the same variable everywhere. The values stored in global variables
persist, for as long as the program does. (Of course, the values can in general still be
overwritten, so they don’t necessarily persist forever.)
#include<stdio.h>
main()
float cal_avg(void);
printf(”Enter the text below:\n”);
while((n=linecount())>0) {
sum+=n;
++lines;
avg=cal_avg();
void linecount(void)
char line[80];
int count=0;
while((line[count]=getchar())!=’\n’)
++count;
return count;
float cal_avg(void)
In the above program the variables sum and lines are globally declared and hence they could be
used in both the functions main() and cal_avg()
b. Static Variables
Static variables are defined within individual functions and therefore have the same scope as
automatic variables, i.e. they are local to the functions in which they are declared. Unlike
automatic variables, however, static variables retain their values throughout the life of the
program. As a result, if a function is exited and then reentered later, the static variables defined
within that function will retain their previous values. This feature allows functions to retain
information permanently throughout the execution of a program. Static variables can be utilized
within the function in the same manner as other variables. They cannot be accessed outside of
their defining function.
In order to declare a static variable the keyword static is used as shown below:
You can define automatic or static variables having the same name as global variables. In such
situations the local variables will take precedence over the global variables, though the values
of global variables will be unaffected by any manipulation of the local variables.
Initial values can be included in static variable declaration. The rules associated with the
initialization remain same as the initialization of automatic or global variables. They are:
2. The initial values are assigned to their respective variables at the beginning of the program
execution. The variables retain these values throughout the life of the program, unless different
values are assigned during the course of computation.
3. Zeros will be assigned to all static variables whose declarations do not include explicit initial
values.
#include<stdio.h>
main()
int count, n;
scanf(”%d\n”, &n);
for(count=1;count<=n;count++)
long int f;
if (count==1)
f=0;
else if (count==2)
f=1;
else
f=f1+f2;
f2=f1;
f1=f; /* f1 and f2 retain their values between different calls of the function*/
return f;
c. External Variables
It is possible to split a function up into several source files, for easier maintenance. When
several source files are combined into one program the compiler must have a way of correlating
the variables which might be used to communicate between the several source files.
Furthermore, if a variable is going to be useful for communication, there must be exactly one of
it: you wouldn’t want one function in one source file to store a value in one variable named
externvar, and then have another function in another source file read from a different variable
named externvar. Therefore, a variable should have exactly one defining instance, in one place
in one source file. If the same variable is to be used anywhere else (i.e. in some other source
file or files), the variable is declared in those other file(s) with an external declaration, which is
not a defining instance. The external declaration says the compiler that the variable will be used
in this source file but defined in some other source file. Thus the compiler doesn’t allocate
space for that variable with this source file.
To make a variable as an external declaration, which is defined somewhere else, you precede it
with the keyword extern:
extern int j;
Type and save the following program in a source file called externvariables.h
int principle=10000;
float rate=5.5;
int time=2;
float interest;
Type and save the following program in a separate source file called demoexternvar.c
#include<stdio.h>
#include “externvariables.h” /* the source file where the external variables are defined should
be included here.*/
main()
{
/* external declarations of the variables which are defined in externvariables.h */
/*compute interest*/
interest= principle*rate*time/100.0;
printf(”Interest=%f\n”, interest);
}
The concept of external storage class can be extended to functions also. A source file can
access a function defined in any other source file provided the source file is included within the
source file where you access that function.
void output(void)
return;
Type and save the following program in a separate source file called demoexternfun.c
#include<stdio.h>
#include ” externfunction.h”
main()
output();
Compile and execute the above program and observe the result.
However, the keyword extern is optional in some C compilers.
How will we specify that we want to access a particular data file? It would theoretically be
possible to mention the name of a file each time it was desired to read from or write to it. But
such an approach would have a number of drawbacks. Instead, the usual approach (and the one
taken in C’s stdio library) is that you mention the name of the file once, at the time you open it.
Thereafter, you use some little token in this case, the file pointer which keeps track (both for
your sake and the library’s) of which file you’re talking about. Whenever you want to read
from or write to one of the files you’re working with, you identify that file by using its file
pointer (that is, the file pointer you obtained when you opened the file). As we’ll see, you store
file pointers in variables just as you store any other data you manipulate, so it is possible to
have several files open, as long as you use distinct variables to store the file pointers.
FILE *fp;
The type FILE is predefined for you by <stdio.h>. It is a data structure which holds the
information the standard I/O library needs to keep track of the file for you. For historical
reasons, you declare a variable which is a pointer to this FILE type. The name of the variable
can (as for any variable) be anything you choose; it is traditional to use the letters fp in the
variable name (since we’re talking about a file pointer). If you were reading from two files at
once you’d probably use two file pointers:
If you were reading from one file and writing to another you might declare an input file pointer
and an output file pointer:
The mode string “r” indicates reading. Mode “w” indicates writing, so we could open
output.dat for output like this:
The other values for the mode string are less frequently used. The third major mode is “a” for
append. (If you use “w” to write to a file which already exists, its old contents will be
discarded.) You may also add “+” character to the mode string to indicate that you want to both
read and write, or a “b” character to indicate that you want to do “binary” (as opposed to text)
I/O.
One thing to beware of when opening files is that it’s an operation which may fail. The
requested file might not exist, or it might be protected against reading or writing. (These
possibilities ought to be obvious, but it’s easy to forget them.) fopen returns a null pointer if it
can’t open the requested file, and it’s important to check for this case before going off and
using fopen’s return value as a file pointer. Every call to fopen will typically be followed with a
test, like this:
If fopen returns a null pointer, and you store it in your file pointer variable and go off and try to
do I/O with it, your program will typically crash.
It’s common to collapse the call to fopen and the assignment in with the test:
You don’t have to write these “collapsed” tests if you’re not comfortable with them, but you’ll
see them in other people’s code, so you should be able to read them.
#include <filename.h>
or
#include “filename.h”
causes the contents of the file filename.h to be read, parsed, and compiled at that point. (After
filename.h is processed, compilation continues on the line following the #include line.) For
example, suppose you got tired of retyping external function prototypes such as
at the top of each source file. You could instead place the prototype in a header file, perhaps
getline.h, and then simply place
#include “getline.h”
at the top of each source file where you called getline. (You might not find it worthwhile to
create an entire header file for a single function, but if you had a package of several related
function, it might be very useful to place all of their declarations in one header file.) As we may
have mentioned, that’s exactly what the Standard header files such as stdio.h are collections of
declarations (including external function prototype declarations) having to do with various sets
of Standard library functions. When you use #include to read in a header file, you automatically
get the prototypes and other declarations it contains, and you should use header files, precisely
so that you will get the prototypes and other declarations they contain.
The difference between the <> and “” forms is where the preprocessor searches for filename.h.
As a general rule, it searches for files enclosed in <> in central, standard directories, and it
searches for files enclosed in “” in the “current directory,” or the directory containing the
source file that’s doing the including. Therefore, “” is usually used for header files you’ve
written, and <> is usually used for headers which are provided for you (which someone else has
written).
The extension “.h”, by the way, simply stands for “header,” and reflects the fact that #include
directives usually sit at the top (head) of your source files, and contain global declarations and
definitions which you would otherwise put there. (That extension is not mandatory, you can
theoretically name your own header files anything you wish, but .h is traditional, and
recommended.)
As we’ve already begun to see, the reason for putting something in a header file, and then using
#include to pull that header file into several different source files, is when the something
(whatever it is) must be declared or defined consistently in all of the source files. If, instead of
using a header file, you typed the something in to each of the source files directly, and the
something ever changed, you’d have to edit all those source files, and if you missed one, your
program could fail in subtle (or serious) ways due to the mismatched declarations (i.e. due to
the incompatibility between the new declaration in one source file and the old one in a source
file you forgot to change). Placing common declarations and definitions into header files means
that if they ever change, they only have to be changed in one place, which is a much more
workable system.
• External declarations of global variables and functions. We said that a global variable
must have exactly one defining instance, but that it can have external declarations in
many places. We said that it was a grave error to issue an external declaration in one
place saying that a variable or function has one type, when the defining instance in
some other place actually defines it with another type. (If the two places are two source
files, separately compiled, the compiler will probably not even catch the discrepancy.)
If you put the external declarations in a header file, however, and include the header
wherever it’s needed, the declarations are virtually guaranteed to be consistent. It’s a
good idea to include the header in the source file where the defining instance appears,
too, so that the compiler can check that the declaration and definition match. (That is, if
you ever change the type, you do still have to change it in two places: in the source file
where the defining instance occurs, and in the header file where the external declaration
appears. But at least you don’t have to change it in an arbitrary number of places, and, if
you’ve set things up correctly, the compiler can catch any remaining mistakes.)
• Preprocessor macro definitions (which we’ll meet in the next section).
• Structure definitions
• Typedef declarations
• Defining instances of global variables. If you put these in a header file, and include the
header file in more than one source file, the variable will end up multi defined.
• Function bodies (which are also defining instances). You don’t want to put these in
headers for the same reason–it’s likely that you’ll end up with multiple copies of the
function and hence “multiply defined” errors. People sometimes put commonly-used
functions in header files and then use #include to bring them (once) into each program
where they use that function, or use #include to bring together the several source files
making up a program, but both of these are poor ideas. It’s much better to learn how to
use your compiler or linker to combine together separately-compiled object files.
Since header files typically contain only external declarations, and should not contain function
bodies, you have to understand just what does and doesn’t happen when you #include a header
file. The header file may provide the declarations for some functions, so that the compiler can
generate correct code when you call them (and so that it can make sure that you’re calling them
correctly), but the header file does not give the compiler the functions themselves. The actual
functions will be combined into your program at the end of compilation, by the part of the
compiler called the linker. The linker may have to get the functions out of libraries, or you may
have to tell the compiler/linker where to find them. In particular, if you are trying to use a third-
party library containing some useful functions, the library will often come with a header file
describing those functions. Using the library is therefore a two-step process: you must #include
the header in the files where you call the library functions, and you must tell the linker to read
in the functions from the library itself.
Macro definition and Substitution
defines a macro with the given name, having as its value the given replacement text. After that
(for the rest of the current source file), wherever the preprocessor sees that name, it will replace
it with the replacement text. The name follows the same rules as ordinary identifiers (it can
contain only letters, digits, and underscores, and may not begin with a digit). Since macros
behave quite differently from normal variables (or functions), it is customary to give them
names which are all capital letters (or at least which begin with a capital letter). The
replacement text can be absolutely anything–it’s not restricted to numbers, or simple strings, or
anything.
The most common use for macros is to propagate various constants around and to make them
more self-documenting. We’ve been saying things like
char line[100];
getline(line, 100);
but this is neither readable nor reliable; it’s not necessarily obvious what all those 100’s
scattered around the program are, and if we ever decide that 100 is too small for the size of the
array to hold lines, we’ll have to remember to change the number in two (or more) places. A
much better solution is to use a macro:
char line[MAXLINE];
getline(line, MAXLINE);
Now, if we ever want to change the size, we only have to do it in one place, and it’s more
obvious what the words MAXLINE sprinkled through the program mean than the magic
numbers 100 did.
Since the replacement text of a preprocessor macro can be anything, it can also be an
expression, although you have to realize that, as always, the text is substituted (and perhaps
evaluated) later. No evaluation is performed when the macro is defined. For example, suppose
that you write something like
#define A 2
#define B 3
#define C A + B
(this is a pretty meaningless example, but the situation does come up in practice). Then, later,
suppose that you write
int x = C * 2;
If A, B, and C were ordinary variables, you’d expect x to end up with the value 10. But let’s see
what happens.
The preprocessor always substitutes text for macros exactly as you have written it. So it first
substitutes the replacement text for the macro C, resulting in
int x = A + B * 2;
int x = 2 + 3 * 2;
Only when the preprocessor is done doing all this substituting does the compiler get into the
act. But when it evaluates that expression (using the normal precedence of multiplication over
addition), it ends up initializing x with the value 8!
To guard against this sort of problem, it is always a good idea to include explicit parentheses in
the definitions of macros which contain expressions. If we were to define the macro C as
#define C (A + B)
then the declaration of x would ultimately expand to
int x = (2 + 3) * 2;
Notice that there does not have to be (and in fact there usually is not) a semicolon at the end of
a #define line. (This is just one of the ways that the syntax of the preprocessor is different from
the rest of C.) If you accidentally type
char line[MAXLINE];
which is a syntax error. This is what we mean when we say that the preprocessor doesn’t know
much of anything about the syntax of C–in this last example, the value or replacement text for
the macro MAXLINE was the 4 characters 1 0 0 ; , and that’s exactly what the preprocessor
substituted (even though it didn’t make any sense).
Simple macros like MAXLINE act sort of like little variables, whose values are constant (or
constant expressions). It’s also possible to have macros which look like little functions (that is,
you invoke them with what looks like function call syntax, and they expand to replacement text
which is a function of the actual arguments they are invoked with) but we won’t be looking at
these yet.
The preprocessor permits us to define more complex and more useful form of replacements. It
takes the form:
There is a basic difference between the simple replacement discussed above and the
replacement of macros with arguments. Subsequent occurrence of a macro with arguments is
known as a macro call. When a macro is called, the preprocessor substitutes the string,
replacing the formal parameters with actual parameters.
volume=CUBE(side);
volume=(side*side*side);
volume=(a+b*a+b*a+b);
which would obviously not produce the correct results. This is because the preprocessor
performs a blind text substitution of the argument a+b in place of x. This shortcoming can be
corrected by using parentheses for each occurrence of a formal argument in the string.
Example:
volume=((a+b)*(a+b)*(a+b));
Some commonly used definitions are:
Nesting of Macros
We can also use one macro in the definition of another macro. That is, macro definitions may
be nested. For instance, consider the following macro definitions:
#define M 5
#define N M+1
Conditional Compilation
The last preprocessor directive we’re going to look at is #ifdef. If you have the sequence
#ifdef name
program text
#else
#endif
in your program, the code that gets compiled depends on whether a preprocessor macro by that
name is defined or not. If it is (that is, if there has been a #define line for a macro called name),
then “program text” is compiled and “more program text” is ignored. If the macro is not
defined, “more program text” is compiled and “program text” is ignored. This looks a lot like
an if statement, but it behaves completely differently: an if statement controls which statements
of your program are executed at run time, but #ifdef controls which parts of your program
actually get compiled.
Just as for the if statement, the #else in an #ifdef is optional. There is a companion directive
#ifndef, which compiles code if the macro is not defined (although the “#else clause” of an
#ifndef directive will then be compiled if the macro is defined). There is also an #if directive
which compiles code depending on whether a compile-time expression is true or false. (The
expressions which are allowed in an #if directive are somewhat restricted, however, so we
won’t talk much about #if here.)
• You are trying to write a portable program, but the way you do something is different
depending on what compiler, operating system, or computer you’re using. You place
different versions of your code, one for each situation, between suitable #ifdef
directives, and when you compile the program in a particular environment, you arrange
to have the macro names defined which select the variants you need in that
environment. (For this reason, compilers usually have ways of letting you define macros
from the invocation command line or in a configuration file, and many also predefine
certain macro names related to the operating system, processor, or compiler in use. That
way, you don’t have to change the code to change the #define lines each time you
compile it in a different environment.)
For example, in ANSI C, the function to delete a file is remove. On older Unix systems,
however, the function was called unlink. So if filename is a variable containing the name of a
file you want to delete, and if you want to be able to compile the program under these older
Unix systems, you might write
#ifdef unix
unlink(filename);
#else
remove(filename);
#endif
#define unix
at the top of the file when compiling under an old Unix system. (Since all you’re using the
macro unix for is to control the #ifdef, you don’t need to give it any replacement text at all.
Any definition for a macro, even if the replacement text is empty, causes an #ifdef to succeed.)
(In fact, in this example, you wouldn’t even need to define the macro unix at all, because C
compilers on old Unix systems tend to predefine it for you, precisely so you can make tests like
these.)
• You want to compile several different versions of your program, with different features
present in the different versions. You bracket the code for each feature with #ifdef
directives, and (as for the previous case) arrange to have the right macros defined or not
to build the version you want to build at any given time. This way, you can build the
several different versions from the same source code. (One common example is whether
you turn debugging statements on or off. You can bracket each debugging printout with
#ifdef DEBUG and #endif, and then turn on debugging only when you need it.)
#ifdef DEBUG
#endif
to print out the value of the variable x at some point in your program to see if it’s what you
expect. To enable debugging printouts, you insert the line
#define DEBUG
at the top of the file, and to turn them off, you delete that line, but the debugging printouts
quietly remain in your code, temporarily deactivated, but ready to reactivate if you find
yourself needing them again later. (Also, instead of inserting and deleting the #define line, you
might use a compiler flag such as -DDEBUG to define the macro DEBUG from the compiler
invocating line.)
Conditional compilation can be very handy, but it can also get out of hand. When large
chunks of the program are completely different depending on, say, what operating system the
program is being compiled for, it’s often better to place the different versions in separate source
files, and then only use one of the files (corresponding to one of the versions) to build the
program on any given system. Also, if you are using an ANSI Standard compiler and you are
writing ANSI-compatible code, you usually won’t need so much conditional compilation,
because the Standard specifies exactly how the compiler must do certain things, and exactly
which library functions it much provide, so you don’t have to work so hard to accommodate the
old variations among compilers and libraries.
The problem with the previous implementation is that the insert function gives a queue-full
signal even if a considerable portion is free. This happens because the queue has a tendency to
move to the right unless the ‘front’ catches up with the ‘rear’ and both are reset to 0 again (in
the delete procedure). To overcome this problem, the elements of the array are required to shift
one position left whenever a deletion is made. But this will make the deletion process
inefficient. Therefore, an efficient way of overcoming this problem is to consider the array to
be circular, as shown in Figure. Initially both front and rear are intitialized to 0.
Program
#include <stdio.h>
#include <stdlib.h>
if(*rear == front)
exit(0);
}
queue[*rear] = value;
if(*front == rear)
exit(0);
*value = queue[*front];
void main()
int queue[MAX];
int front,rear;
int n,value;
front=0; rear=0;
do
do
scanf(”%d”,&value);
insert(queue,&rear,front,value);
printf(”Enter 1 to continue\n”);
scanf(”%d”,&n);
} while(n == 1);
scanf(”%d”,&n);
while( n == 1)
delete(queue,&front,rear,&value);
scanf(”%d”,&n);
}
printf(”Enter 1 to continue\n”);
scanf(”%d”,&n);
} while(n == 1);