Programming in C
Programming in C
Programming in C
Introduction:
Dennis Ritchie developed the C language at Bell Laboratories in the early 1970s. C is
a general-purpose, structured programming language. Its instructions consist of terms
that resemble algebraic expressions augmented by certain English keywords. C also
contains certain additional features, however, that allow it to be used at a lower level,
thus bridging the gap between machine language and more conventional high-level
languages. This flexibility allows C to be used for system programming as well as for
applications programming.
Features of C:
C is a structured programming language.
It is a middle level language.
It is rich in operators and data types.
It optimizes the usage of Memory.
C is simple, contained, versatile and more expressive.
C programs are fast and efficient.
C permits all data conversion and mixed mode operation.
C is proved to be excellent and efficient for a variety of programming applications such
as scientific and commercial quality software developments etc.,
The character set in C:
Alphabet:
A to Z
a to z
Digits:
0 to 9
Special characters:
+-*/=%&#!?^~\|<>()[]{}:;,._
Identifiers:
Identifiers are names that are given to various program elements. Identifiers consist of letters
and digits in any order, except the first character should be a letter.
Keywords:
There are certain reserved words, called keywords that have standard, pre-defined meaning in C.
These keywords can be used only for their intended purpose, they cannot be used as
programmer-defined identifiers. E.g., auto, break, case, char, do, else, if, for..
Variable:
A Variable is an identifier that is used to represent some specified type of information within a
designated portion of a program.
Constants:
A constant refers to fixed value that doesnt change during the execution of program.
There are different types of constants
Integer constants (Constant value without fractional part). e.g. 87 90 3.
Floating points (Constant value with fractional part)
Character constants (Single character enclosed in apostrophes). e.g., v c.
String constants (Constants of any number of consecutive characters enclosed in double
quotation marks). E.g., Computec Bangalore
Data types:
C supports several different types of data, each of which may be represented differently within
the computers memory. The memory requirements for each data type will determine the
permissible range of values for that data type.
Data type
Description
Memory
Representation
Requirements
char
int
float
double
single character
integer quality
floating point
double precision
floating point number
1 byte
2 bytes
4 bytes
c
d
f
8 bytes
C Operators:
An operator is a symbol used to manipulate the data. C has a very rich set of built-in Operators.
Arithmetic Operators:
Arithmetic Operators may be classified as:
Binary arithmetic operators.
Unary arithmetic operators.
Binary arithmetic operators.
Operator
Operation
+
Addition
Subtraction
*
Multiplication
/
Division
%
Modulo
Unary arithmetic operators.
Operator
Operation
+
unary plus
unary minus
++
increment
-decrement
Relational Operators:
Operator
Operation
<
Lesser than
<=
Lesser than or equal to
>
Greater than
>=
Greater than or equal to
==
Equal to
!=
Not equal to
Relational operators are used to compare two quantities containing relational operator is called a
relational expression.
The value of a relational expression is one (true) or zero (false).
e.g.,
2>4 is false
4<5 is true
The relational expression is of the form:
.
->
*
&
Structure member
Pointer to structure member
Pointer variable (indirection operator)
To get the address of the data item stored
in the memory.
To allot memory for the variable.
Comma operator.
Sizeof
,
Initialisation:
Assigning a value to a variable for the first time in a program is known as initialisation. The
value used for the assignment is known as initializer.
e.g.,
int a=5,b=a+5;
int c=a*b;
Escape Sequences:
Escape sequence is a character representation that may appear in a character constant or in a
string constant. The character set does not contain the control characters such as backspace,
tab, enter, etc., to represent such characters, escape sequences are used.
Escape Sequence
Character
\a
bell (alert)
\b
backspace
\f
form feed
\n
new line
\t
horizontal tab
\v
vertical tab
\
double quote
\?
Question mark
\0
null character
\r
carriage return
Comments:
A program comment is written to explain briefly about what a program does. The improve the
readability of a program comments may appear anywhere in a program. /* comments */
Statement Termination (Delimiter):
C is a free format language. Single statement and multiple statements can be on a single line or
they may spread over several lines. Each statement must be terminated by a semicolon.
e.g.,
int a=5,b=35;
x=a+b;
Structure of a C Program:
A C program will have the following structure:
Documentation
File Inclusions
Constant definitions
External Variables (Global) declarations
Function Protypes
main( )
{
Long double
Double
Float
Unsigned int
Long int
Int
Short int
Char
low
Input / Output Facilites:
Programming languages are provided with certain facilities for I/O operations and most of them
have inherent I/O facilities for data transfer. But C does not have I/O facility. Input/Output are
carried out by functions, which are part of C library functions. Standard I/O library functions are
available in a filename stdio.h (standard input output header file). The following line must be
included in all programs as follows:
# include <stdio.h>
Character oriented I/O functions:
These functions are used to read or write one character at a time. Getchar( ) and putchar( ) falls
under this category.
getchar( )
The function getchar( ) is used to read a single character from the keyboard.
The format is as follows:
5
variable=getchar( );
putchar( )
The function putchar( ) writes its arguments, which is a character on the screen.
The format is
putchar(arg);
e.g.,
int c;
c=getchar( ); /*entered character is assigned to c */
putchar( c ); /*the character entered is displayed*/
The gets and puts functions:
The gets function is used to enter a string into the computer from a standard input device. The
puts function is used to transfer a function from a computer to any standard output device. Each
function accepts a single argument. The argument must be a single data item that represents a
string; the string may include a blank space.
e.g.,
#include<stdio.h>
main( )
{
char name[25];
gets(name);
puts(name);
}
Formatted I/O functions:
The data can be entered into the computer from a standard input device by means the C library
function scanf. This function can be used to enter any combination of numerical values, single
character and strings.
The syntax for scanf statement is as follows:
scanf(control string, arg_1,arg_2,.., arg_n);
The control string specifies the field format in which the data is to be entered, and the arguments
arg_1, arg_2, . Arg_n specify the address of locations where the data is stored. Commas
separate control string and arguments. Field format specifications consisting of the conversion
character % followed by the type specifier. It may contain the field width.
Entering Integer values as input:
The file specifies for reading an integer value is %wd.
The % sign indicates that a conversion specification follows. W is an integer number that
specifies the field width of the number to be read and the d is the type specifier (data type
character) indicating that the number to be read is in integer mode.
Consider the following example:
scanf(%d%d,&a,&b);
Suppose we have the data
50 40
The value 50 is assigned to a and 40 to b.
It is our responsibility that there is a correspondence between the data items listed in the scanf
and the values given in the data line. If they do not correspond with respect to the type of data
and the field size, unpredicted errors may occur.
Nested IF Statement:
When more than one decision is needed, if statements may be nested as follows:
if (logical expression-1)
{
if (logical expression-2)
{
statement block-1;
}
else
{
statement block-2;
}
}
else
{
statement block-3;
}
statement-4;
The interpretation of the above nested structure is as follows:
If logical expression-1 is false, statement block-3 will be executed and control will be transferred
to statement-4.
If logical expression is true, it continues to evaluate logical expression-2.
If logical expression-1 is true, statement block-1 will be executed and control will be transferred
to statement-4.
If logical expression-2 is false, statement block-2 will be executed and control will be transferred
to statement-4.
The ELSE-IF ladder:
10
----case value-k:
statement-k;
break;
default:
statement-L;
break;
}
statement m;
--There are four keywords switch, case, break and default. The structure begins with the keyword
switch. The expression is an integer or character expression. Value-1, value-2 . Are
constants or expressions, but on evaluations they must give integer constants. They are known as
case labels, a colon follows each case label. The constants in the case label need not be
consecutive.
The statements works as follows:
The expression following switch is evaluated, execution control will be transferred to the
statement immediately following the case label when value is equal to the value of the switch
expression. This statement is executed and also the succeeding statements, if any. When the
break statement is encountered, the switch statement is terminated immediately and any
remaining statements in the body are ignored. If the switch is nested in another structure (a loop
or another switch), the outer structure is not altered; only the one immediately containing the
break is terminated.
Default is a special label and the inclusion of this portion is optional. It is a label, which allows
for the possibility that the value of the switch expression does not match any of the case labels.
If none of the case labels match, control will be transferred to the default label and the statement
followed by default will be executed. If the default label is not present and if there is no match
of the case labels, the entire switch statement will be skipped. The default can be placed any
where within the body of the switch statement; it need not be the last label.
For any given label, any number of statements may be included. If more than one statement
follows a label, it is not necessary to group them together within braces.
The action of a switch statement can be explained by the following flowchart:
/* A program to calculate the sum of the first n natural numbers, using while statement */
#include<stdio.h>
#include<conio.h>
void main( )
{
int i,n;
long sum=0;
clrscr();
printf(\nEnter the value of n : );
scanf(%d,&n);
i = 1;
While (i<=n)
{
sum+=i;
i++;
}
printf(\nThe sum is %ld,sum);
getch( );
12
}
The DO.. WHILE statement:
The do .. while statement is of the form:
do
{
statement;
}
while (logical expression);
The working of a do .. while structure is shown in the following flowchart.
The do while statement is some what similar to while statement, the only difference is that the
logical expression is at the bottom of the loop. Hence, the statements in a do .. while structure
will be executed at least once. The statements will be repeated as long as the logical expression
is false, control will be transferred to the statements following the do .. while.
/* Program to calculate the value of 22 + 42 + 62 + using do while statement */
#include<stdio.h>
#include<conio.h>
void main( )
{
int i =2;
long sum = 0;
do
{
sum+=i * i; i +=2;
}
while (i<=30);
printf(\nThe sum is %ld,sum);
}
Using while and do .. while structures, it is possible to execute a sequence of statement
repeatedly. Hence they are called looping structures. This repetition is conditional because
execution is repeated only when some condition is satisfied. In the while structure, the condition
is tested in the beginning, where as in the do .. while, the condition is tested towards the end. On
entry, if the condition is not satisfied, the statement in the while structure will not be executed at
13
all. In the do while, the statement will be executed at least once because after executing it, the
condition is tested.
In both the structures, there must be some provision in the body of the loop, which will cause the
logical expression to be false after some repetition of the loop, otherwise it will be an indefinite
loop.
The FOR loop:
The general form of the for loop is:
For (expression-1; expression-2; expression-3)
Statement-1
Expression-1 is called an initialization expression. It will be an assignment statement to
initialize the index of the loop. Expression-2 will be a logical expression, which must be
satisfied in order to continue execution of the loop. Only if it is true, the loop will be executed.
If it is false, the execution of the loop will be terminated and Program execution will continue
from the statement following the FOR structure. Expression-3 is called a modifier statement,
which will change the value of the index so that expression-2 will become false after some
iteration. Expression-3 will be executed at the end of each iteration, after the body of the loop is
executed. The statement may be simple or compound. It is the body of the loop, which is
repeatedly executed as long as expression-2 is true.
The action of the for structure is shown in the following flowchart.
14
int i;
clrscr ( );
for (i=1;i<=10;i++)
printf (%d\n,i);
getch ( );
}
Nested Loops:
Whenever a loop construct appears within another loop construct we say that it is a nested loop
structure. The loops should not overlap with each other. The variable names used in one loop
construct must be different from another construct. The syntax is:
for (expression-1; expression-2; expression-3)
{
statement-1;
for (expression-4; expression-5; expression-6)
{
statement-2;
}
}
Note: More than two constructs may be nested in the same way. A while loop and a do loop
may also be nested. A for loop may be nested in a while loop or a while loop may be nested in a
for loop and so on.
e.g.,
/* Program to print the number 1 one time, the number 2 two times and so on */
#include<stdio.h>
#include<conio.h>
void main ( )
{
int I,j;
for (I=1; I<=10; I++)
{
for (j=1; j<=I; j++)
{
printf (%d\t,I);
}
printf(\n);
}
getch( );
}
The COMMA Operator:
This is one of special features of C. Using this operator in the for loop, it is possible to have
more than one index in the for loop.
e.g.,
for (I=0, j=n; I<=k; I++, j+=2)
{
-----
15
----}
Hence the initialization expression consists of two variables I and j and they are given the initial
values as I = 0 and j = n. To indicate this, a comma is placed. Up to the first semicolon,
initialization is assumed. Similarly, whatever is written after the test condition, they will be
taken as modifiers. Here there are two modifiers: I++ and j+=2. Note that they are separated by
comma.
/* Program to illustrate Comma operator */
/* Sum of odd numbers */
#include<stdio.h>
#include<conio.h>
void main( )
{
int I, j, n, sum=0; clrscr ( );
printf(Enter the number of odd numbers to added \n);
scanf (%d, &n);
for (I=1, j=1; j<=n; I+=2, I++)
sum+=I;
printf(\ Required sum = %d, sum);
getch ( );
}
Jumps in Loop:
Loops perform a set of operations until a condition is satisfied. While executing a loop,
sometimes it may be necessary to stop a part of the loop or to leave the loop as soon as certain
condition occurs. C permits a jump from one statement to another within a loop as well as jump
out of a loop.
The Break Statement:
The break statement is a jump statement and it can be used inside any of the following
constructs.
Switch statement
For loop
While loop
Do..while loop.
We have already seen that execution of a break statement from within a switch block causes
immediate exit from the switch block and program control is transferred to the statement
following the switch block. In the loop constructs also, execution of the break statement
terminates the loop and further execution of the program is resumed with statement following the
loop.
/* use of break in a for loop */
#include<stdio.h>
#include<conio.h>
void main ( )
{
int m; float x, sum = 0, average = 0; clrscr ( );
printf (Enter the values one by one \n);
printf(Enter the negative numbers to terminate \n);
16
17
18
19
1
2
3
4
5
6
7
8
9
10
11
12
Here is a variation of two-dimensional array definition presented in the last example.
int a [3][4] = {
{1,2,3,4},
{5,6,7,8},
{9,10,11,12}
};
/* A sample program for 2-d array */
#include<stdio.h>
#include<conio.h>
void main( )
{
int a [3][3], I, j;
clrscr ( );
printf (\n Enter the elements of matrix of order 3X3 \n);
for (I=0; I<3; I++)
for (j=0; j<3; j++)
scanf (%d, &a [I][j]);
printf (\n The entered elements of a matrix \n);
for (I=0; I<3; I++)
{
for (j=0; j<3; j++)
{
printf (%d\t, a[I][j]);
}
printf (\n;
}
getch ( );
}
String Handling:
A string is an array of characters. It is declared as follows:
char name [size];
The size specifies the number of characters in the string. When the compiler assigns a character
string to a character array, it automatically supplies a null character (\0) at the end of the string.
We must include one extra space in the array to store the null character. Consider the declaration:
char name [20];
Name is declared as a character array that can hold a maximum of twenty characters. But the
last space is always reserved for the null character. Hence the string may contain a maximum of
19 characters. The length of the string is the number of non-null characters in the string. It is
one less than the size specified in the declaration. The allocation will be as follows:
a
20
For reading a string of characters, the scanf function may be used with %s format specification.
E.g.,
char city [25];
scanf (%s, city);
Note that in the scanf function, the ampersand (&) is not required before the variable name. And
also previously, it was mentioned that input /output on arrays as a whole is not permitted, but a
character array is an exception to this. In the example considered, city was declared as an array
of characters and
scanf (%s, city);
Will read the array as if it is an ordinary variable.
For printing a string the printf function may be used with the format specification %s.
The statement
printf (%s, city);
However, it is not permissible to have operators directly on strings. E.g., the statement
city = BANGALORE;
Is not valid.
Similarly, if string1 and string2 are declared as character arrays, the assignment
string1 = string2;
Is not valid.
The scanf function has a problem with strings. The input will be terminated by a blank space (or
tab, carriage return, form feed, new line). Hence it is suitable only if the string has only one
world.
Consider the statement
scanf (%s, city);
Suppose we type
CYBER CITY
Then, only the string CYBER will be read into the array city because the blank space following
CYBER will terminate the string. There are two alternatives for this problem. Using the getchar
( ) function, input may be given character by character.
Consider the example:
char institute [30];
Int I;
In order to supply input to the string name (i.e., for the character array) we may write
For (I=0; I<30; I++)
Institute [I] = getchar ( );
When the data is typed, successive characters including blank spaces will be read into the
elements of the array. The reading terminates when I = 30. Thus, the assignment is for the
subscripts 0 to 28 (only 29 characters) and the last character is the null character.
Alternative, we may write
for (I=0; I<30; I++)
scanf (%c, &institute [I]);
Printing of strings will be possible in the same way. The other library functions available for
reading a string and displaying a string are gets and puts.
Functions for Handling Strings:
A number of functions are available in the C library for handling strings. Here we consider some
of them.
21
strcpy ( ):
The strcpy function works like an assignment statement. It is of the form:
strcpy (string1, string2);
It will assign the contents of string2 to string1.
Suppose we have string2 as COMPUTEC. The above statement will cause the assignment of
COMPUTEC to string1.
strlen ( ):
This function is used to find the number of characters in a string. It is of the form: strlen (str);
Where str refers to the string.
Consider the statement:
n = strlen (city);
Where city is the name of a string. Then, the number of characters in the city is assigned to n,
where n is the integer variable.
strcat ( ):
This function is used to join two strings together nothing but concatenating the strings. It is of
the form:
strcat (string1, string2);
On encountering the above statement string2 will be appended to string1. String2 will remain
the same.
Suppose str1 and str2 are two strings and st1 = COMPUTEC and st2 = ASSOCIATES.
Execution of the statement
strcat (str1, str2);
Will result in
str1 = COMPUTEC ASSOCIATES
str2 = ASSOCIATES
When we use strcat function, we must make sure that string1 is large enough to hold both the
strings.
strcmp ( ):
Two strings cannot be compared directly. Suppose name1 and name2 are the names of the two
strings, then the statement
if (name1==name2)
Is not valid. In order to compare two strings, they will be tested character by character. The
library function strcmp ( ) is used to compare two strings. It is of the form:
strcmp (string1, string2);
Where string1 and string2 are the names of the strings.
This function will return the value zero if both the strings are equal; otherwise, it will return an
integer, which is the difference between the ASCII equivalents of the first mismatch between the
characters of string1 and string2.
For instance, if we write
strcmp (RAJA, RANI);
The function will return the value, which is the ASCII value of J minus ASCII value of N, since J
and N are the first mismatching characters.
strrev ( ):
This function is used to reverse a string. It is of the form:
strrev (string1);
Where string1 is the name of the string.
22
e.g.,
strcpy (string2, strrev (string1));
suppose if string1 = COMPUTEC.
Then string2 = CETUPMOC.
toupper ( ) and tolower ( ) functions:
These two functions operate on a single character. The function toupper ( ) checks the character
given as its arguments and if it is in lower case, converts it into upper case.
In a similar manner, the function tolower ( ) checks the character given as its arguments and if it
is in uppercase, converts it into lowercase. The syntax is:
toupper ( c );
tolower ( c );
Where c is the character to be converted.
sscanf and sprintf functions:
These two library functions are derived from printf and scanf. They do not perform input or
output.
The function sprintf copies information into a string.
The syntax of sprintf is:
sprintf (s, formatstring, arguments);
Here s is the buffer, i.e., an array of characters. Format string and argument list are similar to
those used with printf. The difference is that the output is given to the string instead of to the
monitor. This function also appends a NULL character at the end of the string.
e.g.,
int x = 25;
char string [10];
sprintf (string, %d, x);
The function will write the two digits 2 and 5 followed by a NULL character in the array string.
The effect is
strcpy(string,25);
The function sscanf performs opposite conversion. It gets information from the string in the
same way scanf( ) gets information from the keyboard. The syntax is:
sscanf (s, format string, list of addresses of variables);
Here s is the string to be disassembled into data items and the data assigned to variables
according to the format specified in the format string.
e.g.,
int x; char ch; float f;
char string[20] = 6t3.24;
sscanf(string, %d%c%f, &x, &ch, &f);
The assignment will be 6 to x, the character t to ch and 3.24 to f.
Functions
Built-in functions are pre-defined and supplied along with the compiler and may be used in any
C program. They are also known as library functions. Already we are using some of I/O
functions getchar ( ), putchar ( ), scanf ( ), printf ( ), gets ( ), puts ( ), clrscr ( ) . And the
mathematical functions sqrt( ), sin ( ), cos ( )
Functions defined by the programmers (users) are called as user-defined functions.
23
A function is a self-contained program segment that carries out some specific, well-defined task.
Every C program consists of one or more functions. One of these functions must be called main.
Execution of the program will always begin by carrying out the instructions in main ( ).
Additional functions will be subordinate to main, and perhaps to one another. If a program
contains multiple functions, their definitions may appear in any order, though they must be
independent of one another. That is, one function definition cannot be embedded within another.
A function will carry out its intended action whenever it is accessed (i.e., whenever the function
is called) from some other portion of the program. The same function can be accessed from
several different places within a program. Once the function has carried out its intended action,
control will be returned to the point from which the function was accessed.
Generally, a function will process information that is passed to it from the calling portion of the
program and return function via special identifiers called argument (also called parameters) and
returned via the return statement. Some functions however, accept information but do not return
anything where as some functions may return multiple values.
Advantages of functions:
Many program require that a particular group of instructions be accessed repeatedly from several
different places within the program. The repeated instructions can be placed within a single
function, which can then be accessed whenever it is needed. Moreover, a different set of data
can be transferred to the function each time it is accessed. Thus, the use of function avoids the
need for redundant (repeated) programming of the same instructions.
A complete program can be broken up into a number of smaller sub programs.
A program written as a sequence of functions with each function carrying out a specified task, it
is easy to understand. Such a program is also easy to modify.
Commonly used functions may be generalized, tested thoroughly and kept in a library for future
use.
Functions develop by others may be used.
To make use of the user-defined functions, the programmer must
Define a function
Declare the prototype of a function
Invoke the function.
Function definition:
A function definition describes what a function does, how its actions are achieved and how it is
used. It consists of a function header and a function body. The format for defining a function is:
Return-type function-name (parameters) /*function header */
{
declarations;
statements;
function body
return(expressions);
}
The first line is known as the function header. The function header is not terminated by a semicolon. The function body follows the function header and is always enclosed in braces. The
body of the function is composed of declarations and statements. The statements describe the
actions to be performed by the function.
Return-type: Specifies the data-type of the value returned by the functions. If the return-type is
omitted, the value return is assumed to be an int type by default Void is specified in place of
return type if the function returns no value.
24
Function name: Function name is an identifier. It cannot begin with underscore because such
names are reserved for the use of C-library.
Parameters: Arguments are known as formal arguments or formal parameters. Zero or more
parameters may be used. Each parameter must be preceded by its data-type. Commas must
separate parameters. Parameters are used to pass the value into the function. For functions without
parameter, the keyword void is placed within the parenthesis following the function-name.
25
26
27
}
int square (a) /* function definition */
int a;
{
int s;
s = a*a;
return (s);
} /*end of function square */
Statements within the square function can refer to the variable s, but statements in main cannot
refer. If a reference to s is made in main function, an error will be reported. Similarly, the
function square cannot directly refer to the variables side and area. These variables can be
referred to only within the main function in which they have been declared. This phenomenon is
referred to as scope. The scope of a variable refers to the range within a program over which that
variable has meaning.
A variable exists only when the function that contains the variable is in execution. Thus the
variable s in the example will not exist until the function square is called. When execution of the
function is complete, the variable also disappears.
Declaring a variable with the same name in two functions will not make it possible to use that
variable to communicate between functions. This can be seen from the following example.
#include<stdio.h>
#include<conio.h>
int modify ( ); /*function prototype*/
void main ( )
{
int a=5; clrscr ( );
printf (\n The value of a is %d, a);
modify ( );
printf (\n The value of a after the function call is %d, a);
getch ( );
}
int modify (void) /*function definition*/
{
int a;
a = 25;
return (a);
}
The variable a is declared in 2 functions main ( ) and modify ( ). In the main function, the
value of a is 5. In function modify ( ) the value of a is 25. When the program is executed, the
output will be
The value of a is 5
The value of a after the function call is 5.
The main function declares a and assigns the value 5. This value is printed, then the function
modify ( ) is called. The function creates its own local variable a and assigns the value 25 to it.
This assignment will have no effect on the variable name a that was created by the main
function. When control returns to the main function, the variable a local to main still contains
the value 5 and that is printed.
28
A function does not terminate its execution when calling another function; it only suspends
execution. Hence, the variable a local to main remains while the function modify is in execution.
The variable a is main will disappear only when main finishes execution, which is the
execution of the entire program.
Two-way communication between functions can be made through the use of global variables.
These variables are not declared within a specified function and hence are accessible to all
functions in the program. Consider the following:
/* program to illustrate global variables*/
#include<stdio.h>
#include<conioh>
int getside ( );
int calculate ( );
int side, area;
void main ( )
{
printf (Enter the side of the square : );
side = getside ( );
calculate ( );
printf (\nThe area of the square is %d, area);
getch ( );
}
int getside ( )
{
int a;
scanf (%d, &a);
return (a);
}
int calculate ( )
{
area = side*side;
}
The function main and calculate use the global variables side and area. The function getside uses
a local variable a.
The variables side and area are global because they are not declared within the body of any
function. Usually, global variables are declared in the beginning of a program, before the main
function.
Note:
The main function has no declaration for the variables side and area. If it has, they will be
considered local to main. According to scope rules in C. If a local variable is given the same
name as a global variable, the function declaring the local variable can refer only to the local
variable and not to the global variable of the same name.
Storage Classes
A variable in C is in one of the four storage classes.
Automatic Variables
External Variables
Static Variables
29
Register Variables
We consider the scope and lifetime of each of the classes. The scope of a variable determines
over what part of the program a variable is available for use. Lifetime refers to the period during
which a variable retains a given value during execution of a program.
Automatic Variables:
Automatic variables are declared inside a function in which they are to the utilized. They are
created when the function is called and destroyed automatically when the function is exited.
They are local or private to the function in which they are declared because of this property they
are also called local or internal variables. A variable declared inside a function without storage
class specification is by default an automatic variable.
e.g., the following two declarations are the same.
main ( )
{
int I;
------}
main ( )
{
auto int I;
------}
A variable local to the main function will be normally alive throughout the program, although it
is active only in main.
External variables:
Variables, which are both active and alive throughout the program, are known as external
variables. They are also known as global variables. Global variables are accessed by any
function in the program.
e.g.,
int I; float a;
main ( )
{
------}
function1 ( )
{
------}
function2 ( )
{
------}
30
The variable I and a will be available to all the three functions main, function1 and function2.
In case a local variable and a global variable have the same name, the local variable will have
precedence over the global variable in the function where it is declared.
Consider the example:
Int I;
Main ( )
{
I = 100;
}
function1 ( )
{
int I = 0;
--I = I + 1;
--}
When function1 references i, it will be referencing only the local variable I and not the global
one. Hence, the value of i in the main function will not be affected.
One feature of a global variable is that is it is visible only from the point of declaration to the end
of the program. Consider the example:
main ( )
{
y = 10;
----}
int y;
function1 ( )
{
y = y+1;
--}
In the example above y is referenced in main, but is not defined in it. Hence, an error message
will be displayed. This problem can be solved by declaring the storage class as extern as shown
in the example below.
main ( )
{ be a constant expression. A static variable without an initializer is set to zero. If the value is
changed during the execution, the recent value is retain. When the execution enters the next time
in the same block, the initializer is neglected and recently stored value is retained. Thus, an
internal static variable has persistent storage, block scope and no linkage.
If a static variable is declared before main ( ), i.e., outside all the blocks in a source file, it is
known as an external variable. An external static
extern int y;
---}
function1 ( )
31
{
extern int y;
--}
The variable y has been defined in the main and function1. The declaration y as an external
variable instructs the compiler that y is an integer type and its definition appears somewhere in
the program. Inside the functions main and function1, a reference to y is permitted. Whenever
an external variable is modified in a block, the effect is propagated to all places it is used because
of its global scope. The latest value is retained.
main ( )
{
extern x; int y =10, z;
z =y/x;
printf (\n x = %d\n y = %d\n z = %d; x, y, z);
}
int x = 5;
Static variables:
Any variable declared with the keyword static is treated as a static variable. A static variable can
be internal static or external static based on the place of its declaration. Both the static variables
are declared using the keyword static. If a static variable is declared inside a block, it is known
as internal static variable. The storage used by an internal static variable in a block is not lost
after the completion of the execution. Even after the termination of the block, the value of the
static variable is available. If the internal variable is initialized inside a block, it is initialized
only once. The initializer must be a constant expression. A static variable without an initializer
is set to zero. If the value is changed during the execution, the recent value is retained. When
the execution enters the next time in the same block, the initializer is neglected and recently
stored value is retained. Thus, an internal static variable has persistent storage, block scope and
no linkage.
If a static variable is declared before main ( ), i.e., outside all the blocks in a source file, it is
known as an external variable. An external static be a constant expression. A static variable
without an initializer is set to zero. If the value is changed during the execution, the recent value
is retained. When the execution enters the next time in the same block, the initializer is
neglected and recently stored value is retained. Thus, an internal static variable has persistent
storage, block scope and no linkage.
If a static variable is declared before main ( ), i.e., outside all the blocks in a source file, it is
known as an external variable. An external static variable has permanent storage, file scope and
internal linkage. Initiasation of an external static variable assigns the initialized value when the
program begins its execution. It is initialized only once. The initialiser must be a constant
expression. The recent value is retained when the execution starts next time.
Some valid declarations
Static int a, b, c=5;
Static float x=2.5,y;
Advantages of the Static Variables:
The scope helps in accessing the variable globally within a file. Change of value in any
place within the file is available in its scope.
32
Previous value is retained even after the completion of the execution of the block, but
before the completion of the execution of the program.
Initialization is done only once and the value is retained.
An internal static variable is a local variable and in external static variable is a global
variable. Based on he requirement, it may be declared accordingly.
Eg..
/*program to illustrate internal static variable*/
#include<stdio.h>
#include<conio.h>
void main( )
{
int i,x=2,y=10;
printf(x=%d\ny=%d\n,x,y);
for(i=1;i<=3;I++)
{
static int z = 100; /*internal static variables*/
printf(\n x = %d\ny=%d\nz=%d, x, y, z);
z=z/x;
y=y+z;
}
}
The output will be
x = 2 y = 10
x = 2 y = 10 z = 100
x = 2 y = 60 z = 50
x = 2 y =85 z = 25
If the storage class static is omitted, it will be treated as an auto storage class by default. In this
case, the output will be:
x = 2 y =10
x = 2 y = 10 z = 100
x = 2 y = 60 z = 100
x = 2 y = 110 z = 100
/*program to illustrate an external static variable */
static float x = 5.00; /*x is a external static variable*/
void main ( )
{
float y = 2.0;
printf (\n x = %f\t y = %f, x, y);
{
float y = 3.14;
x = y * 3;
printf (\n x = %f, y = %f, x, y);
}
printf(\nx = %f, y = %f, x, y );
}
33
34
int *p;
p = &i;
Both * and & are unary operators, required only one operand.
The syntax for defining a pointer variable is
Type *variable-name;
Note:
(i)
The variable name must be always preceded by *
(ii)
The type must correspond to the type of data stored in the address i.e., the type of data
stored in the target variable.
Some valid declarations are:
float *a;
char *ch;
double *x;
The pointer variable a points to a memory location containing a float. The pointer variable
ch points to a memory location containing a character. The pointer variable x points to
memory locations containing a double.
Initialization of a pointer variable:
When a pointer variable is defined, a memory location for it is allocated. But the contents of
that location are not known. The location contains some arbitrary data, i.e., garbage. When
the uninitialized pointer variable is used, it may lead to unpredictable results. Hence, a
pointer variable should never be used for data manipulation until it is initialized.
Consider the following definitions of ordinary variables and the corresponding pointer
variables.
int I = 100;
float f = 2.5;
char c =a;
int *pi;
float *pf;
char *pc;
After this definition, for the three pointer variables, memory locations will be allotted, but
they are not yet initialized.
There are two methods to initialize pointer variables. In the first method, the address of
another variable already defined is assigned to the pointer variable.
e.g.,
pi = &i;
pf = &f;
pc = &c;
In the second method, contents of * previously defined variables are assigned as the contents
of the address referred by the pointer variable.
e.g.,
*pi = i;
*pf = f;
*pc = c;;
/* program for defining and initializing pointer variables*/
#include<stdio.h>
#include<conio.h>
35
void main ( )
{
int I, *pi;
float f, *pf;
char c, *pc;
I=100;
f = 2.5;
c = a;
printf(\ni = %d\t f = %f \t c = %c, I, f, c);
printf (\nAddress of I = %d\t f = %d\t c = %d, &I, &f, &c);
printf (\nBefore initialization of pointer variables :\n);
printf (\nAddress of pi = %d\t pf = %d\t pc = %d, &pi, &pf, &pc);
printf (\nValue of pi = %d\t pf = %d\t pc = %d, pi, pf, pc);
pi = &I; pf = &f; pc = &c; /*pointer variables initialized*/
printf (\nAfter initialization of pointer variables: \n);
printf (\nvalue of pi = %d\t pf = %d\t pc = %d, pi, pf, pc);
printf (\n value of *pi = %d\t *pf = %f\t *pc = %c, *pi, *pf, *pc);
getch ( );
}
Pointers as Function Parameters (Call by reference):
While discussing functions we saw that a function was called by passing the values as
arguments to the called function. In other words, only copies of the values are passed on and
the called function cannot alter the original values. This is because the called function has no
access to the variables. Also, a function can return only one value to the called function.
With the use of pointers it is possible:
To provide means of accessing and altering the variables in the called function.
To return more than one value to the called function indirectly.
In this, method, the value of a pointer variable is passed to the called function. Since the
value of the pointer variable is the address of its target variable, the called function can
access that variable using the address and manipulate or alter the value stored. This is known
as passing by reference.
The values of any number of pointer variables can be passed to the called function, which
can manipulate the values stored therein. These modified values become available to the
called function automatically. The calling function also knows their addresses because of
this arrangement; the called function is able to return more than one value to the called
function.
In call by reference the address of the target variable is passed to the called function as actual
parameter. In the called function receiving this address, it should be assigned to a pointer
variable.
Example:
The program passes two parameters viz the addresses of x and y to the function square ( ). In
the function definition the formal parameters are shown as pointer variables.
/*program for call by reference*/
#include<stdio.h>
#include<conio.h>
void square (int *, int *); /*function prototype*/
36
void main ( )
{
int x, y;
x = 10;
square (&x, &y); /*function call with addresses of x and y*/
printf (\n Value of x = %d, x);
printf (\n Value of square of x = %d, y);
}
void square (int a, int b) /*function definition*/
{b = (*a) * (*a); }
The output of the program will be as follows:
Value of x = 10
Value of square of x = 100;
Note that there is no return statement in the function.
Here we consider the called function returning two values to the calling function. The
address of three variables are passed to the called function power ( ). The function evaluates
the square and cube of x and places them in y and z. The variables a, b and c contain the
addresses of x, y, z. The called function will return two values to the called function
indirectly by using the pointer variables.
#include<stdio.h>
#include<conio.h>
void power (int *, int *, int *);
void main ( )
{
int x, y, z; x = 10; clrscr ( );
power (&x, &y, &z);
printf (\n Value of x = %d, x);
printf (\n Value of square of x = %d, y);
printf (\n Value of cube of x = %d, z);
}
void power (int *a, int *b, int *c)
{
*b = (*a) * (*a);
c = (*b) * (*a);
}
Pointer to a pointer:
A pointer contains an address of a variable that variable can also be pointer variable
containing the address of another variable.
If x is an integer variable and P1 a pointer variable containing the address of x, then
P1 = &x;
*p = x;
Let p2 be another variable containing the address of p1.
i.e.,
p2 = &p1;
and
*p2 = p1;
37
38
In this declaration, struct is a required keyword; tag is a name that identifies structures of this
type (i.e., structures having this composition); and member-1, member-2,.. member-n are
individual member declarations (Note: There is no formal distinction between a structure
definition and a structure declaration; the terms are used interchangeably).
The individual members can be ordinary variables, pointers, arrays or other structures. The
member names within a particular structure must be distinct from one another. Though a
member name can be the same as the name of a variable that is defined outside of the structure.
A storage class, however cannot be assigned to an individual member and individual member
cannot be initialized within a structure type declaration.
Once the composition of the structure has been defined individual structure-type variables can be
declared as follows.
Storage-class struct tag variable-1, variable-2, ..variable-n;
Where storage-class is an optional storage class specifier, struct is a required keyword, tag is the
name that appeared in the structure declaration, then variable-1, variable-2, are the structure
variables of type tag. It is possible to combine the declaration of the structure composition with
that of the structure variables as shown below:
storage-class struct tag
{
member-1;
member-2
------member-n;
} variable-1, variable-2, ., variable-n;
the tag is optional in this situation.
Operators used in structures:
Some of the operators exclusively used in structures, they are as follows
. (Dot operator)
= (Assignment operator)
-> (Arrow operator)
The definition of structure variables may be given along with the template:
struct employee
{
char name[25];
int number;
float basicpay;
} emp1, emp2;
Accessing members of a structure:
The dot (.) operator is used to refer to individual members of a structure. With reference to the
example considered, the members may be referenced as follows:
emp1.name
emp2.basicpay
The structure variable name is followed by the dot operator and is followed by the name of the
member. If the member is an array, the individual elements of the array can be referenced with a
subscript.
e.g.,
39
emp1.name[10]
The syntax of referring a structure member is
structvarname.membername
The above reference can be used either to retrieve the data or to modify the value of the member.
Some examples of accessing the members are:
emp1.name=Narayana;
emp2.basicpay = 12000.00;
printf(%f, emp2.basicpay);
Structure Assignment:
When two structure variables, say emp1 and emp2 are defined with the same type of structure,
i.e., with the same tag name such as employee, one variable can be assigned to the other.
e.g.,
emp2 = emp1;
With this assignment, the values of all the members of emp1 will be copied to the corresponding
members of emp2. Note that both the variables should be defined with the same tag name.
Initialization of structure members:
The rules for initialization of members of a structure are similar to those of array initialization.
The members of global or static type of structures variables can be initialized collectively but the
members of local structure variables (i.e., auto type) can be initialized only member by member.
Suppose emp1 is defined as a global of the structure employee, it can be initialized along with its
definition as
struct employee emp1 = { arun, 645, 8000.00};
If emp2 is a local variable, the members are initialized individually as follows:
emp2.name = AJAY
emp2.number = 344
emp2.basicpay = 6500.00
Array of structures:
We can have an array in which each item is a structure. Consider the following example:
struct employee
{
int number;
float basicpay;
}emp[50];
In the above example emp is an array variable, with each of its element is a structure of type
employee. The each element of the array is referenced with its subscript enclosed in square
brackets followed by a dot operator and the member-name (structure member).
e.g.,
emp[0].number = 110;
emp[0].basicpay = 2500.00;
printf (%f, emp[0].basicpay);
Array within structure:
Sometimes each member of a structure can be array. Consider the following example
struct
{
int regno;
int marks[5];
40
} stud[50];
In the above given example marks is the member of the structure, also it is an array of type
integer and then the structure variable is also an array. Each element of the array variable stud is
referenced with its subscripts enclosed in square brackets followed by a dot operator and the
each element of member (array) is referenced with its subscripts enclosed in square brackets.
e.g.,
stud[0].marks[0] = 64;
stud[0].marks[1] = 694;
stud[0].marks[2] = 81;
stud[0].marks[3] = 84;
stud[0].marks[4] = 55;
In the above examples, the integer values are assigned for marks of the five subjects of first
student of the array.
Pointers to a structure:
Just like any other pointer variable, a pointer variable for structure is defined. For example, with
reference to the structure considered. We may have:
struct employee *sp;
Here, sp is a pointer variable pointing to a structure variable with tag name employee. At this
stage, a memory location for the pointer variable sp is allotted, but its contents are not known.
Hence, sp must be initialized with the address of the structure variable before use.
e.g.,
sp = &emp1;
Note that in structures, the name of a structure is not its address. Hence, the address of the
structure variable must be explicitly obtained with the & operator. This is permissible because
sp is a variable. (In case of an array, the name of an array is a constant.)
The member of the structure pointed to by a pointer variable are accessed with use of the
operator ->
e.g.,
sp ->number = 125
sp ->basicpay = 4500
printf (\n %s, sp->name);
In the above example, the pointer variable sp is pointing towards the members number an
basicpay by the arrow operator (->). Here the pointer variable is directly accessing the members
of the structure, because the address of the structure variable is assigned to the pointer variable.
Nested Structure (Structure within a structure):
It is possible to have a structure in which a member is also another structure. Consider the
following example:
struct measure
{
int feet;
float inches;
};
struct room
{
struct measure l, b;
}r;
41
In the above given example, the structure (room) contains two members l and b. Both l and b are
the variables of the structure type measure. The variable r is the structure of type room, which
has the rights of accessing the members feet and inches through its own members. The access
method is given as follows.
e.g.,
r.l.feet = 3;
r.l.inches = 4.3;
r.b.feet =2;
r.b.inches = 2.1;
UNIONS
Unions, like structures contain members whose individual data types may differ from one
another. However, the members within all share the same storage area within the computers
memory, whereas each member within a structure is assigned its own unique storage area. Thus,
unions are used to conserve memory. They are useful for applications involving multiple
members, where values need not be assigned to all of the members at any one time.
In general terms, the composition of a union may be defined as
storage-class union tag
{
member-1;
member-2;
----member-m;
} variable-1, variable-2, . , variable-n;
Where storage-class is an optional specifier. Union is a required keyword and the other terms
have the same meaning as in a structure definition.
USER-DEFINED data-types:
C is flexible that it allows the user to define new data-type names and they can be subsequently
used in the program. These are called type definitions and they are not new data types but are
derived from the standard data types by renaming them differently.
The following is an example of a new data-type of name mark list, which is derived from a
structure.
typedef struct
{
char name[30];
int rollno;
int marks;
}
marklist;
Now, mark list becomes a data-type name and this can be used to define structure variables st1,
st2 and follows:
marklist st1, st2;
Enumerated Data-type:
Enumeration is a special type of variable, which can take values only a defined list of signed
integer constants. Each of these integer values is given a symbolic name. All these symbolic
names are listed within a pair of braces.
42
43
In the unbuffered or low-level system there is no buffer between the program and the device.
Read and write operations are done directly between the operating system and the program.
Low-level I/O functions have no formatting capability and are suitable for binary files only.
ANSI C does not provide for low-level I/O functions. It has standard functions defined only for
stream or buffered I/O.
Stream I/O Functions:
The function prototype for each of the stream I/O function is declared in the header file stdio.h.
Hence, this header file must be included in any C program, whenever any of these routines is to
be used.
The functions related to input from the keyboard and output to the monitor are discussed already.
They are:
Getchar putchar gets puts printf scanf vprintf
The functions sprintf sscanf vsprintf
Are concerned with formatted strings.
Routines connected with file I/O are:
Only one byte is read or written at a time. Routines available are: fgetc fputc getc putc ungetc
Line reading or writing:
Here, each line ending with a new line character is read or written as a string at a time. The
functions available are: fgets fputs
Formatted Reading or Writing:
Here, a group of related data, which can be a combination of different data types is read or
written together. The functions available are:
Fscanf fprintf vfprintf
Binary Read or Write:
They are also known as record read or write. The data stored in a record is full is read or written
in a single use of the functions. They are used with structures. The functions are:
fread fwrite
Other routines related to file management:
Opening and Closing of files:
Fopen freopen fclose fflush
Getting and Setting read / write positions:
Ftell fgetpos fseek fsetpos rewind
File Structure:
A data file is generally initialized as consisting of a number of record, with each record
comprising a number of fields of related items. Each field in a record may contain a different
type of data. The records in a file may be of the same length (fixed length record) or each record
any of a different length. (Variable length record file)
The functions listed earlier can be used with both variable and fixed length record files. For
dealing with variable length record files, field separators between adjacent fields should be
present.
Opening and Closing of files:
File Pointers:
There is a special data structure called FILE type, defined in the header file stdio.h. In a C
program, all files are referred through file pointers. A file pointer is a pointer variable of the type
FILE. The syntax for defining a file pointer variable is:
FILE *fp;
44
fp is the pointer variable. The datatype pointed to by fp correspond to FILE type. Whenever a
file is opened by a stream I/O functions such as fopen(), a pointer to the FILE structure
associated with that file is returned. In all subsequent operations on this file in the program, all
stream I/O functions refer to that file by this file pointer only.
Opening a file:
Before performing any operation on a file, it must be opened. The library function fopen() is
utilized for this purpose. The syntax is
filepointer = fopen(filename, mode);
Before making a call, the variable file pointer must have been defined as
FILE *filepointer;
There are two arguments for the function:
A string of characters for the name of the file.
A string of character for the mode of using the file.
The values of the two arguments may be given, enclosed in double quotes or they may be given
in the form of pointers to two strings.
The functions fopen() returns a pointer which is assigned to the pointer variable file pointer. If a
file cannot be opened or there is an error in opening the file, it returns a null value. A valid file
pointer cannot have this value. Each file opened will have a separate file pointer.
The string for the mode of using the file, to be given, as an argument for fopen shall be one of the
following:
r Open an existing text file for reading.
w Create a new text file for writing.
a Open an existing text file for appending.
r+ Open an existing file for both reading and writing, starting at the beginning of the file.
w+ Create a new text file for both reading and writing.
a+ Open an existing text file for both reading and appending.
If a binary file is to be used for the above six operations, the character b must be appended to the
mode string as:
rb wb ab r+b w+b a+b
Closing a file:
Every file opened must be closed when the program no longer requires it. This is accomplished
by using the function fclose() which is of the form:
fclose(fp);
Here fp is the name of the file pointer variable associated with the file that is to be closed.
Closing a file causes the data remaining in the buffer to be written to the file. Further, it updates
the directory entry for the files and frees the file pointer. Non-closure of a file may result in
errors, such as loss of data or corruption of the file.
The fclose() function returns an integer. The value returned is 0 if the close operation was
successfully performed; otherwise a non-zero value is returned.
The function freopen() is used to open another file with the same file pointer, closing the current
file associated with that pointer. It has the syntax:
freopen(new file name, fp);
Here, fp is the file pointer associated with a file already opened.
Generally, this file is used to re-direct stdout to a file instead of the usual destination, viz the
monitor.
45
46
f = fopen(stud.dat, r);
while(!feof(f))
{
fscanf(f, %d%s%f,&x.regno,&x.name,&x.avg);
printf(Name : %30s\n,x.name);
printf(Regno :%5d\n,x.regno);
printf(Average :%6.2f\n,x.avg);
}
fclose(f);
getch();
}
/*Program for Random File Creation*/
#include<stdio.h>
#include<conio.h>
#include<string.h>
void main()
{
struct stud
{
int regno;
float avg;
char name[30];
}x;
char c = y;
FILE *f;
clrscr();
f = fopen(stud1.dat, w);
while(c = = y || c = = Y)
{
printf(Enter the Regno :);
scanf(%d, &x.regno);
fflush(stdin);
printf(Enter the Name :);
scanf(%s,x.name);
printf(Enter the Average :);
scanf(%f,x.avg);
fflush(stdin);
printf(Do you wish to add one more :);
scanf(%c, &c);
fwrite(&x, sizeof(x), 1, f);
}fclose(f);
}
/*Program for Processing the Random File*/
#include<stdio.h>
47
#include<conio.h>
#include<string.h>
void main()
{
struct stud
{
int regno;
float avg;
char name[30];
}x;
FILE *f;
clrscr();
f = fopen(stud1.dat, r);
while(!feof(f))
{
if(fread(&x,sizeof(x),1,f) = = 0)
break;
printf(Name :%30s\n,x.name);
printf(Regno :%5d\n,x.regno);
printf(Average : %f\n, x.avg);
}
fclose(f);
getch();
}
48