C Language PDF
C Language PDF
C Language PDF
Chapter Outline
“Journey of thousand miles always begins 1.1. Introduction
with one step.”
–Chinese Quotation 1.2. History of C
1.3. Features of C
1.4. Applications of C
1.5. Conclusion
http://pradeeppearlz.blogspot.com 1 Functions
1.1. Introduction
A computer needs to be instructed to perform desired task. For this, programs are written using a special
computer language known as a programming language. Just as in a natural language, a programming
language consists of set of characters, statements and usage rules that allow the user to communicate
with computers. A programming language should follow syntax rules to create an accurate program so
that the computer can yield desired result. One of the most popular programming languages is C.
1.2. History of C
By 1960, a numerous collection of programming languages had come into existence, almost each
for a specific purpose. E.g., COBOL was being used for commercial applications, FORTRAN for
engineering and scientific applications and so on.
At this stage, the people started thinking about the language that can program all possible
applications. Therefore, an International committee was set up to develop such a language. This
committee came out with a language called ALGOL 60 in 1960. However, ALGOL 60 never really
became popular because it seemed too general.
To reduce this generality, a new language called Combined Programming Language (CPL) was
developed at Cambridge University in 1963. However, CPL turned out to be so big, having so many
features, that it was hard to learn and difficult to implement.
Basic Combined Programming Language (BCPL) was developed by Martin Richards at
Cambridge University in 1967. He aimed to solve the problem of many features to learn by bringing
CPL down to its basic good features. But, unfortunately, it turned out to be too less powerful and
too specific.
Around the same time, a language called B was written by Ken Thompson at American Telegraph
and Teli-Communications’ (AT&T) Bell laboratories, as a further simplification of CPL in 1970. But,
like BCPL, B also turned out to be a very specific.
Dennis Ritchie inherited the features of both B and BCPL, added some of his own and developed a
new programming language, C, in 1972.
For many years, the defacto standard for C was the version supplied with the UNIX. In summer of
1983, a committee was established to create an ANSI (American National Standards Institute)
standard that would define the C language. The ANSI C standard was finally adopted in 1989. The
standard was also adopted by ISO (International Standards Organization) and the resulting
standard was typically referred to as ANSI/ISO standard C. The version of C defined by the 1989
standard is commonly referred to as C89.
The work on C continued quietly along, with a new standard fir C being developed. The end result
was the 1999 standard C (C99). In general, C99 retained nearly all of the features of C89. The C99
standardization committee focused on two main areas: the addition of several numeric libraries and
the development of some special-use, but highly innovative, new features, such as variable –length
2
arrays. These innovations have once again put C at the forefront of the computer language
development.
1.3. Features of C
1. C is a middle-level language.
High-level languages have been designed to give better programming efficiency. i.e., faster program
development.
Low-level languages have been designed to give better machine efficiency. i.e., faster program execution.
C stands in between these two categories. Hence, it is often called as a middle-level level language, since
it was developed to have both: a relatively good programming efficiency and relatively good machine
efficiency.
4. C is a portable language.
Portability means the ability of executing a program on one machine that was written on another machine.
A C program written on one computer system (e.g., an IBM Pc) can be compiled and run on another
system (e.g., a DEC VAX system) with little or no modification.
6. C is a programmer’s language.
Surprisingly, not all computer programming languages are for programmers. E.g., BASIC was created
essentially to allow non-programmers to program a computer to solve relatively simple problems. In
contrast, C was created, influenced and field-tested by working programmers. The end result is that C
gives the programmer what the programmer wants: few restrictions, few complaints, block-structure,
3
stand-alone functions and compact set of keywords. C helps the programmer to write system programs
and end-user applications too.
1.4. Applications of C
The languages such as C++ or Java is evolved from the basic language C. Learning these
languages is made easy if we had the idea of the basic concepts of programming language that
were introduced in C.
Major parts of popular operating systems like Windows, UNIX, Linux is still written in C. Even
today, when it comes to performance (Speed of execution), nothing beats C. Moreover, if one is to
extend the operating system to work with new devices, one needs to write device driver programs.
These programs are exclusively written in C.
Mobile devices like cellular phones and palm tops are becoming increasingly popular. Also, common
consumer devices like microwave ovens, washing machines and digital cameras are getting
smarter by the day. This smartness comes from a microprocessor, an operating system and a
program embedded in these devices. These programs not only have to run fast, but also have to
work in limited amount of memory. No wonder that such programs are written in C. With these
constraints on time and space, C is the language of choice while building such operating systems
and programs.
Many popular games have been built using C. We must have seen several professional 3D
computer games where the user navigates some object, say a spaceship and fire bullets at the
invaders. The essence of all such games is speed. Needless to say, such games won’t become
popular, if they take a long time to move the spaceship or to fire a bullet. To match the
expectations of the player, the game has to react fast to the user inputs. This where C scores more
over other languages.
At times, one is required to very closely interact with the hardware devices. Since C provides
several language elements that make this interaction feasible without compromising the
performance, it is the preferred choice of the programmers.
1.5. Conclusion
C is a middle-level programming language that was developed by Dennis Ritchie at AT&T’s Bell labs, USA
in 1972. C language is procedure-oriented, easy-to-learn, portable, flexible and a programmer’s language
developed by working programmers. C acts as a base language for other languages such as C++ and
Java. By using C language, one can write simple application programs to tedious system programs that
interact with hardware. Embedded systems programming is best carried out with C.
4
Language Fundamentals-I
2
(Character set, keywords, identifiers, constants, variables)
Chapter Outline
“First, master the fundamentals.”
–Larry Bird 2.1. Introduction
2.2. Character Set
2.3. Tokens
2.3.1. Keywords
2.3.2. Identifiers
2.3.3. Literals
2.3.4. Data types
“I long to accomplish great and noble task, but 2.3.5. Variables
it is my chief duty to accomplish small tasks as
2.3.6. Type qualifiers
if they were great and noble.”
–Helen Keller 2.4. Conclusion
5
2.1. Introduction
Character Set: A character denotes any alphabet, digit, white space or any special symbol that is
used to represent information. A character set is collection of characters.
Token: A token is the smallest individual unit of a program.
Instruction: An instruction is a statement that is given to computer to perform a specific
operation.
Function: A function is a collection of instructions that performs a particular task.
Program: A program is a well-organized collection of instructions that is used to communicate with
the computer system to accomplish desired objective.
Alphabets: abcdefghijklmnopqrstuvwxyz
ABCDEFGHIJKLMNOPQRSTUVWXYZ
Digits: 0123456789
Special Symbols:
Symbol Meaning Symbol Meaning Symbol Meaning
{ Opening curly ‘ apostrophe ^ Caret or exclusive OR
brace
} Closing curly brace “ Double quotation & Ampersand
mark
( Opening ~ Negation or tilde * Asterisk
parenthesis
) Closing parenthesis ! Exclamation + Plus
[ Opening square # Pound or number - Minus or hyphen
bracket or hash
] Closing square % mod / Forward slash
bracket
. Dot or period ; Semi-colon \ Backward slash
? Question Mark : Colon > Greater than
| Pipe , Comma < Lesser than
_ Underscore = Assigns to
White space characters: blank space, horizontal tab, new line,
6
carriage return, vertical tab, form feed
2.3. Tokens
A token is the smallest individual unit (or element) of a program. The tokens used in a program are:
Keywords.
Identifiers.
Literals (constants).
Variables.
Operators.
2.3.1. Keywords
Each language comes with a set of words. As these words play key role in developing a program, these
are often termed as keywords.
Keywords are the built-in words whose meanings are already explained to compiler.
Keywords are the pre-defined or built-in words. Each keyword has its own definition that is defined by the
language developers. A C compiler can recognize keyword and replaces its definition whenever it is
needed. Keywords also called as reserved words. Each keyword has its own purpose and it should be used
only for that purpose. There are 3 types of keywords:
Keywords
int auto if
float static else
char extern switch
double register default
long case
short while
signed do
unsigned for
void break
struct continue
union goto
typedef return
sizeof
enum
const
volatile
It is important to note that all the keywords should be in lowercase. Some compilers may also include
some or all of the following keywords:
ada asm entry far
fortran huge near pascal
7
1. Which of the following are keywords in C?
a) int b) register
c) switch d) boolean
Q
U
2. Which of the following is a keyword in C?
E a) Int b) int
c) Integer d) integer
S
T
I 3. Which of the following is not a keyword in C?
a) volatile b) enum
O c) constant d) sizeof
N
S
2.3.2. Identifiers
As pre-defined names (i.e., keywords) are needed to develop a C program, User-defined names also
needed. These user-defined names are called as identifiers.
Identifiers are the names given to various program elements such as variables, constants,
arrays, functions, pointers…etc.
These names will be given by the user as and when needed. Giving meaningful identifiers makes program
easy to understand. To define an identifier one should follow these rules:
Rule #2: The first character of identifier must be a letter or an underscore (_). The subsequent
characters may be alphabets, digits or underscore. Special symbols are not allowed.
Ex: pradeep K123 Ravi_varma _abc (valid)
1Raj (invalid)
Rule #3: No special symbol is used except underscore (_). No spaces are allowed in an identifier.
Ex: gross_sal Rect_area (valid)
Gross salary s.i. profit&loss (invalid)
Rule #4: Upper and lower case letters in an identifier are distinct (or different).
Ex: The names amount, Amount, aMOUnt and AMOUNT are not the same identifiers.
Rule #5: An identifier can be arbitrarily long. Some implementations of C recognize only the first eight
characters, though most compilers recognize more (typically, 31 characters).
8
1) Which of the following are valid and invalid identifiers? Give reasons if not valid.
Q 1) record1 2)$tax 3)name 4)name-and-address 5) 1record
6) name and address 7) name_and_address 8) 123-45-6789
U 9) return 10)file_3 11)_master 12)_123 13) Ravi&Bro.
E
S 2) Assume that your C compiler recognizes only first 8 characters of an identifier.
Which of the following are valid and invalid identifiers?
T 1) Master_minds 2)char 3)s.i. 4) SimpleInterest 5)string 6)char1
I 7) identifier_1 8)ANSWER 9)answer 10)number#1
O
N
S
A constant or literal is a value that is being input by the user to a program. The value may
be a character, a string, an integer or a floating-point number.
There are two types of constants: Numeric constants and non-numeric constants. As the names
imply that numeric constant is collection of digits and non-numeric constant is collection of characters
from character set.
Constants
Numeric Non-numeric
Constants Constants
9
2.3.3.1. Integer constants
An integer constant (either positive or negative) is taken to be:
1. Decimal integer constant: if it consists of digits 0-9.
E.g., 98334 -3456 are valid decimal integer constants.
2. Octal integer constant: if it begins with 0 (digit 0) and should not contain 8 and 9.
E.g., 0534 035 are valid octal integer constants.
3. Hexa-decimal integer constant: if the sequence of digits should be preceded by 0x (or) 0X and
should hold the values from 0-9 (or) A-F (a-f).
E.g., 0xFACE 0X124c are valid hexa-decimal integer constants.
An integer constant may be suffixed by the letter u (or) U, to specify that it is unsigned (only positive). It
may also be suffixed by the letter l or L to specify that it is long (big integer). In the absence of any
suffixes, the data type of an integer constant is derived from its value.
Examples of integer constants:
Integer constant Description
5000U Unsigned decimal integer constant
123456789L Long decimal integer constant
0235353l Long octal integer constant
0x23FA3dU Unsigned hexa decimal integer constant
0XFFFFFFFUL Unsigned long hexa-decimal integer constant
0243UL Unsigned long octal integer constant
Decimal notation: In this notation, the floating-point number is represented as a whole number followed
by a decimal point and a fractional part. It is possible to omit digits before or after the decimal point. A
floating-point constant can include one of the suffixes: f, F or l, L.
10
Exponential notation: Exponential notation is useful in representing numbers whose magnitudes are
very large or very small. The exponential notation consists of a mantissa, e or E and an exponent. The
mantissa is either an integer or a real number expressed in decimal notation. A mantissa can be preceded
by a sign (+ or -). The exponent is an integer preceded by an optional sign.
Note: It should be understood that integer constants are exact quantities; where as floating-point
constants are approximations. We should understand that the floating-point constant 1.0 might be
represented within computer’s memory as 0.99999999….., even though it might appear as 1.0 when it is
displayed on the screen (because of automatic rounding). Therefore, floating-point values can not be used
for certain purposes, such as counting, indexing…etc, where the exact values are required.
It is important to note that character constants do not contain the ‘ (single quote character) or new line
within it. In order to represent these and certain other characters, the following escape sequences (or
backslash character constants) may be used:
11
Backslash Description
character
constant
\n New line
\t Horizontal tab
\v Vertical tab
\b Back space
\r Carriage return
\f Form feed
\\ Backslash
\? Question mark
\’ Single quote
The escape sequence \000 consists of the backslash followed by 1, 2 or 3 octal digits which are taken to
specify the value of a desired character. A common example of this construction is \0 (not followed by any
digit), which specifies the character NUL.
The escape sequence \xhh consists of backslash followed by x, followed by hexa-decimal digits, which are
taken to specify the value of the desired character. There is no limit on the number of digits, but the
behavior is undefined if the resulting character value exceeds that of largest character.
12
Interview question #1
What is the difference among 1, ‘1’ and “1”?
1 is a decimal integer constant that occupies 2 or 4 bytes based on execution environment (i.e, on
processor and compiler).
‘1’ is a character constant that occupies 1 byte containing the ASCII code of the character 1.
“1” is a string constant that occupies 2 bytes; one byte containing ASCII code of character 1 and one
byte for null character with value 0 that shows end of string.
1) Which of the following are valid and invalid Integer constants? Give reasons if not
valid.
1) 123.34 2) 0893 3)-2345 4)0x123 5)3458UL 6)2345l 7)0124 8)0XFAGE
Q
2) Which of the following are valid and invalid floating-point constants? Give reasons
U if not valid.
E 1) -934 2) 0345 3)-89.34 4)9E+3 5)67.84L 6)89.342f 7)0.3E-4 8)89. 9).89
S 3) Which of the following are valid and invalid character constants? Give reasons if
not valid.
T 1) ‘a’ 2) ‘{‘ 3)’0’ 4)’ ‘ ‘ 5)’\m’ 6)’\023’ 7)’\x3456’ 8)’,’ 9)’134.3’ 10)’435’
I
4) Which of the following are valid and invalid string constants? Give reasons if not
O valid.
N 1) “Master minds” 2) “234-567-466” 3)’”King & queen” 4)”C” ”is brilliant”
5)”he told-“ I miss you”” 6)”Ravi’s friend”
S
2.3.4. Data types
Data type is a classification or category of various types of data that states the possible
values that can be taken, how they are stored and what operations are allowed on them.
In simple terms, data type is a set of values and operations on those values.
2.3.4.1. Primitive data types: There are 5 basic data types in C. The size and range of each of these
data types may vary among processor types and compilers. The following table shows the primitive data
types in C:
Data type Size (in bytes) Range
13
Type modifiers: Except the data type void, the primitive data types may have various type modifiers
preceding them. Type modifiers are the keywords that are used to modify the behavior of existing
primitive data types. There are two types of modifiers:
Size modifiers: These type modifiers modify the number of bytes a primitive data type occupies.
Based on size, the maximum and minimum values, a primitive data type specifies, will be changed.
The size modifiers include: long and short.
Sign modifiers: These type modifiers modify the sign of a primitive data type. The sign modifiers
include: signed and unsigned.
Size modifiers: A compiler can decide appropriate sizes depending on operating system and hardware for
which it is being written, subject to following rules:
a) shorts are atleast 2 bytes long.
b) longs are atleast 4 bytes long.
c) shorts are never bigger than ints.
d) ints are never bigger than longs.
compiler short int long
16-bit 2 2 4
32-bit 2 4 4
Sign modifiers: if unsigned type modifier is preceding a primitive data type, then the variables of the
specified type accept only positive values. If signed type modifier is preceding a primitive data type, then
the variables of specified type accept both positive and negative values.
The following table specifies various data types including type modifiers: (16-bit compiler)
Data type Size (in Range
bytes)
char / signed char 1 -128 to +127
unsigned char 1 0 to 255
int / signed int / short int/ 2 -32768 to +32767
signed short int
unsigned int / unsigned short 2 0 to 65535
int
long int / signed long int 4 -2,147,483,648 to +2,147,483,647
unsigned long int 4 0 to 4,294,967,295
Float 4 -3.4e38 to +3.4e38 with 6 digits of precision.
double 8 -1.7e308 to +1.7e308 with 10 digits of precision.
long double 10 -1.7e4932 to +1.7e4932 with 10 digits of precision.
2.3.4.2. User-defined data types: These are the data types defined by the user according to his needs.
These data types will be defined by using primitive data types. The user-defined data types include:
struct, union, enum.
14
2.3.5. Variables
The value that is being input to a program will be held by some entity known as a variable. This variable
associates with locations in memory, based on the type of input. E.g., if input is a floating-point value,
then the variable of type float associates with 4 bytes. Each of these bytes has its associated address.
However, it is a good idea to name these locations by avoiding the headache of remembering addresses.
Therefore,
A variable is a named location in memory that holds a value and that value may be varied during
execution of a program.
Ex: f=1.8*c+32
In this formula, 1.8 and 32 are fixed values means that they don’t change each time. Each time the values
of f and c are changed. Hence, f and c will be treated as variables.
In this syntax,
The content in square brackets is optional. The content in angle brackets is mandatory. There should be
spaces in between. The declarative instruction should always be ended with a semi-colon.
The storage class specifies the default value a variable(s) holds, storage location of variable(s),
scope and life time of variable(s). These include: auto, extern, register, static.
The data type is a keyword that specifies the type of data that is being hold by the variable(s).
The variable name is any legal identifier. In other words, it should be built based on the rules of
identifier. If there are more than one variable of the same type, then separate them with commas.
15
Initializing a variable: Initializing a variable is the process of assigning a value to the variable. The
initialization can be done as follows:
In these two syntaxes, we observe an operator, i.e., assignment operator (=), which is used to assign a
value of Right operand to Left operand. In the second syntax, the variable name should be declared
earlier.
Ex: int a=20; is equivalent to
int a;
a=20;
16
2.3.6. Type qualifiers
Type qualifiers are the keywords that add new meanings to existing data types. There are two type
qualifiers: const, volatile.
Making a variable as read-only variable: In order to make the value of variable as unchanged
during the execution of a program, initialize the variable with the type qualifier const as follows:
2.4. Conclusion
Every C program is typically a collection of functions. A function is a collection of instructions that perform
a specific task. Some of instructions in functions made up of words and characters. These are collectively
known as tokens. Hence, tokens are the smallest individual units of a program.
17
Language Fundamentals-III
4
(Writing a Program in C)
Chapter Outline
“First, master the fundamentals.”
–Larry Bird 4.1. Introduction.
4.2. Structure of C
program.
4.3. Executing a C
program in UNIX
system.
4.4. Language processors
“I long to accomplish great and noble task, but for executing a C
it is my chief duty to accomplish small tasks as
program.
if they were great and noble.”
–Helen Keller 4.5. Common
programming errors.
4.6. Multi-file compilation.
4.7. Conclusion.
18
4.1. Introduction
A program is a well-organized collection of instructions that is used to achieve desired objective. In order
to get our work is done using a computer, a program should be written. For writing a program, it is
necessary to learn a programming language. Usually, a programming language follows programming
paradigm(s), model(s) or style(s) in which a program should be written.
Since C is a programming language, it also follows a programming paradigm that is known as
procedure-oriented programming. In this procedure-oriented programming, a program will be divided into
small pieces called procedures (also known as functions, routines). These procedures are combined
into one single location with the help of return statements. From the main or controlling procedure,
a procedure call is used to invoke the required procedure. After the sequence is processed, the flow of
control continues from where the call was made.
Main
procedure
/* User’s Message*/
A comment line should begin with /* and end with */, though it is single line comment or multi-line
comment. However, comments with in the comments are not allowed.
Ex: /* Program to find area of triangle*/ [valid comment]
/* This program helps the user to calculate area of triangle by using three sides that will be input by the
user*/ [valid comment]
/*This is comment /* with in another*/ comment*/ [invalid]
The link section provides instructions to the compiler to link functions from standard library. Library
functions are grouped category-wise and stored in different files known as header files. If we want to
access the functions stored in the library, it is necessary to tell the compiler about the files to be accessed.
This is achieved by using the preprocessor directive #include as follows:
# include <filename>
Where “filename” is the name of the header file that contains the required function definition. Usually,
preprocessor directives are placed at the beginning of the program.
Ex: #include<stdio.h>
This statement informs the compiler to search for the file stdio.h in the subdirectory where other header
files are located.
The file to be included in our source code does not necessarily have to be a system header file.
We can include any file available in our system. Suppose that there is a file namely “myfun.c” in our
working directory. We can include this file by writing the following line:
# include ”myfun.c”
It is important to note that the file name is written inside double quotes. This informs the compiler that
the file to be included is available in the current directory.
# include <first.c> This command looks for the file “first.c” in the specified
directories only.
# include “first.c” This command looks for the file “first.c” in the current
working directory as well as the specified list of
directories only.
20
The definition section defines all the symbolic constants. This can be achieved by the preprocessor
directive #define as follows:
Where const_name is a legal identifier and value is the one that is going to be substituted. The spaces
should be needed among #define, const_name and value and never be terminated with a semicolon.
Ex: # define PI 3.1412
# define NEWLINE printf(“\n”)
# define int float
# define AND &&
The above lines are also called as macros. When these are used, the value will be substituted in
place of const_name wherever it is appears in our source code.
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 functions. The global
variables can be declared as in the way the local variables inside function are declared and can be
initialized.
Every C program must have one main() function. C permits different forms of main() as follows:
o main()
o int main()
o void main()
o main(void)
o void main(void)
o int main(void)
The empty pair of parentheses indicates that the function has no arguments. This must be
explicitly indicated by using the keyword void inside the parentheses. We may also specify the keyword
int or void before the word main. The keyword void means that the function does not return any
information to the operating system and int means that the function returns an integer value to the
operating system. When int is specified, the last statement in the program must be “return 0”.
The main() function contains two parts: declaration part and executable part. The declaration
part declares all the variables used in the executable part. There is atleast one statement in the
executable part. These two parts must appear between the opening and closing braces. The program
execution begins at the opening brace and ends at the closing brace. The closing brace of the main()
function is the logical end of the program. All statements in the declaration and executable parts end with
a semicolon (;).
21
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 main() may be absent when they are not required.
Program #1
Write a program to calculate area and circumfrance of a circle
1. /* A program to calculate area and circumfrance of a circle*/
2. #include<stdio.h>
3. #define PI 3.1412
4. main()
5. {
6. float radius,area,circum;
7. printf(“\nEnter radius:”);
8. scanf(“%f”,&radius);
9. area=PI*r*r;
10. circum=2*PI*r;
11. printf(“\n Area of circle=%f”,area);
12. printf(“\n Circumfrance of circle=%f”,circum);
13. }
Run:
Enter radius:23
Area of circle=1661.694824
Circumfrance of circle=144.495193
Annotation:
1. The first line is a comment that identifies the purpose of the program.
2. The lines 2 and 3 are called as preprocessor directives. The second line is a file-inclusion
directive that is used to include header files and user-defined programs as and when needed.
3. The line 3 is also called as a macro. Usually, it is used to define symbolic constants. Before
execution of program, the macro name (PI) will be substituted with its definition (3.1412),
wherever it appears.
4. The line 4 is the heading for main function. The empty parentheses following the name of the
function indicate that this function does not include any arguments. It is important to note that
the program execution always begins with main().
5. The line 5 indicates the start and line 13 indicates the end of body of main(). From lines 5 to 13,
collectively known as body of main() function or main() function definition.
6. The line 6 is declarative instruction that is used to declare all the variables that are used in a
program. In this program, radius, area and circum are variables that are used to hold the values
of radius, area and circumfrance of circle respectively. Since, all these can hold real values,
these are declared as of float type.
7. The line 8 is used to read a float value from keyboard. The scanf() function reads a value and
stores it in variable radius. Since, radius is of type float, %f is used. %f is a conversion
character that converts the input value into float. For the purpose of user interaction, line 7 is
written.
8. The lines 9 and 10 are called as assignment statements. In line 9, the area is calculated and is
stored in the variable area. In line 10, the circumfrance is calcualated and is stored in variable
circum
9. The lines 11 and 12 print the results that are stored in their respective variables onto the
monitor.
22
Program #2
Write a program to calculate simple interest and amount to be paid
/* A program to calculate simple interest and amount to be paid*/
#include<stdio.h>
int main(void)
{
float p,t,r,si,amount;
printf(“\n Enter principal amount, time and rate of interest:”);
scanf(“%f%f%f”,&p,&t,&r);
si=(p*t*r)/100.0;
amount=p+si;
printf(“\n Simple interest=%.2f”,si);
printf(“\n Amount to be paid=%.2f”,amount);
return 0;
}
Run:
Enter principal amount, time and rate of interest: 1000
2.5
5
Simple interest=125.00
Amount to be paid=1125.00
Program #3
Write a program to encode and decode a 5-letter word. Encode each letter by adding 3 to it.
Decode the encoded word.
/* A program to encode and decode a 5-letter word*/
#include<stdio.h>
int main(void)
{
char word[6];
printf(“\n Enter 5-letter word only:”);
scanf(“%5s”,word);
word[0]=word[0]+3;
word[1]=word[1]+3;
word[2]=word[2]+3;
word[3]=word[3]+3;
word[4]=word[4]+3;
printf(“\n Coded word=%s”,word);
word[0]=word[0]-3;
word[1]=word[1]-3;
word[2]=word[2]-3;
word[3]=word[3]-3;
word[4]=word[4]-3;
printf(“\n Original word=%s”,word);
return 0;
}
Run:
Enter 5-letter word only:
water
Coded word=zdwhu
Original word=water
23
4.3. Executing a C program in UNIX system
Step 1: Creating the C program
Once we load the UNIX operating system into the memory, the computer is ready to receive the program.
The program must be entered into a file that should have a name. The file name consists of letters, digits
and special characters (usually space is omitted), followed by a dot and a letter c.
Ex: simple.c
Hello123.c
A file can be created with the help of a text editor vi. The command for calling the editor and
creating the file is: vi file_name
If the file exists before, it is loaded. If it does not yet exist, the file has to be created so that it is ready to
receive the code to be typed. Any corrections in the program are done under the editor.
When the editing is over, the file should be saved on the disk. It then can be referenced later by
its name. The program that is entered into the file is known as source code or source program.
Step 2: Compiling the C program
Let us assume that we have created the source file: first.c. Now the program is ready for compilation. The
Compilation command to achieve this task under UNIX is: cc first.c
The source program instructions are now translated into a form that is suitable for execution by the
computer. The translation is done after examining each instruction for its correctness. If every thing is
alright, then compilation proceeds silently and the translated program is stored on another file with the
name first.o. This program is also known as object code.
Linking is the process of putting together other program files and functions that are required by the
program. Under UNIX, the linking is done automatically when the cc command is used.
If any mistakes are discovered, then they are listed out and the compilation process ends right
here. The errors should be corrected in the source program with the help of editor and the compilation is
done again.
The compiled and linked program is called the executable object code and is stored in another
file named a.out.
A compiled C program creates and uses four logically distinct regions of memory. The first region is
the memory that actually holds the program’s executable code. The next region is the memory where
global variables are stored. The remaining two regions are the stack and the heap. The stack is used to
for a great many things while our program executes. It holds the return addresses of function calls,
24
arguments to functions and local variables. It also saves the current state of the CPU. The heap is a region
of free memory that our program can use via C’s dynamic memory allocation functions.
25
4. Although an object file contains machine language instructions, it is not a complete program.
Usually, C is conveniently equipped with a library of prewritten code for performing common
operations or some-times difficult tasks. For example, the library contains hardware specific code
for displaying messages on the screen and reading input from the keyboard. Programs almost
always use some part of it. However, when the compiler generates an object file, it does not
include machine code for any run-time library routine the programmer might have used in
program. During the last phase of the translation process, another program called the linker
combines the object file with library routines. Once the linker is finished with this step, an
executable file is created. The executable file contains machine language instructions, or
executable code, and is ready to run on the computer.
5. Once, the executable file is stored on disk, the loader that is a part of operating system brings it to
main memory and starts it running.
This translation process is shown in the following figure:
Source code is
Source Code entered with help
of a text editor by
programmer.
Preprocessor
Modified
Source Code
Compiler
Object Code
Linker
Executable code
26
Interview question #1
What are the differences between compiler and interpreter?
Compiler Interpreter
1) Scans the entire program first and then 1) Translates the program line-by-line.
translates it into machine code.
2) Converts the entire program into machine 2) Each time the program is executed, every line
code; when all the syntax and linker errors are is checked for error and then be converted to
removed from execution. equivalent machine code.
3) Slow for debugging. 3) Good for fast debugging.
4) Execution time is less. 4) Execution time is more.
Interview question #2
What are the functions of linker and loader?
Linkers and loaders perform various related but conceptually different tasks:
1. Program Loading. This refers to copying a program image from hard disk to the main memory
in order to put the program in a ready-to-run state. In some cases, program loading also might
involve allocating storage space or mapping virtual addresses to disk pages.
2. Relocation. Compilers and assemblers generate the object code for each input module with a
starting address of zero. Relocation is the process of assigning load addresses to different parts
of the program by merging all sections of the same type into one section. The code and data
section also are adjusted so they point to the correct runtime addresses.
3. Symbol Resolution. A program is made up of multiple subprograms; reference of one
subprogram to another is made through symbols. A linker's job is to resolve the reference by
noting the symbol's location and patching the caller's object code.
So a considerable overlap exists between the functions of linkers and loaders. One way to think of them
is: the loader does the program loading; the linker does the symbol resolution; and either of them can
do the relocation.
Interview question #3
How many files are created when a C program is written using Borland c compiler?
When a C program is written, four files will be created:
1. Source file (e.g., first.c)
2. Back up file (e.g, first.bak)
3. Object file (e.g., first.obj)
4. Executable file (e.g., first.exe)
27
4.5. Common programming errors
An error is the mistake that causes the
Start
proper execution of program to be
stopped. The errors may be classified into
the following categories: Edit Source code
× Compile-time errors.
× Linker errors. Compiler
× Run-time errors.
Compile-time errors: Compile-time
errors are the most common, easy to Yes
locate and in a way harmless. Most Compile-
time
common causes of compilation errors are: error?
1. Not terminating the statement with
a semicolon or putting a semicolon No
at the wrong place.
Linker
2. Using values not defined.
3. Declaring variables after
assignment statement.
Yes
4. Failure to close the format string or Linker
the definition of function. error?
28
Linker errors: A program in C generally consists of a number of functions. They can be in different files.
An object file is created when a file containing the source program is successfully compiled. The complete
program may contain a number of object files. They have to be combined to create a single ‘.exe’ file. This
process is known as linking.
Linking is required even if our program contains a single function main() in a single file. This is
because, there are some object files in the library which form a part of the system. Our program has to be
linked with C library.
Linker errors result mainly because of wrong-spelt function names.
Ex:
main()
{
int k=10;
Printf(“k=%d”,k);
}
When the above code gets executed, the following error message gets displayed:
Undefined symbol _Printf in function main.
This is because C is case sensitive. It does not understand Printf(). The function should be written as
printf(), in lower case letters only. The program compiles because the compiler expects the function
Printf() to be available in some other ‘.obj’ module. When it is not available during linking, the process is
terminated with the error message.
Run-time errors: Runtime errors are the most difficult to locate and also most harmful. Even after
successful compiling and linking, the program may not produce the desired output. The compiler will not
help us to find the error because as far as the compiler is concerned there is no error in our program. The
undesirable output produced by a computer program is known as garbage.
Some of logical errors occur because of the following:
1. Variable exceeding the maximum or minimum limit.
2. Inability to supply the address of variable while reading it by scanf().
3. Inability to supply the arguments when the control string has format specifiers.
Ex:
main()
{
int a=25000,b=20000,c,k;
c=a+b;
printf(“%d”,c); /*error: variable exceeding maximum limit*/
printf(“\n Enter k value:”);
scanf(“%d”,k); /*error: segmentation fault*/
printf(“%d”); /*error: garbage value gets printed*/
}
29
Find the errors in the following programs:
/*program to find area, /* volume*/ of \*program to calculate area of triangle with
sphere*/ base and height*\
#include (stdio.h) #include<stdio.h>
#define PI 3.1412; main()
Main() int base,height;
{ printf(“\nEnter base and height values:”)
Float area; scanf(“%f%f”,base, height)l;
Printf(“\n Enter radius value:); area=1/2bh;
Scanf(“%d,&r); printf(“\n Area of triangle=%f”,area);
Area=4*PI*rrr/3;
Volume=4PIrr;
printf(“%d”,Area);
printf(“f”,volume);
}
30
4.6. Multifile Compilation
Multiple files can be compiled at a time using the command cc. Suppose that there are three files namely,
“first.c”,”second.c” and ”third.c”. These three files can be compiled at a time.This can be done as follows:
cc first.c second.c third.c
These files will be separately compiled into object files as “first.o”, “second.o” and “third.o” and then
linked to produce an executable program file a.out.
Note:
1) It is also possible to compile each file separately and link them later. E.g., the commands :
cc –c first.c
cc –c second.c
will compile the source files “first.c” and “second.c” into object files “first.o” and “second.o”. They
can be linked together by the command:
cc first.o second.o
2) We may also combine the source files and object files as follows:
cc sample.c second.o
only “sample.c” gets compiled and then linked with the object file “second.o”. This approach is very
useful when one of the multiple source files need to be changed and recompiled or an already
existing object files is to be used along with the program to be compiled.
3) The linker always assigns the same name to the executable object file as a.out. When we compile
another program, this file will be overwritten by the executable object code of the new program. If
we want to prevent from happening, we should rename the file immediately by using the
command: mv a.out name
4.7. Conclusion
A C program is a collection of functions that is written to achieve desired objective. First, a C program
should be written using any text editor (e.g., vi in UNIX). Later, it should be compiled. If there are errors
(whether these are compile-time or linker errors), these should be corrected by editing source file. Once
the program is error-free, it should be run or executed. If there are run-time errors, these should be
corrected by editing source file. The program should be recompiled and re-executed. If we get desired
output whenever we supply correct inputs, then the program is accurate.
31
Language Fundamentals-IV
5
(Operators and Expressions)
Chapter Outline
“First, master the fundamentals.”
–Larry Bird 5.1. Introduction.
5.2. Types of operators
5.2.1. Assignment operator
5.2.2. Binary arithmetic
operators.
5.2.3. Unary arithmetic
operators.
“I long to accomplish great and noble task, but 5.2.4. Relational operators.
it is my chief duty to accomplish small tasks as
5.2.5. Logical operators.
if they were great and noble.”
–Helen Keller 5.2.6. Conditional operator
5.2.7. Bitwise operators.
5.2.8. Special operators.
5.3. Operator’s
precedence and
associativity.
“Success is neither magical nor mysterious. Success
is the natural consequence of consistently applying 5.4. Evaluating an
the basic fundamentals.” expression.
–Jim Rohn
5.5. Type conversion in an
expression.
5.6. Conclusion.
32
5.1. Introduction
Operator: Operator is a special character (or symbol) that performs an operation using operands.
Operand: Operand is a variable or constant that acts as input for an operation to be performed.
Expression: Expression is a collection of operators and operands that, when evaluated, returns a value.
Ex: a+b is an expression in which the operator is + and the operands are a and b.
Unary operator: Unary operator is an operator that performs operation using only one operand at a
time.
e.g., ++ (increment) is a unary operator.
Binary operator: Binary operator is an operator that performs operation using two operands at a time.
e.g., > (greater than) is a binary operator.
Ternary operator: Ternary operator is an operator that performs operation using three operands at a
time.
e.g., ?:(Conditional operator) is ternary operator.
Operand_1=Operand_2;
Here, Operand_1 (also called as LValue) can be a variable or constant. Operand_2 (also called as RValue)
can also be a variable or constant or an expression.
When assignment operator is used, the RValue gets assigned to LValue.
Ex:
1) a=10; /* value 10 gets assigned to variable a*/
2) const float PI=3.1412f; /*value 3.1412 gets assigned to constant PI*/
3) c=a+b; /* a+b is calculated and result gets assigned to c*/
4) a=b=c; /* multiple assignment: value of c gets assigned to b, which in turn gets assigned to a*/
5) a+b=10; /* invalid assignment statement*/
33
Program #1
Write a program to interchange (or swap) two values by using temporary variable.
/* A program to interchange two numbers using temporary variable*/
#include<stdio.h>
main()
{
long int a,b,temp;
printf(“\n Enter any two numbers:”);
scanf(“%ld%ld”,&a,&b);
printf(“\n Before swap a=%ld\tb=%ld”,a,b);
temp=a; /* First, assign value of a to temp*/
a=b; /* Later, assign value of b to a*/
b=temp; /* Finally, assign value of temp to b*/
printf(“\n After swap a=%ld\tb=%ld”,a,b);
}
Output:
Enter any two numbers: 2943
34646
Before swap a=2943 b=34646
After swap a=34646 b=2943
Note:
1. The operator % does not work on the operands of data types: float or double or long double.
2. An unusual aspect of programming in C is the arithmetic which can be done with characters.
Consider the following:
char ch1,ch2;
ch1=’a’; /*assign ‘a’ to ch1*/
ch2=ch1+1; /*assign ‘b’ to ch2*/
35
The second assignment increases the ASCII (American Standard Code for Information Interchange) value
for the given character, a numeric value, by 1 and sets the result to ch2. Thus, ch2 contains ‘b’.
3. x%y is always equals to (x-(x/y)*y).
4. The second operand of operators % and / must be non-zero.
Program #3
Write a program to convert an alphabet from lowercase to uppercase
/*program to convert the lowercase to uppercase*/
#include<stdio.h>
main()
{
char ch;
printf(“\n Enter any lowercase alphabet:\n”);
scanf(“%c”,&ch); /* or ch=getchar();*/
ch=ch-32;
printf(“\n Uppercase alphabet:%c”,ch);
}
Output:
Enter any lowercase alphabet:
m
Uppercase alphabet:M
O 2)#include<stdio.h>
}
5)#include<stdio.h>
}
8)#include<stdio.h>
U main()
{
float a=1.5;
main()
{
printf(“%d”,4%3);
main()
{
int x;
T
int b=3; printf(“%d”,4%-3); x=4%5+6%5;
a=b/2+b*8/b-b+a/3; printf(“%d”,-4%3); printf(“x=%d”,x);
printf(“a=%f”,a); printf(“%d”,-4%-3); }
P
} }
6)#include<stdio.h> 9)#include<stdio.h>
3)#include<stdio.h> main() main()
U main()
{
int x;
{
float a=5,b=2;
{
int x;
int c; x=3*4%5;
T
x=-3*-4%-6/-5; c=a%b; printf(“x=%d”,x);
printf(“x=%d”,x); printf(“%d”,c); }
} }
36
5.2.3. Unary arithmetic operators
Unary Arithmetic operators perform the arithmetic operations such as increment & decrement and change
of sign on only one operand. There are 4 unary arithmetic operators:
Operator Operation
Unary + (Positive) Keeps the sign of value unchanged.
Unary - (Negative) Changes the sign of value.
++ (Increment) Adds 1 to value of operand and assigns the result to that operand only.
-- (Decrement) Subtracts 1 from the value of operand and assigns the result to that
operand only.
Operand_1 Unary_arithmetic_operator
(or)
Unary_arithmetic_operator Operand_1
Both sign operators should be preceded by the operand where as the increment and decrement operators
can be preceded or followed by the operand.
Ex: int a=10;
1) +a /*keeps the sign of 10 as positive only*/
2) –a /* changes the sign of 10 to negative*/
3) ++a or a++ /* equivalent to a=a+1; hence, a holds 11*/
4) –-a or a-- /* equivalent to a=a-1; hence, a holds 9*/
Program #4
Write a program to demonstrate positive and negative signs
/*program to demonstrate positive and negative signs*/
#include<stdio.h>
main()
{
int num;
printf(“\n Enter any number:”);
scanf(“%d”,&num);
printf(“\n Positive number=%d”,+num);
printf(“\n Negative number=%d”,-num);
printf(“\n Positive number=%d”,+(+num));
printf(“\n Negative number=%d”,+(-num));
printf(“\n Positive number=%d”,-(-num));
printf(“\n Negative number=%d”,-(+num));
}
Output:
Enter any number: 123
Positive number=123
Negative number=-123
Positive number=123
Negative number=-123
Positive number=123
Negative number=-123
37
Few words about increment and decrement operators:
If ++ is used before the operand, then this increment operator is called as pre-increment operator. If
++ is used after the operand, then this increment operator is called as post-increment operator. The
same treatment will be given to the --.
The increment / decrement operator works as a simple increment / decrement by one, if it is not
used as a part of an expression. In that case, there is no difference between operations of pre or post
increment or decrement operators.
However, when these operators are used as a part of an expression then the difference can be
noticed:
The pre-increment operator first increments the value of operand and then returns that
incremented value.
The post-increment operator first returns the existing value of operand and then increments the
value of the operand.
The pre-decrement operator first decrements the value of operand and then returns that
decremented value.
The post-decrement operator first returns the existing value of operand and then decrements the
value of the operand.
38
1)#include<stdio.h> 4)#include<stdio.h> 7)#include<stdio.h>
main() main() main()
{ { {
int x=5; int x=3,z; int x=3,z;
x++; z=x---111; z=x++ + x++;
printf(“x=%d”,x); printf(“x=%d z=%d”,x,z); printf(“x=%d
++x; z=%d”,x,z);
printf(“x=%d”,x); } }
} 5)#include<stdio.h> 8)#include<stdio.h>
OBSERVABLE main() main()
O
2)#include<stdio.h> { {
main() int x=3,z; int x=3,z;
{ z=x--- -1; z=x++ + ++x;
int x=3,z;
U
printf(“x=%d z=%d”,x,z); printf(“x=%d
z=x++ +10; z=%d”,x,z);
printf(“x=%d z=%d”,x,z); } }
}
T 3)#include<stdio.h>
main()
6)#include<stdio.h>
main()
{
9)#include<stdio.h>
main()
{
{
U
z=%d”,x,z);
} } }
T
10)#include<stdio.h> 11)#include<stdio.h> 12)#include<stdio.h>
main() main() main()
{ { {
int i=3,j; int x=4,y=3,z; int a,b;
j=++i*++i*++i; z=x-- -y; a=-3 - -3;
printf(“i=%d j=%d”,i,j); printf(“x=%dy=%dz=%d”,x, b=-3 - -(-3);
y,z); printf(“%d%d”,a,b);
} } }
39
equals to)
A relational expression is of the following form:
40
The logical operators are used to form logical expressions as shown below:
1) Logical AND expression:
Where Expression_1 and Expression_2 are any expression those return either true or false.
When logical AND operator is encountered, first Expression_1 is tested. It returns either true or
false. Secondly, the expression_2 is tested. It returns either true or false. Then both of these expressions’
values are combined to give the value of logical expression as given below:
Expression_1 Expression_2 Expression_1 && Expression_2
1 1 1
1 0 0
0 1 0
0 0 0
Ex: int a=10,b=30,c;
c=((a>b)&&(a!=b)); Ans: c=1
Note: If the left operand yields false value, the right operand is not evaluated by a compiler in a logical
expression using &&.
2) Logical OR expression:
Expression_1 || Expression_2
Where Expression_1 and Expression_2 are any expression those return either true or false.
When logical AND operator is encountered, first Expression_1 is tested. It returns either true or
false. Secondly, the expression_2 is tested. It returns either true or false. Then both of these expressions’
values are combined to give the value of logical expression as given below:
Expression_1 Expression_2 Expression_1 || Expression_2
1 1 1
1 0 1
0 1 1
0 0 0
Ex: int a=10,b=30,c;
c=((a>b)||(a!=b)); Ans: c=1
Note: If the left operand yields true value, the right operand is not evaluated by a compiler in a logical
expression using ||.
3) Logical NOT expression:
!(Expression_1)
41
When logical NOT operator is encountered, first the Expression_1 is tested. It returns either true or
false. Upon the value of this Expression_1, Logical NOT returns the value given below:
Expression_1 !(Expression_1)
1 0
0 1
Ex: int a=20,b=30,c=40,d;
d=!(a>b&&b>c); ans: d=1
O
int x,y,z; int x,y,z; int a=30,b=40,x;
x=y=z=1; x=y=z=-1; x=(a!=10)&&(b=50);
z=++x&&++y&&++z; z=++x&&++y&&++z; printf(“x=%d”,x);
U
printf(“%d %d %d”,x,y,z); printf(“%d %d %d”,x,y,z); }
} }
9)#include<stdio.h>
T
3)#include<stdio.h> 6)#include<stdio.h>
main()
main() main()
{
{ {
int a=100,b=200,c;
P
int x,y,z; int x,y,z;
c=(a==100||b>200);
x=y=z=1; x=y=z=-1;
printf(“c=%d”,c);
z=++x&&++y||++z; z=++x&&++y||++z;
}
printf(“%d %d %d”,x,y,z); printf(“%d %d %d”,x,y,z);
U } }
T main()
{
main()
{
main()
{
int x=11,y=6,z; int x=10,y=-20; int x=0,y=1;
z=x==5||y!=4; x=!x; y=!x;
printf(“z=%d”,z); y=!y; x=!y;
} printf(“%d %d”,x,y); printf(“%d %d”,x,y);
} }
42
5.2.6. Conditional operator
The conditional operator consists of two symbols: the question mark (?) and the colon (:). This is the only
operator in C that acts on three operands at a time. Hence, this operator is also called as ternary operator
or trinary operator. This operator acts in the same way as the if…else statement acts. Conditional
operator can be used as follows:
False True
Condition
Expression_2 Expression_1
Next_statement
Program #4
Write a program to find biggest of three numbers
/*program to find biggest of three numbers*/
#include<stdio.h>
main()
{
int num1,num2,num3,big;
printf(“\n Enter any three numbers:”);
scanf(“%d%d%d”,&num1,&num2,&num3);
big=((num1>num2)&&(num1>num3)?num1:num2>num3?num2:num3;
printf(“\n Biggest of three numbers=%d”,big);
}
Output:
Enter any three numbers: 190
452
43
Biggest of three numbers=452
43
1)#include<stdio.h> 4)#include<stdio.h>
main() main()
{ {
int x=3,y=4,z=4; int k=12,n=30;
printf(“ans=%d”,z>=y&&y>=x?1:0); k=(k>5&&n=4?100:200);
OBSERVABLE } printf(“k=%d”,k);
O
}
2)#include<stdio.h>
5)#include<stdio.h>
U
main()
{ main()
int x=3,y=4,z=4; {
int c=0,d=5,e=10,a;
T
printf(“ans=%d”,z>=y>=x?1:0);
} a=c>1?d>1||e>1?100:200:300;
printf(“a=%d”,a);
}
P 3)#include<stdio.h>
main()
6)#include<stdio.h>
{
U
main()
int i=-4,j,num=10;
{
j=i%-3;
int a=10,b=10;
j=(j?0:num*num);
T
printf(“ans=%d”,a>b?a*a:b/b);
printf(“j=%d”,j);
}
}
Bitwise operators perform operations on bits of data. These operators are used for testing, complementing
or shifting bits to the right or left. Usually, bitwise operators are not useful in cases of float and double.
There are six bitwise operators as shown below:
Operator Operation
& (Bitwise AND) Returns 1 if both corresponding bits are 1; otherwise 0.
| (Bitwise inclusive OR) Returns 0 if both corresponding bits are 0; otherwise 1.
^(Bitwise exclusive OR) Returns 0 if both corresponding bits are 0 or 1; otherwise 1.
~ (One’s complement) Returns 1, if bit is 0 and returns 0, if bit is 1.
<< (Left shift) Shifts least significant bit by specified number of times.
>> (Right shift) Shifts most significant bit by specified number of times.
All these operators are binary operators except one’s complement operator. One’s complement operator is
a unary operator.
44
Bitwise AND (&):
The operator & performs a bitwise AND between two operands. It compares each bit of the left operand
with the corresponding bit of the right operand. For each bit, the result is 1, if both the compared bits are
1; otherwise, the result is 0 as shown below:
0&0 0
0&1 0
1&0 0
1&1 1
Interview question #1
What is masking?
Masking is an operation in which the desired bits of a binary number or bit pattern are set to zero. The
operator & (Bitwise AND) is very useful for this purpose. To mask particular bits in a binary number, do
the following:
1. Create a new number that has binary pattern with 0s in the positions that you want to mask and
1s in other positions.
2. Perform bitwise AND operation between the number that is to be masked and created number.
0|0 0
0|1 1
1|0 1
1|1 1
45
Bitwise Exclusive OR (^)
The operator ^ performs a bitwise exclusive OR between two operands. It compares each bit of the left
operand with the corresponding bit of the right operand. For each bit, the result is 0, if both the compared
bits have the same value; otherwise, the result is 1 as shown below:
0^0 0
0^1 1
1^0 1
1^1 0
Constant >> n
(or)
variable >>n
Constant << n
(or)
variable <<n
~operand1
46
Interview question #2
Program #5
Write a program to convert an uppercase alphabet to lowercase alphabet
/*program to convert an uppercase alphabet to lowercase alphabet*/
#include<stdio.h>
int main()
{
char alpha;
printf(“\n Enter any uppercase alphabet:”);
scanf(“\n%c”,&alpha);
printf(“\n Lower case alphabet=%c”, alpha | 32);
return 0;
}
Output:
Enter any uppercase alphabet:
A
Lower case alphabet=a
Program #6
Write a program to swap two integers with out using temporary variable
/*program to swap two integers without using temporary variable*/
#include<stdio.h>
int main()
{
int a,b;
printf(“\n Enter any two numbers:”);
scanf(“%d%d”,&a,&b);
printf(“\n Before swap a=%d\tb=%d”,a,b);
a=a^b;
b=a^b;
a=a^b;
printf(“\n After swap a=%d\tb=%d”,a,b);
return 0;
}
Output:
Enter any two numbers: 10
20
Before swap a=10 b=20
After swap a=20 b=10
Examples:
47
5.2.8. Special operators
1. sizeof operator.
2. comma operator.
3. short-hand operators.
4. Referencing and dereferencing operators.
sizeof operator: It is an unary operator. It returns the number of bytes occupied by the operand in
memory. The operand may be a variable, a constant, an expression or simply a datatype.
Ex: printf(“%d”,sizeof(10)); /*prints 2 or 4*/
printf(“%d”,sizeof(int)); /*prints 2 or 4*/
int x=30; float y=45.355;
printf(“%d”,sizeof(y)); /*prints 4*/
printf(“%d”,sizeof(x+y)); /*prints 4*/
Comma Operator: A comma operator can be used as a separator or a terminator in the following
statements:
int a,b,c;
c=a,a=b,b=c;
This operator can also be used to link related expressions together. A comma-linked list of expressions
is evaluated from left to right and the value of right-most expression is the value of combined
expression.
Ex: value=(x=10,y=20,x+y); ans: value=30
Short-hand Operators: These operators are formed by combining both binary arithmetic operators
and bitwise operators with assignment operator. Hence, these are also called as compound assignment
operators.
The short-hand operators include: +=, -=, *=, /=, %=
&=, |=, ^=, <<=, >>=.
All of these operators are binary operators. So, these operands should act on two operands at a time.
48
Refencing and dereferencing operators: Referencing operator (&) is the operator that returns the
address of operand in the memory. Dereferencing operator (*) is the operator that returns the value at
the address that is pointed by the referencing operator.
Ex: int a=10;
printf(“\n Address of a=%u”,&a); /*prints address of a*/
printf(“\n Value of a=%d”,*(&a)); /*prints value of a */
O a) y=(int) (x+0.5);
b) y=int (x+0.5);
U c) y=(int )x+0.5;
d) y=(int)((int)x+0.5)
T 1)#include<stdio.h>
main()
P
{
printf(“%d %d %d”,sizeof(3.14f),sizeof(3.14),sizeof(3.14l));
}
U 2)#include<stdio.h>
main()
T
{
printf(“%d”,sizeof(4)/sizeof(2.0));
printf(“%d”,sizeof(2.0)/sizeof(4));
}
49
The following table lists the operators, their precedence and associativity.
Precedence Operands Operators Associativity
1 2 () [] . -> Left-to-Right
2 1 ! ~ ++ -- + - * & Right-to-Left
(type) sizeof
3 2 * / % Left-to-Right
4 2 + - Left-to-Right
7 2 == != Left-to-Right
8 2 & Left-to-Right
9 2 ^ Left-to-Right
10 2 | Left-to-Right
11 2 && Left-to-Right
12 2 || Left-to-Right
13 3 ? : Left-to-Right
14 2 = *= /= %= += -= Right-to-Left
&= |= ^= <<= >>=
15 2 , Left-to-Right
50
5.3. Type conversion in an expression
Type conversion is the process of converting a value from one data type to another. This type conversion
makes the operands in an expression belong to similar data type.
If casting is done from lower size type to higher size type value, then it is called as broadening
conversion. E.g., char to int.
If casting is done from higher size type to lower size type value, then it is called as narrowing
conversion, causes some loss of value.
E.g. float to int causes truncation of fractional part.
float to long causes truncation of fractional part.
double to float causes rounding of digits.
long int to int causes dropping of the excess high order bits.
int to short causes dropping of the excess high order bits.
long double
double
float
Broadening
conversion unsigned long int
long int
short char
Note: If the two operands in an assignment statement are of different data types, the right side operand
is automatically converted to the data type of the left side.
Ex: int a=10; Ex: float a=10.98;
float b; int b;
b=a; b=a;
printf(“%f”,b); printf(“%d”,b);
output: output:
Program #4
Write a program to print ASCII value of a character
/*program to print ASCII value of a character*/
#include<stdio.h>
main()
{
char ch;
int val;
printf(“\n Enter any character:”);
scanf(“\n%c”,&ch);
val=ch;
printf(“\n ASCII value of \’%c\’ is %d”,ch,val);
}
Output:
Enter any character:
a
ASCII value of ‘a’ is 97
52
1)#include<stdio.h>
main()
{
printf(“%d %d %d”,72,072,0x72);
OBSERVABLE }
O
U
T 2)#include<stdio.h>
main()
P
{
U printf(“%d %o %x”,72,72,72);
T }
Explicit type conversion: When we want to do type conversion forcefully, then we use cast operator.
Cast operator is used to convert value of an operand from one type to another explicitly by the user. This
explicit type conversion is also called as casting or coercion.
The usage of cast operator is as follows:
(type_name) expression
Here, type_name is any standard data type. The expression may be a constant, variable or an expression.
As this operator works on only one operand at a time, this is a unary operator.
5.6. Conclusion
C supports arithmetic, relational and logical operators like other programming languages. It supports
increment and decrement operators for faster execution. Bitwise operators are supported in C, which are
not available in other languages. In addition to simple assignments, C also provides compound
assignments or short-hand assignments.
Expressions are formulated with the help of operators and operands. These are evaluated to get
the desired result. These are evaluated according to the precedence levels of the operators and their
associativity. In evaluating mixed-type expressions, implicit conversion rules are followed. Explicit type
conversions are possible with coercion or type casting.
53
Control-Flow statements-I
6
(Conditional control-flow statements)
Chapter Outline
“I can't change the direction of the wind, but I
can adjust my sails to always reach my 6.1. Introduction.
destination.” –Jimmy Dean 6.2. Conditional control-
flow statements.
6.2.1. if statement.
6.2.1.1. simple if
statement.
6.2.1.2. if else
“Men, like nails, lose their usefulness when they statement.
lose direction and begin to bend.”
6.2.1.3. nested if
–Walter Savage Landor
else
statement.
6.2.1.4. else if
ladder.
6.2.2. switch
statement
“The means to gain happiness is to throw out from
oneself like a spider in all directions an adhesive 6.3. Conclusion.
web of love, and to catch in it all that comes”
-Leo Nikolaevich Tolstoy
54
6.1. Introduction
Simple statement: A simple statement is a syntactic construct that is used for performing a specific task.
Usually, a simple statement is terminated with a semi-colon (;).
Ex: c=a+b; //An assignment statement
a+b=c; // Not a statement; syntactically it is wrong
printf(“\n Hello world!”); //An output statement
Compound statement (or) Block: A compound statement is a collection of one or more simple
statements that are enclosed with in curly braces { and }. A block can be treated logically as one
statement. The statements in a block are executed sequentially.
Ex: {
int a=10,b=20;
c=a+b;
printf(“%d”,c);
}
Note: 1) A block can be placed in another block.
2) Forgetting the placing of one of the curly braces leads to syntax or logical error.
Null statement (or) Empty statement (or) void statement: A null statement is a statement that
serves for nothing. But, it is executed as a normal statement. A null statement is denoted as ;. A null
statement can appear wherever a statement is expected. Its use is necessary in cases where the presence
of a statement is required by the syntax, but no action is logically needed.
Control-Flow statement: Control-flow statement is a statement that determines the flow of control
during execution of a program. Flow of control is the order of execution of statements with in a program.
There are 3 kinds of control-flow statements:
Control-flow Statements
55
6.2. Conditional control-flow statements
Conditional control-statements are the control-flow statements that determine the flow of control based on
the condition. These are also called as decision-making control-flow statements or selection control-flow
statements. As the name implies, these are used to make a decision based on the available choices.
Decision making in a program is concerned with choosing or selecting to execute one set of statements
rather than another.
There are two conditional control-flow statements:
1. if statement
2. switch statement
6.2.1. if statement
if statement is one of decision-making control-flow statements. It has 4 notations:
1. Simple if statement.
2. if…else statement.
3. Nested if…else statement.
4. else if ladder
6.2.1.1. Simple if statement
Simple if statement is used to make a decision based on the available choice. It has the following form:
if(<condition>)
if-body
next-statement
In this syntax,
If is the keyword. <condition> is a relational expression or logical expression or any expression
that returns either true or false. It is important to note that the condition should be enclosed within
parentheses ( and ).
The if-body can be a simple statement or a compound statement or a null statement.
Next-statement is any valid C statement.
Whenever simple if statement is encountered, first the condition is tested. It returns either true or
false. If the condition is false, the control transfers directly to next-statement with out considering the if-
body. If the condition is true, the control enters into the if-body. Once, the end of if-body is reached, the
control transfers to next-statement. The flow of control using simple if is determined as follows:
56
Program #1
Write a program to calculate salary of an employee based on the following condition:
If he served the organization for more than 15 years, add Rs1500.00 to his basic salary.
/* A program to calculate employee’s salary*/
#include<stdio.h>
main()
{
float salary,bonus;
int yoj,cy,yos;
printf(“\n Enter current year and year of joining:”);
scanf(“%d%d”,&cy,&yoj);
printf(“\n Enter employee’s basic salary:”);
scanf(“%f”,&salary);
bonus=0;
yos=cy-yoj;
if(yos>=15)
bonus=1500; //if-body
salary=salary+bonus;
printf(“\n Salary=Rs. %.2f”,salary);
}
Run:
Enter current year and year of joining :2010 1992
Enter employee’s basic salary: 10000
Salary=Rs. 11500.00
Program #2
Write a program to calculate salary of an employee based on the following condition:
If he served the organization for more than 15 years:
Calculate 25% of his salary as HRA
Calculate 10% of his salary as DA
Rs1500.00 as bonus to his basic salary.
/* A program to calculate employee’s salary*/
#include<stdio.h>
main()
{
float salary,bonus,HRA,DA;
int yoj,cy,yos;
printf(“\n Enter current year and year of joining:”);
scanf(“%d%d”,&cy,&yoj);
printf(“\n Enter employee’s basic salary:”);
scanf(“%f”,&salary);
yos=cy-yoj;
if(yos>=15)
{ //if-body
HRA=(salary*25)/100.00;
DA=(salary*10)/100.00;
bonus=1500;
}
salary=salary+bonus+HRA+DA;
printf(“\n Salary=Rs. %.2f”,salary);
}
Run:
Enter current year and year of joining :2010 1992
Enter employee’s basic salary: 10000
Salary=Rs. 15000.00
57
6.2.1.2. if…else statement
if…else statement is used to make a decision based on two choices. It has the following form:
if(<condition>)
if-body
else
else-body
next-statement
In this syntax,
If and else are the keywords.
<condition> is a relational expression or logical expression or any expression that returns either true
or false. It is important to note that the condition should be enclosed within parentheses ( and ).
The if-body and else-body are simple statements or compound statements or null statements.
Next-statement is any valid C statement.
Whenever if...else statement is encountered, first the condition is tested. It returns either true
or false. If the condition is true, the control enters into the if-body. Once, the end of if-body is reached,
the control transfers to next-statement without considering else-body.
If the condition is false, the control enters into the else-body by skipping if-body. Once, the end
of else-body is reached, the control transfers to next-statement. The flow of control using if...else
statement is determined as follows:
58
Program #3
Write a program to check whether given year is leap year or not
/* A program to check whether given year is leap year or not*/
#include<stdio.h>
main()
{
int year;
printf(“\n Enter any year:”);
scanf(“%d”,&year);
if((year%4==0&&year%100!=0)||(year%400==0)
printf(“\n Given year is a leap year”);
else
printf(“\n Given year is not a leap year”);
}
Run:
Enter any year: 2000
Given year is a leap year
Program #4
Write a program to calculate salary of an employee based on the following conditions:
If he served the organization for more than 15 years:
Calculate 25% of his salary as HRA
Calculate 10% of his salary as DA
Rs1500.00 as bonus to his basic salary.
Otherwise:
Calculate 15% of his salary as HRA
Calculate 5% of his salary as DA
/* A program to calculate employee’s salary*/
#include<stdio.h>
main()
{
float salary,bonus,HRA,DA;
int yoj,cy,yos;
printf(“\n Enter current year and year of joining:”);
scanf(“%d%d”,&cy,&yoj);
printf(“\n Enter employee’s basic salary:”);
scanf(“%f”,&salary);
yos=cy-yoj;
if(yos>=15)
{ //if-body
HRA=(salary*25)/100.00;
DA=(salary*10)/100.00;
bonus=1500;
}
else
{
HRA=(salary*15)/100.00;
DA=(salary*5)/100.00;
bonus=0;
}
salary=salary+bonus+HRA+DA;
printf(“\n Salary=Rs. %.2f”,salary);
}
59
6.2.1.3. Nested if…else statement
Nested if…else statement is one of the conditional control-flow statements. If the body of if statement
contains at least one if statement, then that if statement is called as “Nested if…else statement”. The
nested if…else statement can be used in such a situation where at least two conditions should be satisfied
in order to execute particular set of instructions. It can also be used to make a decision among multiple
choices. The nested if…else statement has the following form:
if(<condition1>)
if(<condition2>)
if-body
else
else-body
next-statement
In this syntax,
if and else are keywords.
<condition1>,<condition2> … <condition> are relational expressions or logical expressions or any
other expressions that return true or false. It is important to note that the condition should be
enclosed within parentheses ( and ).
If-body and else-body are simple statements or compound statements or empty statements.
Next-statement is a valid C statement.
Whenever nested if…else statement is encountered, first <condition1> is tested. It returns
either true or false.
If condition1 (or outer condition) is false, then the control transfers to else-body (if exists) by
skipping if-body.
If condition1 (or outer condition) is true, then condition2 (or inner condition) is tested. If the
condition2 is true, if-body gets executed. Otherwise, the else-body that is inside of if statement gets
executed.
Interview question #1
What is dangling else problem?
Dangling else problem is an ambiguous situation in which one can not judge the else statement to
which if statement it belongs to. E.g., in the above syntax, we can not judge the else statement
whether it belongs to outer if statement or inner if statement.
In order to solve this problem, it is better to include the outer-if-body in curly braces. Hence,
the above syntax can be redefined as:
if(<condition1>) if(<condition1>)
{ {
if(<condition2>) if(<condition2>)
if-body if-body
} else //inner else
else //outer else else-body
else-body }
next-statement else
else-body
next-statement
60
The flow of control using nested if…else statement is determined as follows:
Program #5
Write a program to find biggest of three numbers
/* A program to find biggest, sum and average of three numbers*/
#include<stdio.h> #include<stdio.h>
main() main()
{ {
int a,b,c,big,sum; int a,b,c,big,sum;
float avg; float avg;
printf(“\n Enter any three numbers:”); printf(“\n Enter any three numbers:”);
scanf(“%d%d%d”,&a,&b,&c); scanf(“%d%d%d”,&a,&b,&c);
if(a>b) if(a>b && a>c)
{ big=a;
if(a>c) if(b>a && b>c)
big=a; big=b;
} if(c>a && c>b)
else big=c;
{ sum=a+b+c;
if(b>c) avg=sum/3.0;
big=b; printf(“\n Biggest number=%d”,big);
else printf(“\n Sum=%d”,sum);
big=c; printf(“\n Average=%f”,avg);
} }
sum=a+b+c;
avg=sum/3.0;
printf(“\n Biggest number=%d”,big);
printf(“\n Sum=%d”,sum);
printf(“\n Average=%f”,avg);
}
Run:
Enter any three numbers: 34 54 23
Biggest number=54
61
Program #6
Write a program to print eligibility for voting
/* A program to print eligibility for voting*/
#include<stdio.h>
main()
{
int age;
char sex;
printf(“\n Enter age and sex:”);
scanf(“%d\n%c”,&age,&sex);
if(sex==’m’||sex==’M’||sex==’f’||sex==’F’)
{
if(age>=18)
printf(“\n You are eligible for voting”);
else
printf(“\n Sorry, you are not eligible for voting”);
}
else
printf(“\n You are eligible for special type of voting”);
}
Run:
Enter age and sex:
23
K
You are eligible for special type of voting
In this syntax,
if and else are keywords. There should be a space between else and if, if they come together.
62
<condition1>,<condition2>….<condtionN> are relational expressions or logical expressions or any
other expressions that return either true or false. It is important to note that the condition should
be enclosed within parentheses ( and ).
If-body, else-if-body1,else-if-body2….else-if-bodyN, and else-body are either simple statements or
compound statements or null statements.
Next-statement is a valid C statement.
Whenever else if ladder is encountered, condition1 is tested first. If it is true, the if-body gets
executed. After then the control transfers to next-statement.
If condition1 is false, then condition2 is tested. If condition2 is false, the other conditions are
tested. If all are false, the else-body at the end gets executed. After then the control transfers to next-
statement.
If any one of all conditions is true, then the body associated with it gets executed. After then
the control transfers to next-statement.
The flow control using else if ladder is determined as follows:
63
Program #7
Write a program to find biggest of 6 numbers
/* A program to find biggest of 6 numbers*/
#include<stdio.h>
main()
{
int a,b,c,d,e,f,big;
printf(“\n Enter any 6 numbers:”);
scanf(“%d%d%d%d%d%d”,&a,&b,&c,&d,&e,&f);
if(a>b && a>c && a>d && a>e && a>f)
big=a;
else if(b>c && b>d && b>e && b>f)
big=b;
else if(c>d && c>e && c>f)
big=c;
else if(d>e && d>f)
big=d;
else if(e>f)
big=e;
else
big=f;
printf(“\n Biggest number=%d”,big);
}
Run:
Enter any 6 numbers: 23 54 2 435 32 87
Biggest number=435
Program #8
Write a program to print the type of character that is being input
/* A program to print the type of character that is being input*/
#include<stdio.h>
main()
{
char ch;
printf(“\n Enter any character:”);
scanf(“\n%c”,&ch);
if(ch>=’A’ &&ch<=’Z’)
printf(“\n You entered Upper case alphabet”);
else if(ch>=’a’ && ch<=’z’)
printf(“\n You entered lower case alphabet”);
else if(ch>=’0’ && ch<=’9’)
printf(“\n You entered a digit”);
else if(ch==’ ’ || ch==’\n’ || ch==’\t’)
printf(“\n You entered a white space character”);
else
printf(“\n You entered a special symbol”);
}
Run:
Enter any character:
*
You entered a special symbol
64
6.2.2. switch statement
switch statement is one of decision-making control-flow statements. Just like else if ladder, it is also used
to make a decision among multiple choices. switch statement has the following form:
switch(<exp>)
{
case <exp-val-1>: statements block-1
break;
case <exp-val-2>: statements block-2
break;
case <exp-val-3>: statements block-3
break;
:
:
case <exp-val-N>: statements block-N
break;
default: default statements block
}
Next-statement
In this syntax,
switch, case, default and break are keywords.
<exp> is any expression that should give an integer value or character value. In other words, it
should never return any floating-point value. It should always be enclosed with in parentheses (
and ). It should also be placed after the keyword switch.
<exp-val-1>, <exp-val-2>, <exp-val-3>…. <exp-val-N> should always be integer constants or
character constants or constant expressions. In other words, variables can never be used as <exp-
val>. There should be a space between the keyword case and <exp-val>. The keyword case along
with its <exp-val> is called as a case label. <exp-val> should always be unique; no duplications
are allowed.
Statements block-1, statements-block-2, statements block-3… statements block-N and default
statements block are simple statements, compound statements or null statements. It is important
to note that the statements blocks along with their own case labels should be separated with a
colon ( : ).
The break statement at the end of each statements block is an optional one. It is recommended
that break statement always be placed at the end of each statements block. With its absence, all
the statements blocks below the matched case label along with statements block of matched case
get executed. Usually, the result is unwanted.
The statement block and break statement can be enclosed with in a pair of curly braces { and }.
The default along with its statements block is an optional one. The break statement can be placed
at the end of default statements block. The default statements block can be placed at any where in
the switch statement. If they placed at any other places other than at end, it is compulsory to
include a break statement at the end of default statements block.
65
Next-statement is a valid C statement.
Whenever, switch statement is encountered, first the value of <exp> gets matched with case
values. If suitable match is found, the statements block related to that matched case gets executed. The
break statement at the end transfers the control to the Next-statement.
If suitable match is not found, the default statements block gets executed. After then the control
gets transferred to Next-statement.
The flow of control using switch statement is determined as follows:
Program #9
Write a program to check whether given alphabet is vowel or consonant
/* A program to check whether given alphabet is vowel or consonant*/
#include<stdio.h>
#include<ctype.h>
main()
{
char alpha;
printf(“\n Enter any alphabet:”);
scanf(“\n%c”,&alpha);
switch(tolower(alpha))
{
case ‘a’:
case ‘e’:
case ‘i’:
case ‘o’:
case ‘u’: printf(“\n Given alphabet is vowel:”); break;
default: printf(“\n Given alphbet is consonant”);
}
}
Run:
Enter any alphabet: z 66
Given alphabet is consonant
Program #10
Write a program to calculate areas of different shapes (square, rectangle, circle, triangle
(base & height) and triangle with 3 sides
/* A program to calculate areas of different shapes*/
#include<stdio.h>
# define PI 3.14.12
main()
{
int s,l,b,h,r,choice,a,c;
float area;
printf(“\n1.Square\n2.Rectangle\n3.Circle\n4.Triangle(base & height)\n5.Triangle(3 sides)”);
printf(“\n Enter your choice”);
scanf(“%d”,&choice);
switch(choice)
{
case 1: printf(“\n Enter side value:”);
scanf(“%d”,&s);
area=s*s;
break;
case 2: printf(“\n Enter length and breadth values:”);
scanf(“%d%d”,&l,&b);
area=l*b;
break;
case 3: printf(“\n Enter radius value:”);
scanf(“%d”,&r);
area=PI*r*r;
break;
case 4: printf(“\n Enter base and height values:”);
scanf(“%d%d”,&b,&h);
area=b*h;
break;
case 5: printf(“\n Enter 3 sides value:”);
scanf(“%d%d%d”,&a,&b,&c);
s=(a+b+c)/2;
area=sqrt(s*s-a*s-b*s-c);
break;
default: printf(“\n Wrong choice”);
}
printf(“\n Area=%f”,area);
}
Run:
1.Square
2.Rectangle
3.Circle
4.Triangle (base & height)
5.Triangle (3 sides)
Enter your choice: 1
Enter side value:4
Area=16.000000
67
Program #11
Write a program to perform basic arithmetic operations
/* A program to perform basic arithmetic operations*/
#include<stdio.h>
main()
{
int a,b,result;
char op;
printf(“\n Enter any two numbers:”);
scanf(“%d%d”,&a,&b);
printf(“\n Enter any arithmetic operator (+,-,*,/,%):”);
scanf(“\n%c”,&op);
switch(op)
{
case ‘+’: result=a+b;
break;
case ‘-’: result=a-b;
break;
case ‘*’: result=a*b;
break;
case ‘/’: result=a/b;
break;
case ‘%’: result=a%b;
break;
default: printf(“\n Invalid arithmetic operator”);
}
printf(“\n Result=%d”,result);
}
Run:
Enter any 2 numbers: 23 54
Enter any arithmetic operator (+, -, *, /, %):
/
Result=0
6.3. Conclusion
A control flow statement is a statement that is needed when we want to transfer control as we needed.
Each control statement has its own property. Based on that property, the control gets transferred. The
conditional control statement causes the execution of one or more statements based on particular
condition. Looping control statement causes the repeated execution of one or more statements as long as
the condition is satisfied. The jumping control flow statement transfers the control to the specified position
without the need of satisfying the condition. These jumping control-flow statements transfer the control
unconditionally.
68
1)#include<stdio.h> 3)#include<stdio.h> 6)#include<stdio.h>
main() main() main()
{ { {
int a=300,b=10,c=20; int x=10; if(‘Z’<’z’)
if(!(a>=400)) if x>=2 printf(“\n Hello”);
b=300; printf(“%d”,x); else
c=200; } printf(“\n Hi”);
printf(“%d\t%d”,b,c); }
} 4)#include<stdio.h>
main() 7)#include<stdio.h>
2)#include<stdio.h> {
main() main()
if(!3.14) {
{ printf(“\n IAS”);
int a=300,b=10,c=20; float a=12.25,b=13.65;
else if(a=b)
if(!a>=400) printf(“\n IPS); }
b=300; printf(“\nequal”);
c=200; else
5)#include<stdio.h> printf(“\n not equal”);
printf(“%d\t%d”,b,c);
main() }
OBSERVABLE }
{
O
int x=10,y=100%90; 8)#include<stdio.h>
9)#include<stdio.h>
if(x!=y); main()
main()
printf(“x=%d\ty=%d”,x,y); {
{
U
} float a=0.7;
float a=12.36;
if(a==12.36) if(a<0.7)
printf(“\nequal”); printf(“\nstoned”);
T
else 14)#include<stdio.h> else
printf(“\n not equal”); main() printf(“\n Avenged”);
} { }
P
int k=-2,j=4;
10)#include<stdio.h> switch(k/=j/k) 12)#include<stdio.h>
main() { main()
default: {
U
{
int x=100; printf(“beautiful”); int x=10,y=20;
if(!!x) case 0: if(!(!x)&&x)
printf(“x=%d”,!x); printf(“Handsome”); printf(“%d”,x);
T else
printf(“x=%d”,x);
case 1:
printf(“Smart”);
case 2:
else
printf(“%d”,y);
}
}
printf(“pretty”);
} 13)#include<stdio.h>
11)#include<stdio.h>
} main()
main()
{ {
float a=0.5,b=0.9; int i=400*400/400;
if(a&&b>0.9) if(i==400)
printf(“Master”); printf(“Delhi”);
else else
printf(“Minister”); printf(“Dubai”);
} }
69
1)#include<stdio.h> 2)#include<stdio.h> 3)#include<stdio.h>
main() main() main()
{ { {
int i; char s=3; int i=3;
printf(“Enter any num:”); switch(s) switch(i)
scanf(“%d”,&i); { {
OBSERVABLE switch(i) case ‘1’: case 1:
{ printf(“one\n”); printf(“Moon”);
O case 1:
printf(“Sa”);
case 2:
case ‘2’:
printf(“two\n”);
break;
case 2:
printf(“Sky”);
break;
U
printf(“Ri”); default: case 3:
case 3: printf(“Three”); continue;
printf(“Ga”); } default:
T
case default: printf(“Civil”); printf(“stars….”);
printf(“pa”); } }
} }
P
}
U
T
1) Rewrite the following set of statements using conditional operator:
int a=1,b;
if(a>10)
Q b=20;
70
/* A program to check whether three given /* A program to check type of triangle based
numbers are pythagorean triplets or not*/ on 3 given sides*/
#include<stdio.h> #include<stdio.h>
main() main()
{ {
int a,b,c; int a,b,c;
printf(“\n Enter any three numbers:”); printf(“\n Enter 3 sides values:”);
scanf(“%d%d%d”,&a,&b,&c); scanf(“%d%d%d”,&a,&b,&c);
if(a<b && a<c) if(a==b&&a==c)
{ printf(“\n Equilateral triangle”);
if(c*c==a*a+b*b) else if (a==b||b==c||a==c)
printf(“\n A Pythagorean triplet”); printf(“\n Isosceles triangle”);
else else
printf(“\n Not a Pythagorean triplet”); printf(“\n Scalane triangle”);
} }
else
printf(“\n Not a Pythagorean triplet”);
}
71
Control-flow Statements–II
7
(Looping control statements)
Chapter Outline
“I can't change the direction of the wind, but I
can adjust my sails to always reach my 7.1. Introduction.
destination.” –Jimmy Dean 7.2. Looping control-flow
statements.
7.2.1. while
statement.
7.2.2. for statement.
7.2.3. do-while
“Men, like nails, lose their usefulness when they statement.
lose direction and begin to bend.”
7.3. Jumping control-flow
–Walter Savage Landor
statements.
7.3.1. break
statement.
7.3.2. continue
statement.
7.3.3. goto statement.
“The means to gain happiness is to throw out from
oneself like a spider in all directions an adhesive 7.4. Additional topics.
web of love, and to catch in it all that comes” 7.5. Conclusion
-Leo Nikolaevich Tolstoy
72
7.1. Introduction
A Looping control-flow statement is a control-flow statement that allows the repeated execution of a
group of statements, as long as the specified condition is satisfied. A looping control statement is also
called as an iterative control statement or repetitive control statement.
Loop is the repeated execution of a group of statements (or loop body), as long as specified condition is
satisfied. At some stage, the condition should be dissatisfied. Then only, the loop gets terminated or
ended. Otherwise, the loop becomes indefinite.
Loop counter is a variable that controls the iterations of a loop. Usually, it holds a sequence of values
that are of incremented or decremented. If it holds all the incremented values starting from initial value,
then it is incremented loop counter. If it holds all the decremented values starting from initial value, then
it is decremented loop counter.
Each of these looping control statements should consist of following three essential statements for efficient
looping mechanism:
Initialization statement: This statement is used to set the initial value to the loop counter.
Condition: This statement is used to determine whether the group of statements is to be executed
or not. Usually, a condition is formed with the help of loop counter and its end value.
Updating statement: This statement is used to increment or decrement or change the value of
the loop counter.
Interview question #1
Which
looping control flow statement is better when one wants to use as a loop ?
o The for statement is the best way to perform an operation a set number of times.
o The while statement is the best way to perform a loop until a particular condition occurs.
o The do-while statement is useful if you want to perform a loop at least once.
73
7.2.1. while statement
It is one of the looping control-flow statements. It is also called as entry-controlled looping control-flow
statement. i.e., it tests the condition before entering into the loop body. The syntax for “while” statement
is as follows:
Initialization statement
while(<condition>)
while-body
next_statement
In this syntax,
while is the keyword. <condition> is a relational expression or a compound relational expression or any
expression that returns either true or false. initialization statement, while-body and next_statement
are valid ‘c’ statements. The while-body may be a simple statement, compound statement or null
statement. The updating statement should be included with in the while loop body.
Whenever “while” statement is encountered, the initialization statement gets executed first.
After then, the condition will be tested.
If the condition returns the value true, the control enters into the while loop body and all the
statements in that body will be executed. When the end of the body is reached, the condition is tested
again with the updated loop counter value. If the condition returns the value true, the above said process
will be repeated.
If the condition returns the value false, the control transfers to next_statement with out
executing while loop body.
Initialization statement
74
Program #1
Write a program to calculate sum of n natural numbers using while loop
/* 1+2+3+………….+n*/
#include<stdio.h>
main(void)
{
int i,sum,n;
printf(“\n Enter how many numbers sum do you want:”);
scanf(“%d”,&n);
i=1; /*initialization statement*/
sum=0;
while(i<=n) /*i<=n is the condition to be satisfied*/
{
sum=sum+i;
i=i+1; /*Updating statement*/
}
printf(“\n Sum of %d natural numbers=%d”,n,sum);
}
Run:
Enter how many numbers sum do you want:
5
Sum of 5 natural numbers=15
Program #2
Write a program to print mirror image of a number and check whether given number is
palindrome or not
/*A program to print mirror image of a number and check whether given number is palindrome or
not*/
#include<stdio.h>
main(void)
{
int num,rev,num1;
printf(“\n Enter any number:”);
scanf(“%d”,&num);
num1=num;
rev=0;
while(num>0)
{
rem=num%10;
rev=rev*10+rem;
num=num/10;
}
printf(“\n Mirror image=%d”,rev);
if(rev==num1)
printf(“\n%d is a palindrome”,num1);
else
printf(“\n%d is not a palindrome”,num1);
}
Run:
Enter any number:
12321
Mirror image=12321
12321 is a palindrome
75
7.2.2. for statement
It is one of the looping control statements. It is also called as entry-controlled looping control statement.
i.e., it tests the condition before entering into the loop body. The syntax for “for” statement is as follows:
for(exp1;exp2;exp3)
for-body
next_statement;
In this syntax,
for is a keyword. exp1 is the initialization statement. If there is more than one statement, then
those should be separated with commas. exp2 is the condition. It is a relational expression or a
compound relational expression or any expression that returns either true or false. The exp3 is the
updating statement. If there is more than one statement, then those should be separated with
commas. exp1, exp2 and exp3 should be separated with two semi-colons. exp1, exp2, exp3,
for-body and next_statement are valid ‘c’ statements. for-body is a simple statement or
compound statement or a null statement.
Whenever “for” statement is encountered, first exp1 gets executed. After then, exp2 is tested. If
it returns the value true, the control enters into for loop body. When the end of the body is reached, exp3
is executed. Again, exp2 is tested. If the exp2 returns the value true, the above said procedure will be
repeated.
If exp2 is false, the control transfers to next_statement with out executing the for loop
body.
exp1
false true
exp2
exp3
Next_statement
76
Program #3
Write a program to calculate sum of n natural numbers using for loop
/* 1+2+3+………….+n*/
#include<stdio.h>
main(void)
{
int i,sum,n;
printf(“\n Enter how many numbers sum do you want:”);
scanf(“%d”,&n);
for(i=1,sum=0;i<=n;i++)
sum=sum+i;
printf(“\n Sum of %d natural numbers=%d”,n,sum);
}
Run:
Enter how many numbers sum do you want:
5
Sum of 5 natural numbers=15
Program #4
Write a program to print prime numbers upto N
/* A program to print prime numbers upto N*/
#include<stdio.h>
main(void)
{
int N,fcount,n1,i;
printf(“\n Enter maximum value:”);
scanf(“%d”,&N);
for(n1=2;n1<=N;n1++)
{
fcount=0;
i=1;
while(i<=n1)
{
if(n%i==0)
fcount++;
i++;
}
if(fcount==2)
printf(“%d\t”,n1);
}
}
Run:
Enter maximum value: 100
2 3 5 7 11 13 17 19 23 29
31 37 41 43 47 53 59 61 67 71
73 79 83 89 97
77
7.2.3. do-while statement
It is one of the looping control statements. It is also called as exit-controlled looping control statement.
i.e., it tests the condition after executing the do-while loop body.
The main difference between “while” and “do-while” is that in “do-while” statement, the loop body gets
executed at least once, though the condition returns the value false for the first time, which is not
possible with while statement. In “while” statement, the control enters into the loop body when only the
condition returns true.
Initialization statement;
do
{
statement(s);
} while(<condition>);
next_statement;
In this syntax,
While and do are the keywords. <condition> is a relational expression or a compound relational
expression or any expression that returns either true or false. initialization statement,
statement(s) and next_statement are valid ‘c’ statements. The statements with in the curly
braces are called as do-while loop body. The updating statement should be included with in the do-
while loop body. There should be a semi-colon (;) at the end of while(<condition>).
Whenever “do-while” statement is encountered, the initialization statement gets executed first.
After then, the control enters into do-while loop body and all the statements in that body will be executed.
When the end of the body is reached, the condition is tested again with the updated loop counter value.
If the condition returns the value false, the control transfers to next_statement with out
executing do-while loop body. Hence, it states that, the do-while loop body gets executed for the first
time, though the condition returns the value false.
If the condition returns the value true, the control enters into do-while body and all the statements
in that body will be executed. When the end of the body is reached, the condition is tested again with the
updated counter value. If the condition returns the value true, the above said procedure will be repeated.
78
Initialization statement
false true
condition
Next_statement
Program #3
Write a program to calculate sum of n natural numbers using do-while loop
/* 1+2+3+………….+n*/
#include<stdio.h>
main(void)
{
int i,sum,n;
printf(“\n Enter how many numbers sum do you want:”);
scanf(“%d”,&n);
i=1;
sum=0;
do
{
sum=sum+i;
i=i+1;
}
printf(“\n Sum of %d natural numbers=%d”,n,sum);
}
Run:
Enter how many numbers sum do you want:
5
Sum of 5 natural numbers=15
Interview question #2
What are the differences between while and do-while statements?
while do-while
1) It is an entry-controlled control-flow 1) It is an exit-controlled control-flow
statement. That is, it tests condition before the statement. That is, it tests condition after the
body gets executed. body gets executed.
2) The body gets executed only when the 2) The body gets executed at least once though
condition is true. the condition is false for the first time.
79
7.3. Jumping control-flow statements
A Jumping control-flow statements are the control-flow statements that transfer the control to the
specified location or out of the loop or to the beginning of the loop. There are 3 jumping control
statements:
break;
In this syntax, break is the keyword. The following diagram shows the transfer of control when break
statement is used:
Any loop
{
statement_1;
statement_2;
:
break;
:
}
next_statement
Interview question #3
What are the differences between break and exit() statements?
break exit()
1) It is used to come out of loop or switch or 1) It is used to come out of entire program.
block in which it is placed.
2) It is a keyword. Its definition has already 2) It is a pre-defined function that is available in
defined by language developers. process.h or stdlib.h header files. It takes an
argument: 0 or 1. exit(0) means a clean exit
80without an error message. exit(1) means an
abrupt exit with an error message.
Program #4
Write a program to count the positive, negative and zero values
/* A program to count the positive, negative and zeros*/
#include<stdio.h>
main()
{
char ch;
int n,pc,nc,zc;
pc=nc=zc=0;
while(1)
{
printf(“\n Enter any number (+ve,-ve or zero):”);
scanf(“%d”,&n);
if(n>0)
pc++;
else if(n<0)
nc++;
else
zc++;
printf(“\n Do you want to continue (y/n):”);
ch=getchar();
if((ch=getchar())==’n’)
break;
}
printf(“\n No.of positive numbers=%d”,pc);
printf(“\n No.of negative numbers=%d”,nc);
printf(“\n No.of zeros=%d”,zc);
}
Run:
Enter any number (+ve,-ve or zero):23
Do you want to continue (y/n): y
Enter any number (+ve,-ve or zero):0
Do you want to continue (y/n): y
Enter any number (+ve,-ve or zero):-1
Do you want to continue (y/n): n
No.of positive numbers=1
No.of negative numbers=1
No.of zeros=1
continue;
where continue is the keyword. The following diagram shows the transfer of control when continue
statement is used:
81
Any loop
{
statement_1;
statement_2;
:
continue;
:
}
next_statement
Program #5
Write a program to find the sum of the series 5 2+102+152+202+… upto n terms
/*program to find sum of series 5*5+10*10+15*15+20*20+… upto n terms*/
#include<stdio.h>
main()
{
int i,sum=0,n;
printf(“\n Enter upto which value do u want sum:”);
scanf(“%d”,&n);
for(i=5;i<=n;i++)
{
if(i%5!=0)
continue;
sum=sum+i*i;
}
printf(“\n Sum=%d”,sum);
}
Run:
Enter upto which value do u want sum: 50
Sum=9625
break vs continue: The following example clears the flow of control when using both of these:
#include<stdio.h> #include<stdio.h>
main() main()
{ {
int i=0; int i=0;
while(i<10) while(i<10)
{ {
i++; i++;
if(i==5) if(i==5)
break; continue;
printf(“%3d”,i); printf(“%3d”,i);
} }
} }
Output: 1 2 3 4 Output: 1 2 3 4 6 7 8 9 10
82
Labeled statement: A statement that is preceded by a label along with a colon is known as a labeled
statement. The label must be a valid identifier. The correct way to use it is:
<any_label>: <statement>;
In this syntax, goto is the keyword and label is any valid identifier and should be ended with a colon (:).
The identifier following goto is a statement label and need not be declared. The name of the statement or
label can also be used as a variable name in the same program if it is declared appropriately. The compiler
identifies the name as a label if it appears in a goto statement and as a variable if it appears in an
expression.
If the block of statements that has label appears before the goto statement, then the control has to
move to backward and that goto is called as backward goto. If the block of statements that has label
appears after the goto statement, then the control has to move to forward and that goto is called as
forward goto.
Interview question #4
When
does the goto statement is used compulsary? Why should we avoid the use of goto
statement?
goto
statement is the best option when one wants the control jumps from inner most loop to outer
loop at once.
most
goto
statement causes the loss of sequentiality in order of execution of instructions. Often, this leads
usto difficulty in understanding the program. Hence, it is suggested that one should avoid the use of
goto statement.
83
Ex:
/*program to read a string using goto*/ /*program to generate 4 perfect numbers*/
#include<stdio.h> #include<stdio.h>
main() main()
{ {
char ch; int n,i,sum=0,count=0;
printf(“\n Enter any string:\n”); for(n=4;;n++)
read: ch=getchar(); {
if(ch!=’\n’) sum=0;
{ for(i=1;i<=n/2;i++)
putchar(ch); {
goto read; if((n%i)==0)
}
Output: Enter any string: sum=sum+i;
Output:
} Pradeep Kumar } 6
Pradeep Kumar if(sum==n) 28
{ 496
printf(“%d\n”,sum); 8128
count++;
if(count==4)
goto end;
}
}
end: ; /*null statement*/
}
printf(“%3d”,j); 123
printf(“\n”); 1234
} 12345
84
7.4.3. Conditional Branching vs Unconditional Branching:
When a program breaks the sequential flow and jumps to the new section of code, it is called branching.
When this branching is based on a condition, the program is performing conditional branching. When no
condition is involved and the program always branches when it encounters a particular branching
instruction, the program is performing unconditional branching.
Unconditional Branching occurs when a program branches to a new location in the code with out
analyzing the data and making a decision using condition. Conditional branching occurs when the program
branches based on a decision of some type.
Ex: Conditional branching statement: if… else
Unconditional branching statement: goto
7.5. Conclusion
When a group of statements are to be executed repeatedly, we use looping control flow statements. These
looping control-flow statements help us to reduce number of lines of code, a program has. Whenever we
want to skip execution of a group of statements, we use jumping control flow statements.
85
1. point out the error, if any, in the for loop?
main()
{
int i=1;
for(;;)
{
Q printf(“%d”,i++);
if(i>10)
break;
U }
}
E A. The condition in the for loop is a must.
B. The two semicolons should be dropped.
C. The for loop should be replaced by a while loop.
S D. No error.
U
} main() main()
{ {
2)#include<stdio.h> int a; int a=5;
T main()
{
for(a=1;a<=32767;a++)
printf(“%d”,a);
do
{
int j=1; } printf(“%d\n”,a);
P while(j<=255);
{ 5)#include<stdio.h>
a=-1;
}while(a>0);
U
printf(“%c%d\n”,j.j); main() }
j=j+1; {
} int i;
T
} for(i=1;i++<=5;printf(“%d”,i));
}
86
/* A program to print fibonacci series using /*A program to print floyd’s triangle*/
do-while loop*/ #include<stdio.h>
#include<stdio.h> main()
main() {
{ int n,i,j,k;
int a,b,c,n; printf("\n Enter number of rows:");
printf(“\n Enter n value:”); scanf("%d",&n);
scanf(“%d”,&n); k=1;
a=0; for(i=1;i<=n;i++)
b=1; {
printf(“%d\t%d”,a,b); for(j=1;j<=i;j++)
do printf("%d\t",k++);
{ printf("\n");
c=a+b; }
printf(“\t%d”,c);
a=b; }
b=c;
}while(c<=n);
}
/* A program to calculate GCD and LCM of /* A program to calculate x^y*/
two numbers*/ #include<stdio.h>
#include<stdio.h> main()
main() {
{ int x,y,i;
int num1,num2,gcd,lcm,rem,n1,n2; long int prod;
printf("\n Enter two numbers:"); printf("\n Enter base and exponent value:");
scanf("%d%d",&num1,&num2); scanf("%d%d",&x,&y);
n1=num1,n2=num2; prod=1;
rem=num1%num2; for(i=1;i<=y;i++)
while(rem!=0) prod=prod*x;
{ printf("\n Result=%ld",prod);
num1=num2; }
num2=rem;
rem=num1%num2;
}
gcd=num2;
lcm=(n1*n2)/gcd;
printf("\n LCM=%d\nGCD=%d",lcm,gcd);
}
/*A program to convert decimal number to /*A program to print pyramid of digits*/
binary*/ #include<stdio.h>
#include<stdio.h> main()
main() {
{ int n,i,j,k,digit;
int i=1,rem,bin=0,dec; printf("\n Enter n value:");
printf("Enter the decimal Value" ); scanf("%d",&n);
scanf("%d",&dec); for(i=1;i<=n;i++)
while(dec!=0) {
{ for(j=1;j<=n-i;j++)
rem=dec%2; printf(" ");
dec=dec/2; digit=i;
bin=bin+(i * rem); for(k=1;k<=i;k++)
i=i*10; printf("%4d",digit++);
digit=digit-2;
} for(k=1;k<i;k++)
printf("The Binary value is %d",bin); printf("%4d",digit--);
87
} printf("\n");
}
}
/*A program to print pascal’s triangle*/ /* A program to print all prime factors
#include<stdio.h> of a number*/
main() # include<stdio.h>
{ main()
int n,j,m,i,k; {
printf("\n Enter number of rows:"); int num,fact,fcount,i,k;
scanf("%d",&n); printf(“\n Enter any number:”);
for(j=0;j<n;j++) scanf(“%d”,&num);
{ for(i=2;i<=num;i++)
for(k=35-2*j;k>0;k--) {
printf(" "); if(num%i==0)
for(m=0;m<=j;m++) fact=i;
{ fcount=0;
if(m==0||j==0) for(k=1;k<=fact;k++)
i=1; {
else if(fact%k==0)
fcount++;
i=(i*(j-m+1))/m; }
printf("%4d",i); if(fcount==2)
printf(“%d\t”,fact);
} }
printf("\n"); }
}
} /*A program to find sum of even and odd
/*A program to print number in words*/ numbers of unspecified count of given
#include<stdio.h> numbers*/
main() #include<stdio.h>
{ main()
long int num,rev; {
int rem; int esum,osum;
printf(“\n Enter any number:”); esum=osum=0;
scanf(“%ld”,&num); printf(“\n Enter numbers (-999 to end):”);
rev=0; do
while(num>0) {
{ rem=num%10; scanf(“%d”,&num);
rev=rev*10+rem; if(num==-999)
num=num/10; goto here;
} if(num%2==0 )
while(rev>0) esum=esum+num;
{ rem=rev%10; else
switch(rem) osum=osum+num;
{ here:;
case 0: printf(“ZERO”); break; }while(num!=-999);
case 1: printf(“ONE”); break;
case 2: printf(“TWO”); break; printf(“\n Even sum=%d”,esum);
case 3: printf(“THREE”); break; printf(“\n Odd sum=%d”,osum);
case 4: printf(“FOUR”); break; }
case 5: printf(“FIVE”); break;
case 6: printf(“SIX”); break;
case 7: printf(“SEVEN”); break;
case 8: printf(“EIGHT”); break;
case 9: printf(“NINE”); break;
88
}
printf(“ “);
rev=rev/10;
}
}
89
Functions 8
Chapter Outline
“The function of prayer is not to influence God,
but rather to change the nature of the one who 8.1. Introduction.
prays.” -Soren Kierkegaard 8.2. Advantages of
functions.
8.3. Types of functions.
8.3.1. Predefined
functions
8.3.2. User-defined
“The most important function of education at functions.
any level is to develop the personality of the
8.4. parameter passing
individual and the significance of his life to
himself and to others” -Grayson Kirk mechanisms
8.5. Scope and extent of
variables.
8.5.1. Storage classes
8.6. Recursion.
“The function of genius is not to give new
answers, but to pose new questions - which time 8.7. Conclusion.
and mediocrity can solve.” -Hugh Trevor-Roper
90
8.1. Introduction
A function is a named, independent section of C code that performs a specific task and
optionally returns a value to the calling program.
In other words, a function is an independent, special and named collection of instructions that is
used to achieve the desired result. E.g., sqrt() is function which has the purpose of returning
the square root of a number.
91
8.2. Advantages of functions
Supports structured programming: By using functions in our C programs, we can
practice structured programming, in which individual program tasks are performed by
independent sections of program code. It's easier to write a structured program, because
complex programming problems are broken into a number of smaller, simpler tasks. Each
task is performed by a function. It's easier to debug a structured program.
Reusability: Writing functions avoids rewriting the same code over and over. Suppose we
have a section of code in our program that calculates area of a triangle. If later in the
program we want to calculate the area of a different triangle, we won’t like it if we are
required to write the same instructions all over again. Instead, we would prefer to jump to
a ‘section of code’ that calculates area and then jumps back to the place from where we
left off. This section of code is nothing but a function.
92
Program #1
Write a program to calculate xy using predefined function
/*program to calculate x^y using pre-defined function*/
# include<stdio.h>
#include<math.h>
main()
{
double x,y,ans;
printf(“\n Enter any two numbers:”);
scanf(“%lf%lf”,&x,&y);
ans=pow(x,y);
printf(“\n power of x raised to y=%lf”,ans);
}
Output:
Enter any two numbers: 2
5
power of x raised to y=32.000000
94
Mathematical Functions (Prototypes) <math.h>
long double pow(long double base, long double exponent);
---Returns base raised to the power exponent: baseexponent
Ex: long double x=pow(32.01,1.54); x=208.036691
long double sqrt(long double x);
---Returns square root of x
Ex: long double x=sqrt(1024); x=32.000000
long double exp(long double x);
--- Returns the base-e exponential function of x, which is
the e number raised to the power x.
Ex: long double x=exp(5); x= 148. 413159
long double log(long double x);
--- Returns the natural logarithm of x
Ex: long double x=log(5.5); x= 1.704748
long double log10(long double x);
--- Returns the common logarithm (base 10) of x
Ex: long double x=log10(1000); x= 3.000000
long double ceil(long double x);
--- Returns the smallest integral value that is not less than x.
Ex: long double x=ceil(3.8); x= 4.000000
long double floor(long double x);
--- Returns the largest integral value that is not greater than x.
Ex: long double x=floor(3.8); x= 3.000000
long abs(long x);
--- Returns the absolute value of x.
Ex: long x=abs(-23); x= 23
long double sin(long double x);
long double cos(long double x);
long double tan(long double x);
long double asin(long double x);
long double acos(long double x);
long double atan(long double x);
long double sinh(long double x);
long double cosh(long double x);
long double tanh(long double x);
---Returns the values of different trigonometric functions
Ex: long double x=sin(30*3.1412/180); x=0.500000
long double x=cos(60*3.1412/180); x=0.500000
long double x=tan(45*3.1412/180); x=1.000000
long double x=asin(0.5*180/3.1412); x=30.000000
long double x=acos(0.5*180/3.1412); x=60.000000
long double x=atan(1.0*180/3.1412); x=45.000000
http://pradeeppearlz.blogspot.com 95 Functions
8.3.2. User-defined functions:
These are the functions defined by the user for fulfilling his desired objective. Usually,
these are self-contained blocks of code that perform coherent tasks that are same as pre-
defined functions.
Whenever the user wants to define a function he should keep these things in mind:
First, he should decide the objective of the function. In other words, he should decide the
purpose of function for which it is being developed.
Second, he should develop the function prototype that tells the compiler the name of
the function, types of arguments to that function and return type of that function. Usually,
it has the following form:
<return_type> <function_name>(<data type1>,<datatype2>….<datatypeN>);
In this syntax,
<return_type> and <data type1><data type2>…<datatypeN> are any one of valid
pre-defined data types such as int, float, double, char and void (or) any derived data types
such as long int, short int…etc (or) any user defined data types such as array (not used as
return type), pointer, struct…etc.
<function_name> is any valid identifier. Usually, it is named based on the purpose of
function.
Ex: The user wants to calculate a number rose to power of another number. In other words, if x
and y are two numbers, then he wants to find xy using functions. Then his function prototype
may be as one of these:
int powXY(int,int); /*function with arguments and return value*/
int powXY(void); /*function without arguments but with return value*/
void powXY(int,int); /*function with arguments and without return value*/
void powXY(void); /*function without arguments and without return value*/
http://pradeeppearlz.blogspot.com 96 Functions
A function definition describes what a function does. It consists of a function header and a
function body.
a) The function header consists of:
<return_type> specifies the data type of the value returned by the function. It may
be of any data type other than array and function types. If <return type> is omitted, the
value returned is assumed to be an int type by default. The data type void is specified in
the place of <return_type> if the function returns no value.
function_name is any valid identifier. But, it should not used as name for a variable,
a constant or any other program element.
<arg1>,<arg2>…<argn> are known as formal arguments or formal parameters.
Each parameter must be preceded by its data type. If there is more than one parameter,
then those should be separated with commas. For parameterless functions, the keyword
void is placed within the parentheses following function_name.
b) The function body is also known as a compound statement or a block. All valid C
statements can take part in this function body. In addition to these, two more statements
may take part: function calls and return statement.
A return Statement is a statement that is used to transfer control to the calling
function along with returned value, if any. This statement should be used in the
definition of function, if the function returns value to the calling function. This
statement consists of the keyword return followed by an expression (or) a value with
in optional parentheses.
Ex: These are valid return statements
return; /*Transfers only control to the calling function*/
return 10; /*Transfers control as well as 10 to the calling function*/
return (a+b*c-d); /*the expression is evaluated and the result gets transferred along with
control to the calling function*/
97
Note:
1) Multiple return statements can be used.
/* conversion of upper case letter to lower case letter*/
2) A function can return only one value at a time. Thus, the following statements are
invalid.
return ( a, b ) ;
return ( x, 12 ) ;
3) The return value should match with the <return_type> as in function header.
Otherwise, the value will be converted according to the <return_type> and the
converted value gets returned to the calling function.
Ex: Possible function definitions for the function powXY()
With arguments and with return value Without arguments and with return value
int powXY(int x,int y) int powXY(void)
{ {
int i,product; int x,y,i,product;
product=1; printf(“Enter x,y values:”);
for(i=1;i<=y;i++) scanf(“%d%d”,&x,&y);
product=product*x; product=1;
return (product); for(i=1;i<=y;i++)
} product=product*x;
return (product);
}
With arguments and without return value Without arguments and with out return value
void powXY(int x,int y) void powXY(void)
{ {
int i,product; int x,y,i,product;
product=1; printf(“Enter x,y values:”);
for(i=1;i<=y;i++) scanf(“%d%d”,&x,&y);
product=product*x; product=1;
printf(“Answer=%d”,product); for(i=1;i<=y;i++)
} product=product*x;
printf(“Answer=%d”,product);
}
98
Finally, he should utilize the defined function by calling it from another function or in it.
For this purpose, function call statement (callable statement) is helpful.
A function call is a statement that is used to invoke (or call) a function that is defined
by the user or pre-defined function. A function can call itself or can be called from any other
function. It can be called many times. Even, main() can be called from other functions. A
function call has the following form:
<function_name>(<e1>,<e2>,<e3>…<eN>);
In this syntax,
<function_name> is any existing name of the function that needs to be called.
<e1>,<e2>…<eN> are called as actual arguments or actual parameters.
If there are no arguments, then the parentheses should be left as empty. If there is
any return value that a function returns, then that value will be hold by a variable using
assignment statement (or) that function call can be used as a part of expression as an
operand.
Ex: Possible function calls for the function powXY() from main()
With arguments and with return value Without arguments and with return value
#include<stdio.h> #include<stdio.h>
main() main()
{ {
int a,b,ans; int ans;
printf(“\n Enter any two values:”); ans=powXY(); /*function call*/
scanf(“%d%d”,&a,&b); printf(“\n Answer=%d”,ans);
ans=powXY(a,b); /*function call*/ }
printf(“\n Answer=%d”,ans);
}
With arguments and without return value Without arguments and with out return value
#include<stdio.h> #include<stdio.h>
main() main()
{ {
int a,b; powXY(); /*function call*/
printf(“\n Enter any two values:”); }
scanf(“%d%d”,&a,&b);
powXY(a,b); /*function call*/
}
Hence, we can say that a user can define and utilize a function to achieve his desired objective in any one
of the following ways:
99
With arguments and with Without arguments and with With arguments and without Without arguments and
return value return value return value without return value
#include<stdio.h> #include<stdio.h> #include<stdio.h> #include<stdio.h>
int powXY(int,int); int powXY(void); void powXY(int,int); void powXY();
main() main() main() main()
{ { { {
int a,b,ans; int ans; int a,b; powXY(); /*function call*/
printf(“\n Enter any two ans=powXY(); /*function printf(“\n Enter any two }
values:”); call*/ values:”);
void powXY(void)
scanf(“%d%d”,&a,&b); printf(“\n Answer=%d”,ans); scanf(“%d%d”,&a,&b);
{
ans=powXY(a,b); /*function } powXY(a,b); /*function call*/
int x,y,i,product;
call*/ }
int powXY(void) printf(“Enter x,y values:”);
printf(“\n Answer=%d”,ans);
{ void powXY(int x,int y) scanf(“%d%d”,&x,&y);
}
int x,y,i,product; { product=1;
int powXY(int x,int y) printf(“Enter x,y values:”); int i,product; for(i=1;i<=y;i++)
{ scanf(“%d%d”,&x,&y); product=1; product=product*x;
int i,product; product=1; for(i=1;i<=y;i++) printf(“Answer=%d”,product);
product=1; for(i=1;i<=y;i++) product=product*x; }
for(i=1;i<=y;i++) product=product*x; printf(“Answer=%d”,product);
product=product*x; return (product); }
Output:
return (product); }
Output: Enter x,y values:
}
Output: Enter any two values: 2
Output: Enter x,y values: 2 5
Enter any two values: 2 5 Answer=32
2 5 Answer=32
5 Answer=32
Answer=32
Points to ponder: 1) A function can be called multiple times. Even, the function main() can also be called from other functions.
2) A function’s definition can never be placed in another function’s definition.
3) A function can return only one value at a time to the calling function.
Few points about main(): 1) main() is the user-defined function.
2) main() is invoked or called by operating system and the return value from is returned to operating system.
3) By default, main() function as well as other user-defined functions return an integer value.
100
From the above example, it is clear that there are four types of user-defined functions:
1. Function with arguments and with return value.
2. Function with arguments and without return value.
3. Function without arguments and with return value.
4. Function without arguments and without return value.
Function with arguments and with return value Function with arguments and without return value
Control transfer Control transfer
Calling function Called function Calling function Called function
main() int powXY(int x,int y) main() void powXY(int x,int y)
{ { { {
int x,y,ans;
Arguments
int i,product; int x,y; int i,product;
Arguments
printf(“\n Enter any product=1; printf(“\n Enter any product=1;
two numbers:”); for(i=1;i<=y;i++) two numbers:”); for(i=1;i<=y;i++)
scanf(“%d%d”,&x,&y); product=product*x; scanf(“%d%d”,&x,&y); product=product*x;
ans=powXY(x,y); powXY(x,y);
return (product); printf(“\n
printf(“\n Return value }
} Answer=%d”,product);
Answer=%d”, ans);
} }
Control transfer Control transfer
Function without arguments and with return value Function without arguments and without return value
Control transfer
Control transfer
Calling function Called function
Calling function Called function
main() int powXY(void)
main() void powXY(void)
{ {
{ {
int ans; int i,x,y,product;
ans=powXY(); printf(“\n Enter two
powXY(); int i,x,y,product;
printf(“\n } printf(“\n Enter two
numbers:”);
Answer=%d”,ans); scanf(“%d%d”,&x,&y); numbers:”);
} scanf(“%d%d”,&x,&y);
Return value product=1;
for(i=1;i<=y;i++) product=1;
product=product*x; for(i=1;i<=y;i++)
Control transfer return product; product=product*x;
} Control transfer printf(“\n
Answer=%d”,product);
}
101
Example programs:
/* Program to find the roots of a /*program to print prime factors of a
quadratic equation*/ number*/
#include<stdio.h>
#include<stdio.h> int isPrime(int);
void quadroots(int,int,int);/function prototype void factors(int);
main() main()
{ {
int a,b,c; int n;
printf(“\n Enter values of a,b,c”); printf(“\n Enter any number:”);
scanf(“%d%d%d”,&a,&b,&c); scanf(“%d”,&n);
quadroots(a,b,c); //function call factors(n);
} }
//function definition void factors(int n)
void quadroots(int a,int b,int c) {
{ int i,r;
int desc; printf(“\n Prime factors:”);
float root1,root2,r1,r2; for(i=1;i<=n;i++)
if(a==0) {
{ if(n%i==0)
printf(“\n given equation is not quadratic”); r=isPrime(i);
root1=-c/b; if(r==1)
printf(“\n Root1=%f”,root1); printf(“\n%d”,i);
} }
else
{ }
desc=b*b-4*a*c; int isPrime(int n)
if(desc==0) {
{ int i,fcount;
printf(“\n roots are real and equal”); fcount=0;
root1=root2=-b/(float)2*a; for(i=1;i<=n;i++)
printf(“root1=%f\nroot2=%f”,root1,root2); {
} if(n%i==0)
else if(desc>0) fcount++;
{ }
printf(“\n roots are real and unequal”); if(fcount==2)
root1=(-b+sqrt(desc))/(2*a); return 1;
root2=(-b-sqrt(desc))/(2*a); else
printf(“root1=%f\nroot2=%f”,root1,root2); return 0;
} }
else
{
printf(“\n roots are complex”);
r1=-b/(float)(2*a);
r2=sqrt(-desc)/(2*a);
printf(“root1=%.2f+i%.2f”,r1,r2);
printf(“root2=%.2f-i%.2f”,r1,r2);
}
}
}
102
8.4. Parameter passing mechanisms (or) passing arguments to a
function
A function can be called by passing arguments (or inputs or parameters) to it from another
function. This process is called as parameter passing mechanism.
There are two parameter passing mechanisms:
1. call by value (or) pass by value
2. call by reference / address (or) pass by reference / address
In call by value method, the arguments are normal values. In call by reference method, the
arguments are the addresses or references.
To pass arguments to a function, we list them in parentheses following the function name.
The number of arguments and the type of each argument must match the parameters in the
function header and prototype. For example, if a function is defined to take two type int
arguments, we must pass it exactly two int arguments—no more, no less--and no other type. If
we try to pass a function an incorrect number and/or type of argument, the compiler will detect
it, based on the information in the function prototype.
If the function takes multiple arguments, the arguments listed in the function call are
assigned to the function parameters in order: the first argument to the first parameter, the
second argument to the second parameter, and so on. Each argument can be any valid C
expression: a constant, a variable, a mathematical or logical expression, or even another
function (one with a return value). For example, if half(), square(), and third() are all functions
with return values, we could write
x = half(third(square(half(y))));
The program first calls half(), passing it y as an argument. When execution returns from half(),
the program calls square(), passing half()'s return value as an argument. Next, third() is called
with square()'s return value as the argument. Then, half() is called again, this time with third()'s
return value as an argument. Finally, half()'s return value is assigned to the variable x. The
following is an equivalent piece of code:
a = half(y);
b = square(a);
c = third(b);
x = half(c);
103
While passing arguments, we can observe that there are basically two types of functions: calling
function, called function.
Calling function: It is a function that calls another function or itself.
Called function: It is a function that is being called from another function.
8.4.1. Call by value
In this method, the values will be passed to called function from calling function. The values
passed are called as “actual arguments”. In the header of called function definition, there will be
arguments that hold the passed values. These arguments are called as “formal arguments”.
Whenever a function is called from another function using call by value method, the actual
arguments are copied into formal arguments. Then the called function gets executed with those
copied values. After completion, the control returns to calling function with return value, if any.
Ex: The following program demonstrates the call by value method.
/*program to convert lowercase to uppercase*/
#include<stdio.h>
char toUpperCase(char);
main()
{
char alphabet,upper;
printf(“\n Enter any lowercase alphabet:”);
scanf(“\n%c”,&alphabet);
upper=toUpperCase(alphabet); /*call by value – actual argument: alphabet*/
printf(“\n Uppercase alphabet:%c”,upper);
}
char toUpperCase(char ch) /*formal argument: ch*/
{
if(ch>=’a’ && ch<=’z’)
ch=ch-32;
return ch;
}
In this program, main() is the calling function and toUpperCase() is called function. The
toUpperCase() function is called with one actual argument from main(). The actual argument is
copied into formal argument. The conversion process is carried out with copied value. After then,
the converted character is returned to main(), the calling function. The main(), the calling
function, holds the value and prints that value.
8.4.2. Call by reference
In this method, the addresses will be passed to called function from calling function. Hence, the
actual arguments are addresses. That is, the variables that are preceded by reference operator
(&). The formal arguments in function header are pointers. That is, the variables that are
preceded by de-reference operator (*). This method is very useful in such a situation where the
called function wants to change the calling function’s arguments.
104
The following program demonstrates call by reference method.
/*progam to swap two numbers using /*progam to swap two numbers using
call by value method*/ call by reference method*/
#include<stdio.h> #include<stdio.h>
void swap(int,int); void swap(int*,int*);
main() main()
{ {
int a,b; int a,b;
printf(“\n Enter any two numbers:”); printf(“\n Enter any two numbers:”);
scanf(“%d%d”,&a,&b); scanf(“%d%d”,&a,&b);
printf(“\n Before swap a=%d \t b=%d”,a,b); printf(“\n Before swap a=%d \t b=%d”,a,b);
swap(a,b); swap(&a,&b);
printf(“\n After swap a=%d \t b=%d”,a,b); printf(“\n After swap a=%d \t b=%d”,a,b);
} }
void swap(int x,int y) void swap(int *x,int *y)
{ {
int temp; int temp;
temp=x; temp=*x;
x=y; *x=*y;
y=temp; *y=temp;
} }
Output: Enter any two numbers: 10 20
Output: Enter any two numbers: 10 20
Before swap a=10 b=20
Before swap a=10 b=20
After swap a=10 b=20
After swap a=20 b=10
Actual arguments: Normal values Actual arguments: addresses
Formal arguments: Normal variables Formal arguments: pointers
The changes in formal arguments are not The changes in formal arguments are
reflected in actual arguments. reflected in actual arguments.
The longevity or lifetime or extent of a variable refers to the duration for which the variable retains a
given value during the execution of a program.
The same variable name may appear in different scopes. It is the duty of the compiler to decide whether
the different occurrences of the variable refer to the same variable or not.
105
Block Scope: A variable is said to have block scope, if it is recognised only with in the block where it is
declared.
The following example demonstrates this concept:
#include<stdio.h>
main()
{
{/*Block-1*/
int a;
a=10;
printf("%d\t%d",a,b);
}
{/*Block-2*/
int b;
b=20;
printf("%d\t%d",a,b);
}
}
Whenever we execute this program, we get an error because we are trying to utilize the variables that are
out of block scope. In this program, we observe that there are two blocks. In block-1, the variable ‘a’ is
declared and initialized. In block-2, the variable ‘b’ is declared and initialized. In block-1, undoubtedly, we
can access the value of ‘a’. But, we can’t access the value of ‘b’ that is declared in block-2. Since, b is not
declared and initialized in block-1, b is out of scope. The variable ‘b’ is available only in the block-2.
Hence, we get an error like ‘b undeclared’. The same happens with the variable ‘a’ in block-2.
Local Scope: A variable is said to have local scope or function scope, if it is recognised only with
in the function where it is declared. The following example demonstrates this concept:
#include<stdio.h>
void fun(void);
main() //function-1
{
int a;
a=10;
printf("a=%d\tb=%d",a,b);
fun();
}
void fun() //function-2
{
int b;
b=20;
printf("a=%d\tb=%d",a,b);
}
Whenever we execute this program, we get an error because we are trying to utilize the variables that are
out of function scope. In this program, we observe that there are two functions. In function-1, the variable
‘a’ is declared and initialized. In function-2, the variable ‘b’ is declared and initialized. In function-1,
undoubtedly, we can access the value of ‘a’. But, we can’t access the value of ‘b’ that is declared in
function-2. Since, b is not declared and initialized in function-1, b is out of scope. The variable ‘b’ is
available only in the function-2. Hence, we get an error like ‘b undeclared’. The same happens with the
variable ‘a’ in function-2.
106
Global Scope: A variable is said to have global scope or file scope, if it is recognised with in blocks and
all the functions defined in a program. A global variable can be declared outside of all functions with in a
file. The following example demonstrates the concept of global variable:
#include<stdio.h>
void fun(void);
int c=30; //global variable
int d; //global variable
main()
{
int a;
a=10;
d=40;
printf("\n With in main()");
printf("\n Local variable a=%d",a);
printf("\n Global variables c=%d\td=%d",c,d);
fun();
}
void fun()
{
int b;
b=20;
d=60;
printf("\n With in fun()");
printf("\n Local variable b=%d",b);
printf("\n Global variables c=%d\td=%d",c,d);
}
In this example, the variables ‘c’ and ‘d’ are global variables. These variables can be available in both
functions. We can assign different values to same global variable in different functions. The value that is
assigned locally in the function only gets accessed.
The life time of a variable is best demonstrated with the following example:
#include<stdio.h>
main()
{
int i;
for(i=1;i<=4;i++)
{
int y=20;
printf("\ny is %d",y);
y=100;
printf("\ny is now %d",y);
}
}
In this program, it is clear that the variable y in loop is alive until the iteration is completed. In the first
iteration, the variable y is initialized with the value 20. Later it is changed to 100. After completion of first
iteration, agian the value of y gets initialized with 20. Hence, the old value is unchanged until first
iteration is completed. Hence, the life time of variable y is upto the iteration only.
107
8.5.1. Storage classes
Variables in C differ in behavior. The behavior depends on the storage class a variable may
assume. From C compiler’s point of view, a variable name identifies some physical location
within the computer where the string of bits representing the variable’s value is stored. There
are basically two kinds of locations in a computer where such a value may be kept— Memory
and CPU registers. It is the variable’s storage class that determines in which of these two
locations the value is stored.
Storage Memory.
Default initial value An unpredictable value, which is often called a garbage value.
Life Till the control remains within the block in which the variable is defined.
108
Following program shows how an automatic storage class variable is declared, and the fact that if the
variable is not initialized it contains a garbage value.
main( )
{
auto int i, j ;
printf ( "\n%d %d", i, j ) ;
}
When you run this program you may get different values, since garbage values are unpredictable. So
always make it a point that you initialize the automatic variables properly, otherwise you are likely to get
unexpected results. Scope and life of an automatic variable is illustrated in the following program.
main( )
{
auto int i = 1 ;
{
auto int i = 2 ;
{
auto int i = 3 ;
printf ( "\n%d ", i ) ;
}
printf ( "%d ", i ) ;
}
printf ( "%d", i ) ;
}
Note that the Compiler treats the three i’s as totally different variables, since they are defined in different
blocks. It means the scope of i is local to the block in which it is defined. The moment the control comes
out of the block in which the variable is defined, the variable and its value is irretrievably lost. Once the
control comes out of the innermost block the variable i with value 3 is lost, and hence the i in the second
printf( ) refers to i with value 2. Similarly, when the control comes out of the next innermost block, the
third printf( ) refers to the i with value 1.
Default initial value An unpredictable value, which is often called a garbage value.
Life Till the control remains within the block in which the variable is defined.
109
A value stored in a CPU register can always be accessed faster than the one that is stored in memory.
Therefore, if a variable is used at many places in a program it is better to declare its storage class as
register. A good example of frequently used variables is loop counters. We can name their storage class as
register.
main( )
{
register int i ;
for ( i = 1 ; i <= 10 ; i++ )
printf ( "\n%d", i ) ;
}
Here, even though we have declared the storage class of i as register, we cannot say for sure that the
value of i would be stored in a CPU register. Why? Because the number of CPU registers are limited, and
they may be busy doing some other task. What happens in such an event is the variable works as if its
storage class is auto.
For example, if the microprocessor has 16-bit registers then they cannot hold a float value or a double
value, which require 4 and 8 bytes respectively. However, if you use the register storage class for a float
or a double variable you won’t get any error messages. All that would happen is that the compiler would
treat the variables to be of auto storage class.
The features of a variable defined to have a static storage class are as under:
Storage Memory.
110
The programs above consist of two functions main( ) and increment( ). The function increment( ) gets
called from main( ) thrice. Each time it increments the value of i and prints it. The only difference in the
two programs is that one uses an auto storage class for variable i, whereas the other uses static storage
class.
Like auto variables, static variables are also local to the block in which they are declared. The difference
between them is that static variables don’t disappear when the function is no longer active. Their values
persist. If the control comes back to the same function again the static variables have the same values
they had last time around.
In the above example, when variable i is auto, each time increment( ) is called it is re-initialized to one.
When the function terminates, i vanishes and its new value of 2 is lost. The result: no matter how many
times we call increment( ), i is initialized to 1 every time.
On the other hand, if i is static, it is initialized to 1 only once. It is never initialized again. During the first
call to increment( ), i is incremented to 2. Because i is static, this value persists. The next time
increment( ) is called, i is not re-initialized to 1; on the contrary its old value 2 is still available. This
current value of i (i.e. 2) gets printed and then i = i + 1 adds 1 to i to get a value of 3. When
increment( ) is called the third time, the current value of i (i.e. 3) gets printed and once again i is
incremented. In short, if the storage class is static then the statement static int i = 1 is executed only
once, irrespective of how many times the same function is called.
111
4) External Storage Class
The features of a variable whose storage class has been defined as external are as follows:
Storage Memory.
Scope Global.
External variables differ from those we have already discussed in that their scope is global, not local.
External variables are declared outside all functions, yet are available to all functions that care to use
them. Here is an example to illustrate this fact.
int i ;
main( )
{
printf ( "\ni = %d", i ) ;
increment( ) ;
increment( ) ;
decrement( ) ;
decrement( ) ;
}
increment( )
{
i=i+1;
printf ( "\non incrementing i = %d", i ) ;
}
decrement( )
{
i=i-1;
printf ( "\non decrementing i = %d", i ) ;
}
The output would be:
i=0
on incrementing i = 1
on incrementing i = 2
on decrementing i = 1
on decrementing i = 0
As is obvious from the above output, the value of i is available to the functions increment( ) and
decrement( ) since i has been declared outside all functions.
int x = 21 ;
main( )
{
112
extern int y ;
printf ( "\n%d %d", x, y ) ;
}
int y = 31 ;
Here, x and y both are global variables. Since both of them have been defined outside all the functions
both enjoy external storage class. Note the difference between the following:
extern int y ;
int y = 31 ;
Here the first statement is a declaration, whereas the second is the definition. When we declare a variable
no space is reserved for it, whereas, when we define it space gets reserved for it in memory. We had to
declare y since it is being used in printf( ) before it’s definition is encountered. There was no need to
declare x since its definition is done before its usage. Also remember that a variable can be declared
several times but can be defined only once.
int x = 10 ;
main( )
{
int x = 20 ;
printf ( "\n%d", x ) ;
As is obvious from the above output, the value of i is available to the functions increment( ) and
decrement( ) since i has been declared outside all functions.
int x = 21 ;
main( )
{
extern int y ;
printf ( "\n%d %d", x, y ) ;
}
int y = 31 ;
Here, x and y both are global variables. Since both of them have been defined outside all the functions
both enjoy external storage class. Note the difference between the following:
extern int y ;
int y = 31 ;
113
Here the first statement is a declaration, whereas the second is the definition. When we declare a variable
no space is reserved for it, whereas, when we define it space gets reserved for it in memory. We had to
declare y since it is being used in printf( ) before it’s definition is encountered. There was no need to
declare x since its definition is done before its usage. Also remember that a variable can be declared
several times but can be defined only once.
int x = 10 ;
main( )
{
int x = 20 ;
printf ( "\n%d", x ) ;
display( ) ;
}
display( )
{
printf ( "\n%d", x ) ;
}
Here x is defined at two places, once outside main( ) and once inside it. When the control reaches the
printf( ) in main( ) which x gets printed? Whenever such a conflict arises, it’s the local variable that gets
preference over the global variable. Hence the printf( ) outputs 20. When display( ) is called and control
reaches the printf( ) there is no such conflict. Hence this time the value of the global x, i.e. 10 gets
printed.
One last thing—a static variable can also be declared outside all the functions. For all practical purposes it
will be treated as an extern variable. However, the scope of this variable is limited to the same file in
which it is declared. This means that the variable would not be available to any function that is defined in
a file other than the file in which the variable is defined.
Dennis Ritchie has made available to the C programmer a number of storage classes with varying
features, believing that the programmer is in a best position to decide which one of these storage classes
is to be used when. We can make a few ground rules for usage of different storage classes in different
programming situations with a view to:
114
Use static storage class only if you want the value of a variable to persist between different
function calls.
Use register storage class for only those variables that are being used very often in a program.
Reason is, there are very few CPU registers at our disposal and many of them might be busy doing
something else. Make careful utilization of the scarce resources. A typical application of register
storage class is loop counters, which get used a number of times in a program.
Use extern storage class for only those variables that are being used by almost all the functions in
the program. This would avoid unnecessary passing of these variables as arguments when making
a function call. Declaring all the variables as extern would amount to a lot of wastage of memory
space because these variables would remain active throughout the life of the program.
If we don’t have any of the express needs mentioned above, then use the auto storage class. In
fact most of the times we end up using the auto variables, because often it so happens that once
we have used the variables in a function we don’t mind loosing them.
8.6. Recursion
Recursion is a process by which a function calls itself repeatedly, until some specified
condition has been satisfied.
void g()
{
f();
}
Recursion is just a loop; however, it has one difference from other loops. With recursion, each
time a recursive function is called, a new set of variables is created. This is not true of the other
loops
When a function calls itself, a new set of local variables and parameters are allocated
storage on the stack, and the function code is executed from the top with these new variables. A
recursive call does not make a new copy of the function. Only the values being operated upon
are new. As each recursive call returns, the old local variables and parameters are removed from
the stack, and execution resumes immediately after the recursive call inside the function.
115
The main advantage to recursive functions is that we can use them to create clearer and
simpler versions of several programs.
When writing a recursive function, we should follow these rules:
Recursion rule #1: Every recursive method must have a base case -- a condition under which no
recursive call is made -- to prevent infinite recursion.
When writing recursive functions, we must have a conditional statement, such as an if,
somewhere to force the function to return without the recursive call being executed. If we don't,
the function will never return once we call it. Omitting the conditional statement is a common
error when writing recursive functions.
Recursion rule #2: Every recursive method must make progress toward the base case to prevent
infinite recursion.
When writing recursive functions, we must write a recursive case in which there should be a call
to same function.
Ex: Suppose we want to calculate the factorial value of an integer. As we know, the factorial of a number
is the product of all the integers between 1 and that number. For example, 4 factorial is 4 * 3 * 2 * 1.
This can also be expressed as 4! = 4 * 3!, where ‘!’ stands for factorial. Thus factorial of a number can be
expressed in the form of itself. Hence this can be programmed using recursion.
Program #2
Write a program to calculate factorial of a number
/* program to calculate factorial of a /* program to calculate factorial of a
number in iterative approach*/ number using recursion*/
#include<stdio.h> #include<stdio.h>
main() int fact(int);
{ main()
int n,fact,i; {
printf(“\n Enter any number:”); int n,f;
scanf(“%d”,&n); printf(“\n Enter any number:”);
for(i=1,fact=1;i<=n;i++) scanf(“%d”,&n);
fact=fact*i; f=fact(n);
printf(“\n Factorial of %d is %d”,n,fact); printf(“\n Factorial of %d is %d”,n,f);
} }
int fact(int n)
{
int f;
if(n==0||n==1) //base case
f=1;
else
f=n*fact(n-1); //recursive case
return f;
}
Output:
Enter any number: 5
Factorial of 5 is 120
116
Let us see how the recursion works. Assume n=5. since the value of n is not 1 or 0, the
statement will be executed with n=5. That is,
f=5*fact(4);
will be evaluated. The expression on the right hand side includes the call to fact() with n=4.
This call, fact(4), will return this value: 4*fact(3). Like this, the sequence of operations can be
summarized as follows:
f=5*fact(4);
=5*4*fact(3);
=5*4*3*fact(2);
=5*4*3*2*fact(1);
=5*4*3*2*1
=120
When this recursive program is executed, the recursive function calls are not executed
immediately. Rather, these are placed on a stack until the condition terminates the recursion is
encountered. The function calls are then executed in reverse order, as they are deleted from the
stack. Thus, when evaluating a factorial recursively, the function calls will proceed in the
following order:
fact(1)
2*fact(1)
3*fact(2)
4*fact(3)
5*fact(4)
117
/*A program to calculate sum of n natural /*A program to calculate sum of n natural
numbers using iterative approach*/ numbers using recursive approach*/
#include<stdio.h> #include<stdio.h>
main() int sumNatural(int);
{ main()
int n,sum,i; {
printf(“\n Enter n value:”); int n,s;
scanf(“%d”,&n); printf(“\n Enter n value:”);
for(i=1,sum=0;i<=n;i++) scanf(“%d”,&n);
sum=sum+i; s=sumNatural(n);
printf(“\n Sum of %d numbers=%d”,n,sum); printf(“\n Sum of %d numbers=%d”,n,s);
} }
int sumNatural(int n)
{
int sum;
if(n==0)
sum=0; //base case
else
sum=sum+sumNatural(n-1); //recursive case
return sum;
}
/*A program to calculate sum of digits of a /*A program to calculate sum of digits of a
number using iterative approach*/ number using recursive approach*/
#include<stdio.h> #include<stdio.h>
main() int sumDigits(int);
{ main()
int num,sum,r; {
printf(“\n Enter any number:”); int num,s;
scanf(“%d”,&num); printf("\n Enter any number:");
sum=0; scanf("%d",&num);
while(num>0) s=sumDigits(num);
{ printf("\n Sum of digits=%d",s);
r=num%10; }
sum=sum+r; int sumDigits(int n)
num=num/10; {
} if(n==0)
printf(“\n Sum of digits=%d”,sum); return 0;
} else
return (n%10)+sumDigits(n/10);
}
118
/*A program to calculate GCD of two numbers /*A program to calculate GCD of two numbers
using iterative approach*/ using recursive approach*/
#include<stdio.h> #include<stdio.h>
int gcd(int,int); int gcd(int,int);
main() main()
{ {
int a,b; int a,b;
printf("\n Enter any two numbersx:"); printf("\n Enter any two numbers:");
scanf("%d%d",&a,&b); scanf("%d%d",&a,&b);
printf("\n GCD=%d",gcd(a,b)); printf("\nGCD=%d",gcd(a,b));
} }
int gcd(int a,int b) int gcd(int a,int b)
{ {
int t; if(b==0) //base case
if(a<b) return a;
{ else
t=a; return gcd(b,a%b); //recursive case
a=b; }
b=t;
}
while(1)
{
t=a%b;
if(t==0)
return b;
a=b;
}
}
/*A program print Fibonacci series using /*A program to calculate sum of digits of a
iterative approach*/ number using recursive approach*/
#include<stdio.h> #include<stdio.h>
int main() int fibrec(int);
{ int main()
int n,a,b,c,i; {
printf("\n Enter how many numbers:"); int n,i;
scanf("%d",&n); printf("\n Enter how many numbers:");
a=0; scanf("%d",&n);
b=1; printf("%d\t%d",0,1);
printf("%d\t%d",a,b); for(i=1;i<n-1;i++)
for(i=3;i<=n;i++) printf("\t%d",fibrec(i));
{ return 0;
c=a+b; }
printf("\t%d",c); int fibrec(int n)
a=b; {
b=c; int fib;
} if(n==0||n==1)
return 0; fib=1;
} else
fib=fibrec(n-1)+fibrec(n-2);
return fib;
}
119
Recursion vs Iteration
Similarities:
1. Both iteration and recursion are based on a control structure: Iteration uses a repetition structure;
recursion uses a selection structure.
2. Both iteration and recursion involve repetition: Iteration explicitly uses a repetition structure;
recursion achieves repetition through repeated function calls.
3. Iteration and recursion each involve a termination test: Iteration terminates when the loop-
continuation condition fails; recursion terminates when a base case is recognized.
4. Iteration and recursion can occur infinitely: An infinite loop occurs with iteration if the loop-
continuation test never becomes false; infinite recursion occurs if the recursion step does not
reduce the problem in a manner that converges on the base case.
Differences:
1. Recursive version of a program is slower than iterative version of a program due to overhead of
maintaining stack.
2. Recursive version of a program uses more memory (for the stack) than iterative version of a
program.
3. Some times, recursive version of a program is simpler to understand than iterative version of a
program.
120
1)#include<stdio.h> 4) #include<stdio.h> 7) #include<stdio.h>
void foo(void); main() main()
main() { {
{ int c; int i;
int a=10,b=20; printf("\n before call printf(“\n Helloooooo”);
goto here; c=%d",c); for(i=1;i<=10;i++)
} c=message(); main();
void foo() printf("\n after call }
{ c=%d",c);
here: printf(“%d%d”,a,b); } 8) #include<stdio.h>
} message() main()
{ {
2)#include<stdio.h>
printf("\n Live and let live"); if(printf(“Hello”))
main()
} main();
{
}
int i=45; 5) #include<stdio.h>
float c; main() 9) #include<stdio.h>
c=check(i); { main()
printf("\nc=%f",c); C() {
} { printf(“\n Mama”);
check(ch) c() message();
OBSERVABLE int ch; { }
{
O
printf("\n C is a sea"); message()
float x; } {
(ch>=45)? printf("....and......."); printf(“\n Chandamama”);
(x=35.4):(x=34.2); main();
U
}
return x; printf("\n Next what?"); }
} }
T
3)#include<stdio.h> 6) #include<stdio.h> 10) #include<stdio.h>
main() main() main()
{ { {
P
int area; int i=135,a=135,k; int k=35,z;
float radius=2.0; k=fun(!++i,!a++); k=fun1(k=fun1(k=fun1(k)));
area=areacircle(radius); printf("i=%d a=%d printf("k=%d",k);
U
printf("area=%d",area); k=%d",i,a,k); }
} } fun1(k)
areacircle(r) fun(j,b) int k;
float r;
T
int j,b; {
{ { k++;
float a; int c; return k;
a=3.14*r*r; c=j+b; }
printf("\na=%f",a); return c;
return (a); } 11) #include<stdio.h>
}
main()
13) #include<stdio.h>
{
#include<stdio.h>
int z=4;
main()
printf(“%d”,printf(“%dHello”,z));
{ int k=35,z;
}
z=fun1(k);
printf("%d",z);} 12) #include<stdio.h>
main()
fun1(int k) {
{ int p=k++; int z;
return k; printf(“%d”,scanf(“%d”,&z);
return 90;} }
121
Arrays-I
9
(Numeric Arrays)
Chapter Outline
“There are basically two types of people. People
who accomplish things and people who claim to 9.1. Introduction.
have accomplished things. The first group is less 9.2. Types of arrays.
crowded.” -Mark Twain
9.3. One-Dimensional
array.
9.4. Operations on one-
dimensional array.
9.5. Two-Dimensional
“We must remember that one determined array.
person can make a significant difference, and
9.6. Passing array as an
that a small group of determined people can
change the course of history.” -Sonia Johnson argument to a
function.
9.7. Conclusion.
122
9.1. Introduction
For understanding the concept of arrays, let us consider an example:
#include<stdio.h>
main()
{
int a;
a=10;
a=20;
a=30;
printf(“%d%d%d”,a,a,a);
}
This program prints the values 30, 30 and 30 instead of 10, 20 and 30. In this program, we can observe
that “a“ is a variable that holds only one value at a time. But, we require a special type of variable that
holds more than one value of same type at a time, referred by same name. Here, the concept of arrays
comes into picture.
Suppose, we wish to arrange the percentage marks obtained by 100 students in ascending order. In
such a case we have two options to store these marks in memory:
a) Construct 100 variables to store percentage marks obtained by 100 different students, i.e. each
variable containing one student’s marks.
b) Construct one variable (called array or subscripted variable) capable of storing or holding all the
hundred values.
Obviously, the second alternative is better. A simple reason for this is, it would be much easier to handle
one variable than handling 100 different variables.
Therefore,
Variables are like individual folders, whereas an array is like a single folder with many compartments.
As an array is collection of elements, the total count of elements in it should be specified with a non-
negative integer with in square brackets [], placed after the array name. E.g., a[10] is an array that has
the capability of holding 10 elements.
123
9.2. Types of arrays
Based on type of values being hold, arrays are broadly classified into two categories:
a) Numeric array: An array that consists of elements of numeric type; whether they are integers or
floating-point values.
b) Non-numeric array: An array that consists of elements of type char. These non-numeric arrays are
also called as strings.
An array’s name should be followed by square brackets. These square brackets are used to specify the
total number of elements present in that array. Based on number of square brackets (subscripts or
dimensions), arrays are broadly classified into two categories:
I. One-dimensional arrays.
II. Multi-dimensional arrays.
One-dimensional array consists of only one subscript. Multi-dimensional arrays consist of more than one
subscript. E.g., two-dimensional array consists of 2 subscripts; 3-dimensional array consists of 3
subscripts and so on. Usually, one-dimensional numeric array consists of numbers as individual elements
where as multi-dimensional numeric array consists of arrays as individual elements. Hence, multi-
dimensional array is also called as array of arrays.
124
9.3.2. Initializing one-dimensional array:
Initializing One-dimensional array is the process of assigning values to its all contiguous locations or to
some of them with some initial values for avoiding garbage values those are already in it. It can be
directly done with the help of assignment operator.
A one-dimensional array is initialized as follows: array declaration follows assignment operator and a list
of values that are separated by commas enclosed with in curly braces. This process is also called as
“initialization at compile-time”.
Ex: int a[7]={12,45,54,2,87,76,3};
Once the above array gets initialized, the memory map for it will be as follows:
From this memory map, we can observe that an array subscript value (or index) starts from 0 and ends
with n-1, where n is the size of the array. Usually, the first element’s location is called the base address of
the array. Each element is uniquely identified with the help of array name and its subscript value – 1 or
base address+ (pos-1) * sizeof(type). . e.g., 4 th element of array ‘a’ is identified with a[3] or 1000+(4-
1)*2=1006.
9.3.3. Reading and printing one-dimensional array:
A One-Dimensional array’s locations can be filled with input values from keyboard with the help of scanf()
statement. Because an array consists of more than one element, we should require a loop counter for
keeping track of index values. The loop counter is always an integer value that begins with 0 and ends
with n-1. The loop counter should be incremented by 1 for keeping track of next immediate indexes. For
each indexed element, scanf() statement expects an input value from programmer. This process can be
depicted with the help of the following statement:
for(i=0;i<n;i++) // i: loop counter
scanf(“%d”,&a[i]);
The above statement first reads a[0], then a[1], a[2], a[3]…and so on. This process is also called as
“initialization at run-time”.
Once an array is read, it can be accessed directly or sequentially with the help of printf()
statement. If we want an element at particular position, then we should give the following argument to
printf() : a[position-1]. E.g., we want the element at 5th position, then we should give a[4] to printf()
statement:
printf(“Element at 5th position is %d”,a[4]);
If we want to access all the elements in the array sequentially, then we can use printf() statement along
with a loop as follows:
printf(“\n The array elements are:”);
for(i=0;i<n;i++)
printf(“%d\t”,a[i]);
125
/*Program to calculate sum and average /*Program to calculate Biggest and
of n numbers*/ smallest of n numbers*/
#include<stdio.h> #include<stdio.h>
main() main()
{ {
int a[10],n,i; int a[10],n,i,big,small;
float avg,sum;
printf(“\n Enter the array size:”); printf(“\n Enter the array size:”);
scanf(“%d”,&n); scanf(“%d”,&n);
sum=0.0; printf(“\n Enter the array elements:”);
printf(“\n Enter the array elements:”); for(i=0;i<n;i++)
for(i=0;i<n;i++) scanf(“%d”,&a[i]);
{ big=small=a[0];
scanf(“%d”,&a[i]); for(i=1;i<n;i++)
sum=sum+a[i]; {
} if(a[i]>big)
printf(“\n Sum=%d”,sum); big=a[i];
avg=(float)sum/n; if(a[i]<small)
printf(“\n Average=%f”,avg); small=a[i];
} }
printf(“\n Biggest number=%d”,big);
printf(“\n Smallest number=%d”,small);
}
/*program to calculate mean, variance /*Program to calculate second Biggest
and standard deviation*/ and second smallest of n numbers*/
#include<stdio.h> #include<stdio.h>
#include<math.h> main()
main() {
{ int a[10],n,i,j,k,temp;
int a[10],n,i; printf(“\n Enter the array size:”);
float mean,sum,sumsq,std,variance; scanf(“%d”,&n);
printf(“\n Enter the array size:”); printf(“\n Enter the array elements:”);
scanf(“%d”,&n); for(i=0;i<n;i++)
sum=0.0; scanf(“%d”,&a[i]);
printf(“\n Enter the array elements:”); /*for removing duplicate elements*/
for(i=0;i<n;i++) for(i=0;i<n-1;i++){
{ for(j=i+1;j<n;j++){
scanf(“%d”,&a[i]); if(a[i]==a[j]){
sum=sum+a[i]; for(k=j;k<n-1;k++)
} a[k]=a[k+1];
mean=sum/(float)n; n=n-1;
j=j-1;
for(i=0,sumsq=0.0;i<n;i++) }
sumsq=sumsq+(mean-a[i])*(mean-a[i]); }
}
variance=sumsq/(float)n; /* sorting*/
std=sqrt(variance); for(i=0;i<n-1;i++)
printf(“\n Mean=%f”,mean); for(j=i+1;j<n;j++)
printf(“\n variance=%f”,variance); if(a[i]>a[j]){
printf(“\n standard deviation=%f”,std); temp=a[i];
} a[i]=a[j];
a[j]=temp;
}
printf(“\n Second biggest=%d”,a[n-2]);
printf(“\n Second smallest=%d”,a[1]);}
126
9.4. Operations on arrays
An array is an Abstract Data Type (ADT). An ADT is a collection of data and operations on that data. As an
ADT, the data an array includes is the collection of data items (integers, decimal points, characters or
strings). The operations on these data items include:
Traversing: Visiting each element at least once.
Reversing: Changing the positions of elements.
Insertion: Inserting a new data item into existing list of data items
Deletion: Deleting a data item from existing list of data items.
Searching: Searching for a particular data item in the list of data items.
Sorting: Arranging the list of data items in ascending order.
Merging: Combining sorted arrays into one sorted array.
Interview question #1
What is meant by bounds checking?
Bounds checking is the process of verifying whether the accessed array element is in bounds or not.
An array has two bounds: lower bound (0) and upper bound (n-1). While accessing an array, it is
important to access the elements only within bounds. Some language compilers check the bounds. If
we try access out of bounds, then there will be runtime errors. C compiler allows us to access elements
out of bounds, since there is no bounds checking concept in C. It is suggested that access each
element in an array within bounds.
127
9.4.2. Reversing an array
Reversing is the process of changing positions of elements in actual array to get reversed order of
elements. To reverse an array, we should interchange the elements a[0] with a[n-1], a[1] with a[n-2],
a[2] with a[n-3] and so on. For reversing the contents of an array, we use two loop counters; one for
keep tracking the values of 0,1,2…so on and the other for keep tracking the values of n-1, n-2,n-3… and
so on. By using these loop counters, we can interchange the elements.
10 9 12 76 45
10 9 12 76 45
2) Second, move all the elements to their next locations starting from 3 rd position until the end of array
is reached. This process is depicted as follows:
Iteration #1 10 9 12 76 45 45
Iteration #2 10 9 12 76 76 45
Iteration #3 10 9 12 12 76 45
10 9 89 12 76 45
129
9.4.4. Deleting an element from an array
Deletion is the process of removing an existing element from an array. The deletion process can best be
explained with the following example:
10 9 12 76 45
Iteration #1 10 9 76 76 45
Iteration #2 10 9 76 45 45
3) As the deletion of an element decreases the size of array, decrease the current length of array by1.
Hence the length of array now becomes 4. Now, the array looks like this:
10 9 76 45
130
9.4.5. Searching an element from an array
Searching is the process of finding location of an element in the given array. There are two basic methods
of locating an element:
1. Linear Search
2. Binary Search
Linear Search (or) Sequential Search:
This method works on the following principle: “ Compare each element of array with the element to be
searched. If suitable match is found, then return the position by leaving next comparisions; otherwise,
leave the proper message to the programmer after the end of the array gets reached.”
This method can best be explained with the following example:
Suppose that there is an array with the following memory map:
12 45 54 2 87 76 3
Let the element to be searched be 87. Then, Linear search works as follows:
87
87
87
87
131
87
Binary Search: When the input elements’ list is in sorted order, there is more efficient way to search
through it than looking at each element from beginning. This method is known as binary search.
The pre-requisite for binary search method is that the input elements’ list is in the sorted order.
The method starts with looking at the middle element of the list. If it matches with the search key, then
the search is completed. Otherwise, the search key may be in upper half or in lower half. The search
progresses through the upper half, if the search key is greater than the middle element or through the
lower half, if the search key is lesser than the middle element. The process is continued until the search
key is found or when the portion of the sub-list to be searched is empty.
This binary search method follows divide-and-conquer approach. By using this approach, the sorted
list will be divided into sub-lists. Each sub-list, in turn, will be divided into sub-lists till the search key is
found or there are no elements in the sub-list.
132
Ex: Let us consider an array (in sorted order) that consists of the following elements to search element
87:
Iteration #1
2 3 12 45 54 76 87 mid=(low+high)/2
=(0+6)/2
=3
low=0 mid=3 high=6
Since ele>a[mid], process right half. Then change low=mid+1 and calculate new middle position.
2 3 12 45 54 76 87
Iteration#2
mid=(low+high)/2
=(4+6)/2
low=4 high=6 =5
mid=5
Since ele>a[mid], process right half. Then change low=mid+1 and calculate new middle position.
low=6 Iteration#3
mid=(low+high)/2
=(6+6)/2
2 3 12 45 54 76 87 =6
mid=6 high=6
Since ele==a[mid], the element is found at mid+1 position. i.e., the element is found at 7 th position.
Iterative approach: The iterative approach progresses through by defining 3 variables: lower bound,
upper bound and middle position of search list that contain the search key.
If the search key and search list’s element are equal, then the search is completed and the middle
position will be taken into count.
If the search key is lesser than the middle element of array, then the search key must be in lower
half of that array. So, set the upper bound to one less than the middle position.
If the search key is greater than the middle element of array, then the search key must be in upper
half of that array. So, set the lower bound to middle position plus 1.
This iterative process stops when either 1) the search key is found or 2) the search sub-list becomes
empty.
133
The following program demonstrates iterative process of binary search:
#include<stdio.h>
main()
{
int a[10],n,low,high,mid,ele,pos,i,flag;
printf(“\n Enter the array size:”);
scanf(“%d”,&n);
printf(“\n Enter the array elements:”);
for(i=0;i<n;i++)
scanf(“%d”,&a[i]);
printf(“\n Enter the element to be searched:”);
scanf(“%d”,&ele);
low=0;
high=n-1;
flag=0;
while(low<=high)
{
mid=(low+high)/2;
if(ele= =a[mid])
{
flag=1;
pos=mid+1;
break;
}
else if(ele>a[mid])
low=mid+1;
else
high=mid-1;
}
if(flag= =1)
printf(“\n The element is found at %d position”,pos);
else
printf(“\n The element is not found”);
}
Recursive approach: The recursive approach of binary search procedure is relatively easy. It differs from
the iterative approach mainly in that it requires the upper bound and lower bound indices be passed as
arguments.
The recursive function determines whether the search key lies in the lower half or upper half of the
array, then calls itself on the appropriate half. The termination conditions or base cases are:
If low>high, then the partition (sub-list) to be searched has no elements in it and
If there is a match with the element in the middle of the current partition, then we can return that
middle position immediately.
There is no particular advantage in applying recursion in binary search of an array. In fact, from a
processing stand point, the iterative approach is likely to be more efficient.
134
The following program demonstrates the recursive approach of binary search:
#include<stdio.h>
int binarysearch(int[],int,int,int);
main()
{
int a[10],n,ele,pos,high;
printf(“\n Enter the array size:”);
scanf(“%d”,&n);
printf(“\n Enter the array elements:”);
for(i=0;i<n;i++)
scanf(“%d”,&a[i]);
printf(“\n Enter the element to be searched:”);
scanf(“%d”,&ele);
low=0;
high=n-1;
pos=binarysearch(a,ele,low,high);
if(pos<0)
printf(“\n The element is not found”);
else
printf(“\n The element is found at %d position”,pos+1);
}
int binarysearch(int a[],int ele,int low,int high)
{
int mid;
if(low>high)
return (-1);
mid=(low+high)/2;
if(ele= =a[mid])
return (mid);
else if(ele>a[mid])
binarysearch(a,ele,mid+1,high);
else
binarysearch(a,ele,low,mid-1);
}
Selection sort: Suppose an array A with N elements A[0], A[1]……..A[N-1] is in memory. Then in
selection sort, first find the smallest element in the list and put it in first position (i.e., at A[0]). Later, find
the second smallest element in the list and put it in second position (i.e., at A[1])…. and so on.
The selection sort method is carried out like this:
135
Pass 1: Find the location MINPOS the smallest element in the list of n elements:
A[0],A[1],A[2]…A[n-1]. After then, interchange A[MINPOS] and A[0]. Now,
observe that A[0] is sorted.
Pass 2: Find the location MINPOS of the smallest element in the sub-list of n-1 elements:
A[1],A[2],A[3]…A[n-1]. After then, interchange A[MINPOS] and A[1]. Now,
observe that A[0] and A[1] are sorted, since A[1]<=A[0].
Pass 3: Find the location MINPOS of the smallest element in the sub-list of n-2 elements:
A[1],A[2],A[3]…A[n-1]. After then, interchange A[MINPOS] and A[1]. Now,
observe that A[0] and A[1] are sorted, since A[1]<=A[0].
…….
…….
Pass n-1: Find the location MINPOS of the smaller of the elements A[n-2] and A[n-1]. After
then, interchange A[MINPOS] and A[n-2]. Now, observe that A[0], A[1],A[2]… A[n-
1] are sorted, since A[n-2]<=A[n-1].
Ex: suppose an array A consists of 8 elements as follows:
77 33 44 11 88 22 66 55
136
The following program demonstrates the selection sort technique:
#include<stdio.h>
main()
{
int a[10],i,j,temp,minpos,n;
printf("\n Enter the array size:");
scanf("%d",&n);
printf("\n Enter the array elements:");
for(i=0;i<n;i++)
scanf("%d",&a[i]);
for(i=0;i<n-1;i++)
{
minpos=i;
for(j=i+1;j<n;j++)
if(a[j]<a[minpos])
minpos=j;
if(minpos!=i)
{
temp=a[i];
a[i]=a[minpos];
a[minpos]=temp;
}
}
printf("\n Array elements after sorting (Selection sort):");
for(i=0;i<n;i++)
printf("%d\t",a[i]);
}
Bubble Sort: The bubble sort is the oldest and simplest sort in use. Unfortunately, it's also the slowest.
The bubble sort works by comparing each item in the list with the item next to it, and swapping them if
required. This process gets repeated until there is a pass all the way through the list without swapping any
items (in other words, all items are in the correct order). This causes larger values to "bubble" to the end
of the list while smaller values "sink" towards the beginning of the list. The following example best
explains the concept of bubble sort:
77 33 44 11 88 22 66 55
137
The following code demonstrates the bubble sort technique:
#include<stdio.h>
main()
{
int a[10],n,i,j,temp;
printf("\n Enter the array size:");
scanf("%d",&n);
printf("\n Enter the array elements:");
for(i=0;i<n;i++)
scanf("%d",&a[i]);
for(i=0;i<n;i++)
{
for(j=0;j<n-i-1;j++)
{
if(a[j]>a[j+1])
{
temp=a[j];
a[j]=a[j+1];
a[j+1]=temp;
}
}
}
printf("\n Array elements after sort (Bubble sort):");
for(i=0;i<n;i++)
printf("%d\t",a[i]);
}
Insertion sort: Suppose that there is an array A with N elements A[0], A[1], A[2]……..A[N-1]. The
insertion sort method scans A from A[0] to A[N-1], inserting each element A[k] into its proper position in
the previously sorted sub array A[0], A[1], A[2]…….A[k-1]. The insertion method is carried out like this:
In this technique, we insert an element A[k] in sub array A[0],A[1]…A[k-1]. This can be accomplished by
comparing A[k] with A[k-1], A[k-1] with A[k-2], A[k-2] with A[k-3]… and so on until first meeting an
138
element A[j] such that A[j]<=A[k]. Then each of elements A[k-1], A[k-2] …….A[j+1] is moved forward to
one location and A[k] is inserted at j+1 st position.
#include<stdio.h>
main()
{
int a[10],n,i,j,temp;
printf("\n Enter the array size:");
scanf("%d",&n);
printf("\n Enter the array elements:");
for(i=0;i<n;i++)
scanf("%d",&a[i]);
for(i=0;i<n;i++)
{
temp=a[i];
j=i;
while(j>0&& temp<a[j-1])
{
a[j]=a[j-1];
j=j-1;
}
a[j]=temp;
}
printf("\n Sorted list (Insertion sort):");
for(i=0;i<n;i++)
printf("%d\t",a[i]);
}
9.4.6. Merging arrays into one array
Merging is the process of combining two or more sorted arrays into one sorted array. Suppose that there
are two sorted arrays: A with N elements and B with M elements. Then the merged array consists of N+M
elements or less, if there are duplicate elements in both.
139
The following program best explains the concept of merging two arrays:
/* Merging two arrays into one array*/
#include<stdio.h>
main()
{
int a[10],n,b[10],m,c[20],i,j,k,l;
printf(“\n Enter the first array size:”);
scanf(“%d”,&n);
printf(“\n Enter the first array elements in sorted order:”);
for(i=0;i<n;i++)
scanf(“%d”,&a[i]);
141
From this memory map, we can observe that a Two-Dimensional array’s row’s subscript value as well as
column’s subscript’s value start from 0 and end with n-1.
142
Operations on matrices:
printf(“\n Enter the first matrix order:”); printf(“\n Enter the first matrix order:”);
scanf(“%d%d”,&m,&n); scanf(“%d%d”,&m,&n);
printf(“\n Enter first matrix elements:”); printf(“\n Enter first matrix elements:”);
for(i=0;i<m;i++) for(i=0;i<m;i++)
for(j=0;j<n;j++) for(j=0;j<n;j++)
scanf(“%d”,&a[i][j]); scanf(“%d”,&a[i][j]);
printf(“\n Enter the second matrix order:”); printf(“\n Enter the second matrix order:”);
scanf(“%d%d”,&p,&q); scanf(“%d%d”,&p,&q);
printf(“\n Enter second matrix elements:”); printf(“\n Enter second matrix elements:”);
for(i=0;i<p;i++) for(i=0;i<p;i++)
for(j=0;j<q;j++) for(j=0;j<q;j++)
scanf(“%d”,&b[i][j]); scanf(“%d”,&b[i][j]);
if(m==p&&n==q) if(n==p)
{ {
for(i=0;i<m;i++) for(i=0;i<m;i++)
for(j=0;j<n;j++) {
c[i][j]=a[i][j]+b[i][j]; for(j=0;j<q;j++)
c[i][j]=0;
printf(“\n The resultant matrix \n”); for(k=0;k<n;k++)
for(i=0;i<m;i++) c[i][j]=c[i][j]+a[i][k]*b[k][j];
{ }
for(j=0;j<n;j++) printf(“\n The resultant matrix \n”);
printf(“%d\t”,c[i][j]); for(i=0;i<m;i++)
printf(“\n”); {
} for(j=0;j<n;j++)
} printf(“%d\t”,c[i][j]);
else printf(“\n”);
printf(“\n Matrix addition is not possible”); }
} }
else
printf(“\n Matrix multiplication is not
possible”);
}
143
/*Program to find transpose of matrix */ /*Program to compare two matrices*/
#include<stdio.h> #include<stdio.h>
main() main()
{ {
int a[10][10],b[10][10],i,j,m,n; int a[10][10],b[10][10],i,j;
int m,n,p,q,flag;
printf(“\n Enter the matrix order:”);
scanf(“%d%d”,&m,&n); printf(“\n Enter the first matrix order:”);
printf(“\n Enter matrix elements:”); scanf(“%d%d”,&m,&n);
for(i=0;i<m;i++) printf(“\n Enter first matrix elements:”);
for(j=0;j<n;j++) for(i=0;i<m;i++)
scanf(“%d”,&a[i][j]); for(j=0;j<n;j++)
scanf(“%d”,&a[i][j]);
for(i=0;i<n;i++)
for(j=0;j<m;j++) printf(“\n Enter the second matrix order:”);
b[i][j]=a[j][i]; scanf(“%d%d”,&p,&q);
printf(“\n Enter second matrix elements:”);
printf(“\n The Transpose of matrix A \n”); for(i=0;i<p;i++)
for(i=0;i<n;i++) for(j=0;j<q;j++)
{ scanf(“%d”,&b[i][j]);
for(j=0;j<m;j++)
printf(“%d\t”,b[j][i]); if(m==p && n==q)
printf(“\n”); {
} flag=0;
}
for(i=0;i<m;i++)
/*Program to print identity matrix*/ {
#include<stdio.h> for(j=0;j<n;j++)
main() {
{ if(a[i][j]!=b[i][j])
int a[10][10],m,n,i,j; {
printf(“\n Enter matrix order:”); flag=1;
scanf(“%d%d”,&m,&n); break;
if(m!=n) }
printf(“\n Identity matrix should be }
square matrix”); }
else
{ if(flag==1)
printf(“\n Matrices are not equal”);
for(i=0;i<m;i++) else
for(j=0;j<n;j++) printf(“\n Matrices are equal”);
if(i==j) }
a[i][j]=0; else
else printf(“\n Matrix comparison is not possible”);
a[i][j]=1; }
144
/*Program to find the trace of a matrix*/ /*Program to find the norm of a matrix*/
/*trace of matrix is sum of diagonal /*norm of matrix=square root of the sum
elements*/ of the squares of the elements of the
#include<stdio.h> matrix*/
main() #include<stdio.h>
{ #include<math.h>
int a[10][10],i,j,m,n,sum; main()
printf(“\n Enter the matrix order:”); {
scanf(“%d%d”,&m,&n); int a[10][10],i,j,m,n;
if(m!=n) long int sum;
printf(“\n Rectangular matrices don’t have double norm;
diagonal”); printf(“\n Enter the matrix order:”);
else scanf(“%d%d”,&m,&n);
{
printf(“\n Enter matrix elements:”); printf(“\n Enter matrix elements:”);
for(i=0;i<m;i++) for(i=0;i<m;i++)
for(j=0;j<n;j++) for(j=0;j<n;j++)
scanf(“%d”,&a[i][j]); scanf(“%d”,&a[i][j]);
sum=0; sum=0;
for(i=0;i<m;i++) for(i=0;i<m;i++)
{ {
for(j=0;j<n;j++) for(j=0;j<n;j++)
if(i==j) sum=sum+a[i][j]*a[i][j];
sum=sum+a[i][j]; }
} norm=sqrt(sum);
printf(“\n Trace of matrix=%d”,sum); printf(“\n Norm of matrix=%lf”,norm);
} }
}
/*Program to check whether given
matrix is symmetric or not */
/*A is symmetric if AT=A*/
#include<stdio.h>
main()
{
int a[10][10],b[10][10],i,j,m,n,flag;
printf(“\n Enter the matrix order:”);
scanf(“%d%d”,&m,&n);
printf(“\n Enter matrix elements:”);
for(i=0;i<m;i++)
for(j=0;j<n;j++)
scanf(“%d”,&a[i][j]);
for(i=0;i<n;i++)
for(j=0;j<m;j++)
b[i][j]=a[j][i];
flag=0;
for(i=0;i<m;i++){
for(j=0;j<n;j++){
if(a[i][j]!=b[i][j]){
flag=1;
break;
}
}
}
if(flag)
printf(“\n Given matrix is not symmetric”);
145
else
printf(“\n Given matrix is symmetric”);}
9.6. Passing an array as an argument
Like the values of simple variables, it is also possible to pass an array to a function. While passing
array as an argument, all the elements of array are not being passed. Instead, the name of the array is
being passed. In C, the name of an array is the primary expression whose value is the address of the first
element in the array. Hence, the arrays are passed to a function using call by reference only. By using this
method, there is no need of copying all the elements for further use in called function. Instead, the called
function refers to the array back in the calling function so that a lot of memory and time will be saved.
9.6.1. Passing one-dimensional array:
To pass a one-dimensional array to a called function, these rules should be followed:
The function must be called by passing only the name of the array, without the subscript.
In the function definition, the formal parameter must be an array type; the size of the array does
not need to be specified.
The function prototype must show that the argument is an array.
The following program demonstrates passing one-dimensional array as an argument:
/*Program to find largest element in an array*/
#include<stdio.h>
int largest(int[],int); //function prototype
main()
{
int a[10[,n,big,i;
printf(“\n Enter the array size:”);
scanf(“%d”,&n);
printf(“\n Enter the array elements:”);
for(i=0;i<n;i++)
scanf(“%d”,&a[i]);
big=largest(a,n); //function call
printf(“\n Biggest number=%d”,big);
}
int largest(int a[],int n)
{
int x;
x=a[0];
for(i=0;i<n;i++)
{
if(x<a[i])
x=a[i];
}
return x;
}
}
}
else
printf(“\n Lower triangle matrix will be formed only for square matrices”);
}
9.7. Conclusion
An array is a finite, homogenous collection of elements stored in contiguous locations in memory that are
referred by a common name. An array is needed when we want a variable to store multiple values at a
time. An array is also called as an Abstract Data Type. As an ADT, array is a collection of data elements
and operations on those data items such as traversal, insertion, deletion, reversal, searching, sorting and
merging. Because an array contains at least one subscript preceded by a name, it is also called as a
subscripted variable.
147
Arrays-II 10
(Non-Numeric Arrays)
0
Chapter Outline
“There are basically two types of people. People
10.1. Introduction.
who accomplish things and people who claim to
have accomplished things. The first group is less 10.2. One-Dimensional
crowded.” -Mark Twain
array of characters.
10.3. String-handling
functions.
10.4. Two-Dimensional
array of characters.
“We must remember that one determined 10.5. Conclusion
person can make a significant difference, and
that a small group of determined people can
change the course of history.” -Sonia Johnson
148
10.1. Introduction
Variables of type char can hold only a single character, so they have limited usefulness. We also need a
way to store strings, which are sequences of characters. A person's name and address are examples of
strings. Although there is no special data type for strings, C handles this type of information with arrays of
characters.
e.g., “I Love India” is a string. Whenever a string is stored in memory, the compiler automatically inserts
a NULL character (\0) at the end of string. This NULL character is a string terminator, i.e., it denotes the
end of string. This NULL character is the first ASCII character which has a value of zero.
In this syntax:
<Storage_class> is any one of auto, extern, static or register, an optional one.
char is the data type that determines the type of elements in the array are as characters.
<array_name> is any valid identifier.
size, a positive integer constant or integer constant expression, determines the number of characters in
the string.
Ex: char name[20]; //can hold a string of 19 characters; one location is for NULL
char a [35]; //can hold a string of 34 characters; one location is for NULL
When we declare a character array, a memory location should be reserved for the NULL character.
149
char a[]=”I Love India”;
When the character array is initialized, the memory map for that array is as follows:
1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012
I L o v e I n d i a \0
a[0] a[1] a[2] a[3] a[4] a[5] a[6] a[7] a[8] a[9] a[10] a[11] a[12]
Interview question #1
If I can say
char a[]=”I Love India”;
Why can’t I say
char a[13];
a=”I Love India”;
As we know that strings are arrays. As we can’t assign arrays directly, strings can’t be assigned
directly. Instead, we can use strcpy() like this:
strcpy(a,”Hello world”);
}
Usually, scanf() statement expects an address of the variable. Because the name of the array itself is an
address of it, we don’t use an ampersand (&) before the name of the string. The %s option uses a blank
space as a delimiter and hence it considers the character separated by blank space as two strings.
The disadvantage of scanf() function is that there is no way to read a multi-word string (i.e., string
with spaces) into a single variable. The scanf() function terminates the input string when it finds blank
150
space in input string. E.g., if the input for scanf() function is “pradeep kumar”, the string variable str
holds only the string pradeep.
To read a multi-word, we can use the following form of scanf():
#include<stdio.h>
main()
{
char str[25];
printf(“\n Enter your name:”);
scanf(“[^\n]”,str);//[^\n] means read set of characters except new line character
printf(“\n Your Name=%s”,str);
}
10.2.3.2. By using the gets() and puts() functions
The gets() function can also be used to read a string using keyboard. It reads and assigns the input string
to the character array until the ENTER key is pressed. The input string can consist of blank spaces and
tabs as part of it. The puts() function is used to print that string which was read by using gets() or
scanf().
Ex: #include<stdio.h>
main()
{
char str[25];
printf(“\n Enter your name:”);
gets(str);
puts(str);
}
The string can be entered until the ENTER key is pressed and can be stored in string variable. Now,
suppose that we input the string “pradeep kumar”. Then the variable str holds the whole string “pradeep
kumar”.
The disadvantage of gets() function is that it can be used to read only one string at a time. E.g.,
the following gets() statement is invalid:
gets(str1,str2); //invalid
The gets() function expects only one string as an argument. If more than one string is input to this
function, the compiler gives an error “too many arguments to function gets”
However, a scanf() function can be used to read more than one string at a time.
E.g., scanf(“%s%s%s”,str1,str2,str3); can be used to read 3 strings.
10.2.3.3. By using a loop
A string can be read character by character by using a for loop (or any loop). Each time the loop runs, the
getchar() function takes the character from the keyboard and that character will be assigned to the one of
character array’s locations. The loop should be stopped when the new line character is encountered. When
the repetition has stopped, the last location should occupy the NULL character for denoting the end of
string.
For printing the string using a loop, the iterative process should start at 0 th location and should
terminate before the NULL character. In each iteration, the character should be printed with the help of
putchar() or printf() with %c conversion specifier.
151
E.g.,#include<stdio.h>
main()
{ char str1[23],ch;
int i;
printf("\n Enter any string:");
for(i=0;(ch=getchar())!='\n';i++)
str1[i]=ch;
str1[i]='\0';
for(i=0;str1[i]!=’\0’;i++)
putchar(str1[i]);
}
Example programs:
/*A program to check whether given /*Program to count no.of vowels and
string is palindrome or not*/ consonants in a line of text*/
#include<stdio.h> #include<stdio.h>
main() main()
{ {
char str[30]; char text[50];
int len=0,flag=0,i,j; int nv=0,nc=0;
printf("\n Enter a string:"); printf(“\n Enter a line of text:”);
gets(str); gets(text);
for(i=0;str[i]!='\0';i++) for(i=0;text[i]!=’\0’;i++)
len++; {
for(i=0,j=len-1;i<j;i++,j--) if(text[i]==’a’||text[i]==’e’||text[i]==’o’||
if(str[i]!=str[j]) text[i]==’i’||text[i]==’u’)
{ nv++;
flag=1; else
break; nc++;
} }
if(flag==0) printf(“\n No.of vowels=%d”,nv);
printf("\n Given string is palindrome"); printf(“\n No.of consonants=%d”,nc); }
else
printf("\n Given string is not a
palindrome");
}
/*Program to count no.of lines, words /*Program to convert the case of text*/
and characters in multiple lines of #include<stdio.h>
text*/ main()
#include<stdio.h> {
main() char text[50];
{ printf(“\n Enter a line of text:”);
char text[150],ch; gets(text);
int nl=0,nw=0,nc=0; for(i=0;text[i]!=’\0’;i++)
printf(“\n Enter multiple lines of text (end {
with #):”); if(text[i]>=’A’ && text[i]<=’z’)
for(i=0;(ch=getchar())!=’#’;i++) text[i]=text[i]+32;
{nc++; else
if(ch==’ ‘) text[i]=text[i]-32;
nw++; }
else if(ch==’\n’) printf(“\n converted text=%s”,text);
nl++; }
else ;}
printf(“\n No.of lines=%d”,nl);
printf(“\n No.of words=%d”,nc);
printf(“\n No.of characters=%d”,nc); }
152
Passing a string to a function
To pass a string to a function, these rules should be followed:
The function must be called by passing only the name of the string, without the subscript.
In the function definition, the formal parameter must be a character array type; the size of the
array does not need to be specified.
The function prototype must show that the argument is a character array.
The following program demonstrates the concept of passing a string to a function:
}
void display(char s[]) //function definition
{
printf(“\n Given string=%s”,s);
}
int getCount(char s[],char ch) //function definition
{
int count=0,i;
for(i=0;s[i]!=’\0’;i++)
if(s[i]==ch)
count++;
return count;
}
153
/* A program to convert a string to a /* A program to convert an integer to a
number*/ string*/
#include<stdio.h> #include<stdio.h>
int str_to_int(char []); #include<string.h>
main() char * int_to_str(int);
{ main()
char str[10]="1234"; {int n = 1234;
printf("number = %d",str_to_int(str)); printf("string is %s",int_to_str(n));
} }
int str_to_int(char str[]) char * int_to_str(int n)
{ {static char str[10];
int i,sum=0; char temp;
for(i=0;str[i]!='\0';i++) int i=1,j;
{ if(n>=0)
if(str[i]=='-' && i==0) str[0]='+';
continue; else
sum = sum*10 + (str[i]-'0'); {str[0]='-';
} n = -n;}
if(str[0]=='-') for(;n>0;n=n/10)
sum = -sum; str[i++] = n%10+'0';
return sum; str[i]='\0';
} for(i=1,j=strlen(str)-1;i<j;i++,j--)
{temp = str[i]; str[i] = str[j]; str[j] = temp;}
return str;
}
/*A program to convert a string to float*/ /*A program to convert a float to string*/
#include<stdio.h> #include<stdio.h>
char * float_to_str(float);
float str_to_float(char *);
main()
main() {float n = -1234.1234;
{ char str[20]="-1234.12345"; printf("string is %s",float_to_str(n));
printf("number = %f",str_to_float(str)); }
char * float_to_str(float p)
}
{static char str[10];
float str_to_float(char *str) char temp;
{ int i,x=0,y=10; int i=1,j,k,n,m;
float sum=0; if(p>=0)
str[0]='+';
for(i=0;str[i]!='\0';i++)
else
{ if(str[i]=='-' && i==0) { str[0]='-';
continue; p = -p;}
if(str[i]=='.') m = n = p;
for(;n>0;n=n/10)
{x=1;
str[i++] = n%10+'0';
continue;} p = p-m;
if(x==0) for(j=1;j<=4;j++)
sum = sum*10 + (str[i]-'0'); p = p*10;
n=p;
else
str[i]='.';
{ sum = sum + (str[i]-'0')/(float)y; k = i;
y=y*10; for(i++;n>0;n=n/10)
}} str[i++] = n%10+'0';
str[i]='\0';
if(str[0]=='-')
for(i=1,j=k-1;i<j;i++,j--)
sum = -sum; {temp = str[i]; str[i] = str[j]; str[j] = temp; }
return sum;} for(i=k+1,j=strlen(str)-1;i<j;i++,j--)
{temp = str[i]; str[i] = str[j]; str[j] = temp;}
return str;
}
154
10.3. String-handling functions
C supports a number of string handling functions. All of these built-in functions are aimed at
performing various operations on strings. All of these built-in functions are defined in the header file
string.h. Therefore, whenever we use one of these string handling functions, we should add the
preprocessor statement #include<string.h> to our program. Some of the string- handling functions are:
strlen() strrev() strcpy() strcat() strcmp()
strlwr() strupr() strncpy() strncat() strncmp()
1. strlen() function: This function is used to find the length of the string excluding the NULL character.
In other words, this function is used to count the number of characters in a string. Its syntax is as follows:
int strlen(string1);
2. strrev() function: This function is used to find the reversed string of a given string. Its syntax is as
follows:
strrev(string1);
155
/* A program to reverse a string using /* A program to reverse a string without using
strrev() function*/ strrev() function*/
#include<stdio.h> #include<stdio.h>
#include<string.h> void MyStringReverse(char [30]);
main() main()
{ {
char string1[30]; char string1[30];
printf(“\n Enter any string:”); printf("\n Enter any string:");
gets(string1); gets(string1);
strrev(string1); printf("\n Original string=%s",string1);
printf(“\n Reversed string=%s”,string1); MyStringReverse(string1);
} }
void MyStringReverse(char str[30])
{
int length=0,i,j;
char temp;
for(i=0;str[i]!='\0';i++)
length++;
for(i=0,j=length-1;i<j;i++,j--)
{
temp=str[i];
str[i]=str[j];
str[j]=temp;
}
printf("\n Reversed string=%s",str);
}
3.strcpy() function: This function is used to copy one string to the other. Its syntax is as follows:
strcpy(string1,string2);
156
}
4.strcat() function: This function is used to concatenate two strings. i.e., it appends one string at the
end of the specified string. Its syntax as follows:
strcat(string1,string2);
5. strcmp() function: This function compares two strings character by character (ASCII comparison) and
returns one of three values {-1,0,1}. Its syntax is as follows:
int strcmp(string1,string2);
157
/* A program to compare two strings using /* A program to compare two strings without
strcmp() function*/ using strcmp() function*/
#include<stdio.h> #include<string.h>
#include<string.h> int MyStringCompare(char[],char[]);
main() main()
{ { char string1[20],string2[20];
char string1[30],string2[15]; int x;
int x; system("clear");
printf(“\n Enter first string:”); printf("\n Enter first string:");
gets(string1); gets(string1);
printf(“\n Enter second string:”); printf("\n Enter second string:");
gets(string2); gets(string2);
x=strcmp(string1,string2); x=MyStringCompare(string1,string2);
if(x==0) if(x==0)
printf(“\n Both strings are equal”); printf("\n Both strings are equal");
else if(x>0) else if(x>0)
printf(“\n First string is bigger”); printf("\n First string is bigger");
else else
printf(“\n Second string is bigger”); printf("\n Second string is bigger");
} }
int MyStringCompare(char str1[],char str2[])
{ int i,c=0;
for(i=0;str1[i]!='\0'||str2[i]!='\0';i++)
{
if(str1[i]>str2[i])
{
c=1;
break;
}
else if(str1[i]<str2[i])
{
c=-1;
break;
}
}
return c;
}
6. strlwr() function: This function converts all the uppercase alphabets into lowercase. Its syntax is as
follows:
strlwr(string1);
158
/* A program to convert an upper case string /* A program to convert an uppercase string
to lower case string using strlwr() function*/ to lowercase string without using strlwr()
#include<stdio.h> function*/
#include<string.h> #include<stdio.h>
main() void MyStringLower(char[]);
{ main()
char string[30]; { char string[30];
printf(“\n Enter any uppercase string:”); printf("\n Enter any uppercase string:");
gets(string); gets(string);
strlwr(string); MyStringLower(string);
printf(“\n lower case string=%s”,string1); }
} void MyStringLower(char str[])
{ int i;
for(i=0;str[i]!='\0';i++)
if(str[i]>='A' && str[i]<='Z')
str[i]=str[i]+32;
printf("\n lower case string=%s",str);
}
7. strupr() function: This function converts all the lowercase alphabets into uppercase. Its syntax is as
follows:
strupr(string1);
159
8.strncpy() function: This function copies the first n characters of second string to the first string. Its
syntax is as follows:
strncpy(string1,string2,n);
where string1 and string2 are the one-dimensional arrays of characters and n is an integer.
e.g., string1 holds Delhi and string2 holds Bangalore and n=4, then strncpy() copies the first 4
characters of string2 to string1. The string1 holds the copied substring Bang.
/* A program to copy first n characters of a /* A program to copy first n characters of a
string using strncpy() function*/ string without using strncpy() function*/
#include<stdio.h> #include<stdio.h>
#include<string.h> void MyStringNCpy(char[],char[],int);
main() main()
{ {
char string1[30],string2[30]; char string1[30],string2[30];
printf(“\n Enter first string:”); int n;
gets(string1); printf("\n Enter first string:");
printf(“\n Enter second string:”); gets(string1);
gets(string2); printf("\n Enter second string:");
printf(“\n How many characters:”); gets(string2);
scanf(“%d”,&n); printf("\n Enter howmany characters:");
strncpy(string1,string2,n); scanf("%d",&n);
printf(“\n First string=%s”,string1); MyStringNCpy(string1,string2,n);
} }
void MyStringNCpy(char str1[],char str2[],int n)
{
int i;
for(i=0;i<n;i++)
str1[i]=str2[i];
str1[i]='\0';
printf("\n First string=%s",str1);
}
Interview question #2
How to pick a substring from a given string?
A substring is a part of another string. In order to pick up a substring from a given string, we should
use strncpy() function. E.g., there is a string: master minds. Suppose we want to pick up a
substring mind. Then we can observe that the word mind is located at 7th location in array. From 7th
location, we have to keep track of next 4 characters to pick up the following string. The following
program demonstreates this:
#include<stdio.h>
main()
{
char word[]="Master minds";
char sub[15];
strncpy(sub,&word[7],4);
printf("%s",sub);
}
160
9. strncat() function: This function concatenates the first n characters of second string to the first
string. Its syntax is as follows:
strncat(string1,string2,n);
where string1 and string2 are the one-dimensional arrays of characters and n is an integer.
e.g., string1 holds Master and string2 holds System and n=3, then strncpy() concatenates or adds
the first 3 characters of string2 to string1. The string1 holds the concatenated string MasterSys.
10. strncmp() function: This function compares the first n characters of two input strings and returns
one of these 3 values {-1,0,1} same as strcmp() function. Its syntax is as follows:
strncmp(string1,string2,n);
where string1 and string2 are the one-dimensional arrays of characters and n is an integer.
e.g., string1 holds master and string2 holds minister and n=4, then strncmp() compares first 4
characters of both of these strings character by character and returns the value (i.e., -1) as strcmp()
returns.
161
/* A program to compare first n characters of /* A program to compare first n characters of
two strings using strncmp() function*/ two strings without using strncmp()
#include<stdio.h> function*/
#include<string.h> #include<stdio.h>
main() int MyStringNCmp(char[],char[],int);
{ main()
char string1[30],string2[15]; {
int x; char string1[30],string2[30];
printf(“\n Enter first string:”); int n,x;
gets(string1); printf("\n Enter first string:");
printf(“\n Enter second string:”); gets(string1);
gets(string2); printf("\n Enter second string:");
x=strncmp(string1,string2); gets(string2);
if(x==0) printf("\n Enter howmany characters:");
printf(“\n Both strings are equal”); scanf("%d",&n);
else if(x>0) x=MyStringNCmp(string1,string2,n);
printf(“\n First string is bigger”); if(x==0)
else printf("\n Both strings are equal");
printf(“\n Second string is bigger”); else if(x>0)
} printf("\n First string is greater");
else
printf("\n Second string is greater");
}
int MyStringNCmp(char str1[],char str2[],int n)
{ int i,c=0;
for(i=0;i<n;i++)
{ if(str1[i]>str2[i])
{ c=1;
break;
}
if(str1[i]<str2[i])
{ c=-1;
break;
}
}
return c;
}
162
10.4. Two-Dimensional array of characters
By using one-dimensional array, only one string (including spaces) is accepted and processed. Some
times, it is necessary for us to process a group of strings. In such situations, we need a two-dimensional
array. A two-dimensional array of characters is an array of one-dimensional arrays of characters. This
means that, a two-dimensional character array consists of strings (i.e., one-dimensional arrays of
characters) as its individual elements.
10.4.1. Declaration: Like Two-dimensional numeric arrays, Two-dimensional character arrays should be
declared before it is used. A Two-dimensional array of characters can be declared as follows:
<Storage_class> char <array_name>[row][column];
where <Storage_class> is any one of auto, extern, static or register, an optional one.
char is the data type that determines the type of elements in the array.
<array_name> is any valid identifier.
row, a positive integer, determines the number of strings in the array.
Column, a positive integer, determines the number of characters a string can hold.
Ex: char a[5][10]; //can hold 5 input strings, each input string should be of length 9 chars.
10.4.2. Initialization: Like One-dimensional character array, a Two-dimensional character array can also
be initialized with the help of assignment operator as follows:
char names[3][10]={ {‘R’,’a’,’j’,’ ’,’k’,’u’,’m’,’a’,’r’},
{‘S’,’a’,’n’,’j’,’a’,’n’,’a’},
{‘P’,’o’,’o’,’j’,’a’}};
is equivalent to
char names[3][10]={“Raj kumar”,”Sanjana”,”Pooja”};
When this Two-dimensional character array is initialized, it will be in memory as follows:
[0] [1] [2] [3] [4] [5] [6] [7] [8] [9]
names[0] R a j k u m a r \0
names[1] S a n j a n a \0
names[2]
P o o j a \0
10.4.3. Reading and printing multiple strings: The above three methods will be very helpful in
reading and printing each string with the help of a loop. The loop is used for keeping track of loop counter
of rows of two-dimensional array. The following example clears this concept:
Method-1: using printf() and Method-2: using gets() Method-3: Using getchar() and
scanf() and puts() putchar() repeatedly
163
#inlcude<stdio.h> #inlcude<stdio.h> #include<stdio.h>
main() main() main()
{ { { char names[10][15],ch;
char names[10][15]; char names[10][15]; int i,n,j,k;
int n,i; int n,i; printf(“\n How many strings:”);
printf(“\n How many strings:”); printf(“\n How many scanf(“%d”,&n);
scanf(“%d”,&n); strings:”); for(k=0;k<n;k++)
for(i=0;i<n;i++) scanf(“%d”,&n); {printf(“\n Enter %d
{printf(“\n Enter %d for(i=0;i<n;i++) string:”,k+1);
string:”,i+1); {printf(“\n Enter %d for(i=0;(ch=getchar())!='\n';i++)
scanf(“%s”,names[i]); string:”,i+1); names[k][i]=ch;
} gets(names[i]); names[k][i]='\0';
printf(“\n Given strings are:”); } }
for(i=0;i<n;i++) printf(“\n Given strings printf(“\n Given strings are:”);
printf(“%s\t”,names[i]); are:”); for(k=0;k<n;k++)
} for(i=0;i<n;i++) { for(i=0;names[k][i]!=’\0’;i++)
puts(names[i]); putchar(names[k][i]);
} putchar(‘\n’);
}
}
164
{ int search(char names[][],int n,char ele[])
{
if(strcmp(names[i],names[j])>0) int i,pos=-1;
{ for(i=0;i<n;i++)
strcpy(temp,names[i]); {
strcpy(names[i],names[j]); if(strcmp(names[i],ele)==0)
strcpy(names[j],temp); {
} pos=i+1;
} break;
} }
printf(“\n Strings in alphabetical order:”); }
for(i=0;i<n;i++) return pos;
printf(“%s\t”,names[i]); }
}
/*A program print frequencies of words /* A program to print words those begin
in a line of text*/ with given alphabet*/
#include<stdio.h> #include<stdio.h>
#include<string.h> main()
main() {
{ char **words,alpha;
char str[50],copy[20][20],word[15]; int n,i;
char temp[]=" "; printf("\n Enter how many words:");
int i,j,k,l,count; scanf("%d",&n);
printf("\n Enter a line of text:"); for(i=0;i<n;i++)
scanf("%[^\n]",str); *(words+i)=(char *)malloc(15*sizeof(char));
k=0; printf("\n Enter %d words",n);
for(i=0;str[i]!='\0';i++) for(i=0;i<n;i++)
{ j=i; scanf("%s",*(words+i));
l=0; printf("\n Enter the alphabet based on which
while(str[j]!=' ') words are displayed:");
{ copy[k][l]=str[j]; scanf("\n%c",&alpha);
l++; printf("\n The searched words starts with
j++; \'%c\' are:",alpha);
} for(i=0;i<n;i++)
copy[k][l]='\0'; {
k++; if(words[i][0]==alpha)
i=j; printf("%s\t",*(words+i));
} }
for(i=0;i<k;i++) }
{ count=1;
for(j=i+1;j<k;j++)
{ if(strcmp(copy[i],copy[j])==0)
{
strcpy(copy[j]," ");
count++;
}
}
if(strcmp(copy[i]," ")!=0)
printf("\n%s occured %d
times",copy[i],count);
}
}
165
10.5. Conclusion
Generally, a string is a collection of characters. In C, just like int represents integer values, there is no
data type that represents strings. Instead, a string is represented as a one-dimensional array of
characters. Each string has one termination character (‘\0’) that denotes the end of string.
In C, there is a header file namely string.h that has different built-in functions which perform
various operations on strings. In order to represent one string (either single word or multi-word), one-
dimensional array is helpful. In order to store multiple strings (either single word or multi-word), two-
dimensional array is helpful.
166
Pointers 11
0
Chapter Outline
“Better pointed bullets than pointed words.”
-Otto Von Bismarck 11.1. Introduction.
11.2. Advantages of pointers.
11.3. Referencing operator.
11.4. De-referencing operator.
11.5. Working with pointers.
11.6. Operations on pointers.
11.7. Pointers and functions.
“If you open up the mind, the opportunity to 11.8. Casting pointers.
address both profits and social conditions are
11.9. Dynamic memory
limitless. It's a process of innovation.”
-Jerry Greenfield allocation.
11.10. Pointers and one-
dimensional numeric
arrays.
11.11. Pointers and two-
dimensional numeric
“In all pointed sentences some degree of accuracy
must be sacrificed to.” -Oscar Wilde arrays.
11.12. Pointers and strings.
11.13. Pointers and const.
11.14. Command line
arguments.
11.15. Various pointer
declarations.
11.16. Problems with pointers.
11.17. Conclusion.
167
11.1. Introduction
The smallest piece of data in computer memory is known as a bit, which represents 0 or 1. Bits are
grouped to form a byte. Bytes are grouped to form a word. Sets of one or more bytes are used to store
data items. Each byte in the computer memory is called memory location or memory cell. Computer
memory consists of a series of consecutive memory locations. Each memory location is numbered to be
referenced. The number attached to a memory location is called the memory address of that location.
This memory location is merely a positive number, usually a hexa decimal number.
C uses byte as the fundamental unit of data storage to measure the memory required for storing
the data items. A data item may require more than one byte. The number of bytes required for storing the
value of each data type is system dependent. When more than one byte are used for holding a value, the
starting address of that storage is considered as the address of that value (or data item).
Interview question #1
What is a pointer?
A Pointer is a special type of variable that holds the address as a data item in it. The address may be of
one of these: variable, array, function, structure or another pointer.
Usually, an ordinary variable holds a number or a character as a data item in it. Instead, pointer
holds the address. If a variable occupies more than one byte, pointer holds the first byte (or byte0)
address. As this is a variable, the address in a pointer can be changed. Mostly, pointer uses 2 or 4
bytes to hold the addresses. In short, a pointer variable is a group of cells that can hold an address.
Point to ponder #1
Pointer is just an address; not any ordinary value
168
11.3. Referencing operator (&)
Referencing operator is a unary operator. It acts on one operand at a time. It returns the address of
operand. The operand must be a named region of storage (like int variable, array variable, pointer
variable etc.) for which a value may be assigned. The operand must not be a constant or an expression or
a register variable. This operator is also called as “address of” operator.
The & operator should be preceded with the operand in order to return the address.
&Operand_1
a Name of variable
From this memory map, it is clear that the data item 20 can be accessed with the help of name of variable
as well as address of variable (or memory location or reference).
The conversion character %x is used to print address in hexa-decimal notation. The conversion
character %u is used to print the address in decimal notation (especially, a positive number to
understand easily).
169
Program #1
Write a program to print the address of variable in hexa decimal and decimal notations
#include<stdio.h>
main()
{
int a=20;
printf(“\n The address of a =%x”,&a); //prints address in hexa decimal notation
printf(“\n The address of a=%u”,&a); // prints the address as a positive long integer
printf(“\n The address of a=%p”,&a);
}
Output:
Interview question #2
What are the differences between referencing operator and bitwise AND?
*Operand_1
170
Program #2
Write a program to print the content of a variable
#include<stdio.h>
main()
{
int a=20;
printf(“\n The value of a=%d”,a);
printf(“\n The value of a=%d”,*(&a));
}
Output: The value of a=20
The value of a=20
Interview question #3
What are the differences between Indirection operator and Arithmetic operator?
Declaration of a pointer variable: Just like an ordinary variable, a pointer variable should be declared
before it is used. This declaration has the following form:
171
The declaration int *iptr; does not mean that iptr is going to contain integer value. What it means is,
iptr is a pointer variable that is going to hold the address of an integer value. Hence, iptr is a pointer that
points to integer value. In short, iptr is a pointer-to-int.
In the same way, the pointer fptr is going to contain the address of floating point value. Hence,
fptr is a pointer that points to a floating point value. In short, fptr is a pointer-to-float.
Similarly, the pointer cptr is going to contain the address of a character. Hence, cptr is a pointer
that points to a character. In short, cptr is a pointer-to-char.
Initialization of a pointer variable: A pointer variable should be initialized with an address before it is
used. The initialization of a pointer variable takes the following form:
Lvalue=Rvalue;
Where Lvalue is any pointer variable and Rvalue is a variable preceded with an ampersand or a pointer of
same type of LValue.
Point to ponder#2
A Pointer can never be initialized with a normal value (except 0); it should be initialized with an
address.
iptr1 a iptr2
Interview question #4
172
Point to ponder#3
Interview question #5
What is a NULL pointer?
NULL pointer is a special type of pointer with the meaning: “not allocated” or “not pointing anywhere
yet”. That is, it points definitively nowhere; it is not the address of any variable, array, structure or
function.
If any type of pointer is initialized with the value 0, then it can be treated as a NULL pointer.
The following are the examples of NULL pointers:
1) int *iptr=0; 3) # define NULL 0 int *iptr=NULL;
2) float *fptr=0; 4) float *fptr=NULL;
In the example 4, NULL is a predefined macro that is available in stdio.h and stddef.h which has the
value 0 (same as example3).
Program #3
Write a program to declare, initialize and access a pointer variable
#include<stdio.h>
main()
{
int a=40;
int *iptr; //Declaration: pointer-to-int
iptr=&a; //Initialization: with the address of a
173
Interview question #6
Define pointer-to-pointer?
If a pointer variable is initialized with the address of another pointer variable, then we can say that
pointer is a pointer-to-pointer.
174
Pointer increment and decrement:
Pointer Description
Expression
Ptr=Ptr+n*sizeof(data_type_of_pointer)
Ptr+n Use the original value of ptr and then n*sizeof(data_type_of_pointer) is added
to ptr after statement execution.
Ptr=Ptr-n*sizeof(data_type_of_pointer)
Ptr-n Use the original value of ptr and then n*sizeof(data_type_of_pointer) is
subtracted from ptr after statement execution.
Ptr=Ptr+ sizeof(data_type_of_pointer)
Ptr++ Use the original value of ptr and then ptr is incremented after statement
execution.
Ptr=Ptr- sizeof(data_type_of_pointer)
Ptr-- Use the original value of ptr and then ptr is decremented after statement
execution.
Ptr=Ptr+ sizeof(data_type_of_pointer)
++Ptr
Original Ptr is incremented before the execution of statement.
Ptr=Ptr- sizeof(data_type_of_pointer)
--Ptr
Original Ptr is decremented before the execution of statement.
*(Ptr++)
*Ptr++ Retrieve the content of the location pointed to by pointer and then increment
ptr.
*(Ptr--)
*Ptr-- Retrieve the content of the location pointed to by pointer and then decrement
ptr.
*(++ptr)
*++Ptr Increment pointer and then retrieve the content of the new location pointed to
by Ptr.
*(--Ptr)
*--Ptr Decrement pointer and then retrieve the content of the new location pointer
to by Ptr.
Retrieve the content of *Ptr of the location pointed to by Ptr, and then
(*Ptr)++ Increment content of the location pointed to by Ptr. For pointer type content,
use pointer arithmetic of standard arithmetic.
Retrieve the content *Ptr of the location pointed to by Ptr, then decrement
(*Ptr)--
the content of that location; Ptr is not changed.
Point to ponder#4
Comparing two pointers those point to different types of objects lead to error, although they have
addresses as data items in them.
176
Program #5
Write a program to increment three values from called function and print them in calling
function.
#include<stdio.h>
void increment(int *,int *,int *); //function prototype
main()
{
int a=20,b=30,c=40;
printf(“\n Before increment a=%d\tb=%d\tc=%d”,a,b,c);
increment(&a,&b,&c); //function call
printf(“\n After increment a=%d\tb=%d\tc=%d”,a,b,c);
}
void increment(int *x,int *y,int *z) //function definition
{
++*x;
++*y;
++*z;
}
Output:
Point to ponder#4
Indirectly, a called function can return multiple values if pointers to these are passed as arguments.
Program #6
Write a program to interchange two numbers in calling function from called function
#include<stdio.h>
void swap(int *,int *); //function prototype
main()
{
int a,b,*aptr,*bptr;
printf(“\nEnter any two numbers:”);
scanf(“%d%d”,&a,&b);
aptr=&a;
bptr=&b;
printf(“\n Before swap a=%d\tb=%d”,a,b);
swap(aptr,bptr); //function call
printf(“\n After swap a=%d\tb=%d”,a,b);
}
void swap(int *x,int *y) //function definition
{
*x=*x+*y;
*y=*x-*y;
*x=*x-*y;
}
Output:
177
11.7.2. Pointer as a return value
Pointers can also be returned to the calling function from called function as normal values. When we want
to return a pointer to the calling function from called function, we should do these:
In function prototype, place an ‘*’ after the return type to indicate that the function returns a
pointer.
In calling function, there should be a pointer variable that is declared to hold the pointer that is
returned. However, both types should be the same to avoid ambiguities.
Develop the function definition as specified in function prototype. In function definition, the return
statement, at end, should consist of an ‘&’ before the return value or a pointer that is declared
earlier.
Point to ponder #4
Returning a pointer to local argument of called function to calling function gives you a warning.
Output:
Enter the values of a and b: 10
12
The result=22
178
11.7.3. Pointer-to-function
We can also call a function using a pointer. To call a function using a pointer, do the following:
1. First, declare a pointer to function that has the following form:
Output:
Enter the values of a and b: 10
12
The result=22
179
11.7.4. Passing a function as an argument to another function
A pointer-to-function can be passed to another function as an argument. This allows one function to be
transferred to another function. Let us refer to the first function as the guest function and the second
function as host function. Thus the guest function is passed to the host function, where it can be
accessed. When we want to pass a function as an argument to another function, do the following:
1) While calling the host function, place the name of the guest function as an argument. The name
itself serves as a pointer to guest function.
2) Give the definition of guest function as usual.
3) In the definition of host function, place a pointer to guest function as an argument.
4) In the definition of host function, call guest function for further process.
Program #9
Write a program that demonstrates function as an argument to another function
#include<stdio.h>
int add(int,int); //guest function prototype
void swap(int(*)(int,int));//host function prototype
int a,b;
main()
{
printf("\n Enter any two numbers:");
scanf("%d%d",&a,&b);
swap(add); //step-1
printf("\n After swap a=%d\tb=%d",a,b);
}
int add(int x,int y) //step-2
{
return x+y;
}
void swap(int (*addptr)(int,int)) //step-3
{
a=(*addptr)(a,b); //step-4
b=(*addptr)(a,-b); //step-4
a=(*addptr)(a,-b); //step-4
}
Output:
Enter any two numbers: 32
45
After swap a=45 b=32
180
11.8. Casting pointers
A pointer always has a type associated with it. As we can convert a variable of one type to another, we
can also convert one type of pointer to another type of pointer. This process of conversion is called as
casting pointers. Unlike variables, we can’t assign one type of pointer variable with another type of pointer
variable, although both of them have memory addresses as their values. This is known as incompatibility
of pointers.
We can’t use the assignment operator with the pointers of different types. We can, however, make
explicit assignment between two incompatible pointer types by using cast operator, as we do with
fundamental types. The cast operator can be used as follows:
In this syntax, ptr2 is a pointer variable of a data type that is going to be converted to the type of ptr1.
Usually, the <data type> is same as the type of <ptr1>.
Program #10
Write a program that demonstrates casting from one type to another
#include<stdio.h>
main()
{
int a=65;
int *iptr=&a;
char *cptr;
cptr=(char *)iptr;
printf("%c",*cptr);
}
Output:
A
181
11.9. Dynamic memory allocation
Though arrays can be used for data storage, they are of fixed size. The programmer must know the size of
the array while writing the program. In most situations, it is not possible to know the size of the memory
required until run time. At execution time, a program can request more memory from a free memory pool
(heap). Dynamic memory allocation refers to the allocation of such memory during program execution.
The only way to access this dynamically allocated memory is through pointers.
Interview question #7
What are the differences between dynamic memory allocation and static memory
allocation?
Points to ponder #5
The limit for dynamic memory allocation can be as large as the amount of available physical memory in
the computer or the amount of available virtual memory in a virtual memory system.
C supports many built-in standard library functions for efficient dynamic memory allocation / de-
allocation. Their prototypes are declared in the header files stdlib.h, alloc.h and malloc.h. These
functions are: malloc(), calloc(), realloc() and free().
1) malloc() — allocates a block of memory
The function malloc() has the following prototype:
182
Ex: 1) malloc(30); allocates 30 bytes of memory and returns the address of byte0.
2) malloc(sizeof(float)); allocates 4 bytes of memory and returns the address of byte0.
Interview question #8
What do malloc(-20) and malloc(0) return?
The parameter to malloc() function should be an unsigned integer. If we pass any negative value as an
argument, then NULL is returned. So, malloc(-20) returns NULL.
Though the value 0 is not a negative integer, malloc(0) does not return pointer to 0 bytes or NULL
pointer. Instead, it also returns the constant NULL.
Interview question #9
What are the differences between malloc() and calloc()?
malloc() calloc()
malloc() accepts one argument of type calloc() accepts two arguments of type
size_t with the following prototype: size_t with the following prototype:
malloc() can allocate one block of memory. calloc() can allocate multiple blocks of
memory.
malloc() does not clear the allocated calloc() clears the allocated memory. i.e.,
memory. it places zeros in allocated bytes.
malloc() function allocates memory as calloc() function expects the total
chained link. expected memory to be continuous.
183
3) realloc() — grows or shrinks allocated memory
The function malloc() has the following prototype:
The function realloc() adjusts the amount of memory allocated to the block to size, copying the contents
to a new location if necessary.
Arguments: block is the pointer to the memory block that is previously obtained by calling malloc(),
calloc() or realloc(). If block is NULL pointer, realloc() works just like malloc().
Size is the new size for allocated block.
Return value:
On success, this function returns the address of the reallocated block, which might be different
from the address of the original block.
On failure, i.e., if the block can’t be reallocated or if the size passed is 0, the function returns NULL.
The function realloc() is more useful when the maximum size of allocated block can not be decided in
advance.
Ex: int *a;
a=(int *) malloc(30); //first 30 bytes of memory is allocated.
a=(int *) realloc(a,15); //later the allocated memory is shrink to 15 bytes.
Interview question #10
Why does not sizeof operator tell us the size of block of memory pointed by a pointer?
The sizeof operator does not know the at malloc() has been used to allocate pointer; sizeof tells
us the size of the pointer itself. There is no portable way to find out the size of a block allocated
by malloc().
186
Interview question #12
Can we use the content of allocated memory after freeing it?
Some early documentation for malloc() stated that the contents of freed memory were “left
undisturbed”. So, few programmers would use the contents of freed memory deliberately.
Program #14
Write a program to access a 2-D array using pointer and print it in matrix form
#include<stdio.h>
main()
{
int a[10][10],m,n,i,j;
int (*ptr)[10]; //pointer-to-array
printf(“\n Enter the matrix row and column values:”);
scanf(“%d%d”,&m,&n); Output:
printf(“\n Enter matrix elements:”);
Enter matrix row and column values: 2 2
for(i=0;i<m;i++)
Enter matrix elements: 23 45 65 232
for(j=0;j<n;j++)
The matrix elements:
scanf(“%d”,&a[i][j]);
23 45
ptr=a;
65 232
printf(“\n The matrix elements:\n”);
for(i=0;i<m;i++)
{
for(j=0;j<n;j++)
{
printf(“%d\t”,*(*(ptr+i)+j));
printf(“\n”);
}
}
188
11.11.2. Dynamically allocated 2-D array
When we declare an array, we declare it as an array of fixed size. It can’t be grown or shrink as and when
needed. To overcome this problem, dynamically allocated array is introduced. To work with dynamically
allocated array, do the following:
1. Declare a pointer variable.
2. Allocate memory to that pointer variable.
3. Initialize and access array elements through pointer variable.
4. De-allocate the pointer variable.
The following program demonstrates this concept:
Program #15
/*A program to multiply two matrices using pointers*/
#include<stdio.h>
void display(int **,int,int);
void multiply(int **,int **,int,int,int,int);
main()
{
int **a,**b,m,n,p,q,i,j; //step-1
b=(int **)malloc(p*sizeof(int));
for(i=0;i<m;i++)
a[i]=(int *)malloc(q*sizeof(int));
printf("\n Enter second matrix elements");
for(i=0;i<m;i++)
for(j=0;j<n;j++)
scanf("%d",&b[i][j]);
printf(“\n Second matrix\n”);
display(b,p,q);
multiply(a,b,m,n,p,q);
free(a);
free(b);
}
}
189
void display(int **a,int m,int n)
{
nt i,j;
for(i=0;i<m;i++)
{
for(j=0;j<n;j++)
printf("%d\t",a[i][j]);
printf(“\n”);
}
}
void multiply(int **a,int **b,int m,int n,int p,int q)
{
int **c,i,j;
c=(int **)malloc(m*sizeof(int));
for(i=0;i<m;i++)
c[i]=(int *)malloc(q*sizeof(int));
for(i=0;i<m;i++)
{
for(j=0;j<q;j++)
{
c[i][j]=0;
for(k=0;k<n;k++)
c[i][j]=c[i][j]+a[i][k]*b[k][j];
}
}
printf(“\n The resultant matrix:\n”);
display(c,m,q);
free(c);
}
190
Program #17
Write a program to print transpose a matrix using array of pointers.
#include<stdio.h>
main()
{
int *a[10];
int m,n,i,j;
for(i=0;i<m;i++)
a[i]=(int *)malloc(n*sizeof(int));
191
Program #18
Write a program to print transpose of a matrix using pointer-to-array
#include<stdio.h>
main() Output:
{ Enter matrix row and column values: 2 2
int a[10][10],m,n,i,j; Enter matrix elements: 23 45 65 232
int (*ptr)[10]; //pointer-to-array The matrix elements:
printf(“\n Enter the matrix row and column values:”); 24 45
scanf(“%d%d”,&m,&n); 65 232
printf(“\n Enter matrix elements:”); The transpose of matrix:
for(i=0;i<m;i++) 24 65
for(j=0;j<n;j++) 45 232
scanf(“%d”,&a[i][j]);
ptr=a;
printf(“\n The matrix elements:\n”);
for(i=0;i<m;i++)
{ for(j=0;j<n;j++)
{
printf(“%d\t”,*(*(ptr+i)+j));
printf(“\n”);
}
}
printf(“\n The transpose of matrix:\n”);
for(i=0;i<n;i++)
{ for(j=0;j<m;j++)
{
printf(“%d\t”,*(*(ptr+j)+i));
printf(“\n”);
}
}
}
192
11.12. Pointers and Strings
As a group of integers is stored in an integer array, a group of characters will be stored in a character
array. This character array is called as a string. Usually, a string constant is a one-dimensional array of
characters terminated by a null character (\0).
11.12.1. Accessing a string by using a pointer
Because a string is one-dimensional array of characters and the array name is the base address, the name
of the character array also becomes the base address. In order to access string with the help of pointer,
do the following:
1. First declare a pointer of type char.
e.g., char *ptr; //A character pointer
2. Initialize the pointer with the name of character array that was declared and initialized earlier.
e.g., char s[]=”Ravi Chandra”;
ptr=s; //holds the base address of character array ‘s’
3. Access each character of string with the help of pointer by incrementing once till the \0 character is
encountered.
e.g., while(*ptr!=’\0’)
{
printf(“%c”,*ptr);
ptr++;
}
Program #19
Write a program to read a string and print a string along with its length
#include<stdio.h>
int stringlength(char *);
main()
{
char s[]=”Ravi Chandra”;
char *ptr;
int len;
cptr=s;
len=stringlength(s);
printf(“\n The length of string=%d”,len);
}
int stringlength(char *s)
{
int count=0;
printf(“\n Given string is=”);
while(*s!=’\0’)
{
printf(“%c”,*s);
count++;
s++;
}
return count;
}
Output:
Given string is= Ravi Chandra
The length of string=12
193
Program #20
Write a program to count number of alphabets, digits, spaces and special characters in a line
of text
#include<stdio.h>
main()
{
char line[100];
char *ptr;
int nalpha,ndigit,nspace,nspecial;
printf(“\n Enter a line of text:”);
scanf(“%[ ^\n]”,line);
ptr=line;
nalpha=nspace=ndigit=nspecial=0;
while(*ptr!=’\0’)
{
if(toupper(*ptr)>=’A’ && toupper(*ptr)<=’Z’)
nalpha++;
else if(*ptr>=’0’&&*ptr<=’z’)
ndigit++;
else if(*ptr= =’ ‘ || *ptr= =’\t’)
nspace++;
else
nspecial++;
}
printf(“\n No.of alphabets=%d”,nalpha);
printf(“\n No.of digits=%d”,ndigits);
printf(“\n No.of spaces=%d”,nspace);
printf(“\n No.of special characters=%d”,nspecial);
}
Output:
Enter a line of text: Master says, “B.Tech 1 st year students are brilliant”
No.of alphabets=41
No.of digits=1
No.of spaces=5
No.of special symbols=4
3. Once a string has been defined using character array, it can’t be initialized to another set of
characters. Unlike character array, such an operation is perfectly valid with char pointer.
Ex: #include<stdio.h>
main()
{
char message[]=”Bye Forever”;
char *p=”Bye forever”;
message=”welcome friend”; // A blunder
p=”Welcome friend”;
}
195
Program #21
Write a program to sort names using array of character pointers.
#include<stdio.h>
main()
{
int n,i,j;
char *names[10],*temp;
for(i=0;i<n;i++)
names[i]=(char *) malloc(15*sizeof(char));
for(i=0;i<n;i++)
{ for(j=i+1;j<n;j++)
{ if(strcmp(names[i],names[j])>0)
{
temp=names[i];
names[i]=names[j];
names[j]=temp;
}
}
}
printf(“\n Names in alphabetical order:”);
for(i=0;i<n;i++)
printf(“%s\t”,names[i]);
}
Output:
Enter how many strings: 5
Enter 5 names:
Master
Minister
Servant
King
Queen
Names in alphabetical order: King Master Minister Queen Servant
A pointer is a special type of variable that holds address as a data item in it. The address is may be
of a variable, or of a constant, or of an array, or of a function, or of another pointer.
A pointer can hold the base address of an array that is collection of elements.
A pointer can be assigned to another pointer (of same type only) directly.
197
11.13. Pointers and const
As we know that const is the keyword that is used to define a symbolic constant that never be changed
throughout the program. E.g., the following is the constant definition:
const float PI=3.1412;
This definition defines a constant PI and this value never be changed through out the program.
11.13.1. Pointer to constant
When we want to deal with a pointer to constant, do the following:
1) Declare a pointer to constant that has the following form:
2) q is a constant pointer.
q will never be changed. But *q will be changed.
From this function definition, it is clear that the function main() takes these two arguments:
argc- an integer argument that holds the total number of arguments that are supplied at command
prompt.
argv- a pointer to a character array or pointer-to-pointer-to character that holds all the strings (or
arguments) supplied at command prompt.
199
When we want to write a program that deals with command line arguments, do the following:
1. First, write the program with the above definition.
2. Compile it successfully.
3. While running it, supply more arguments along with ./a.out. Because we are supplying the
arguments at command prompt ($ in unix), these arguments are called as command line
arguments.
Program #22
Program #23
}
Output:
$cc sumnum.c
$./a.out 12 43 65 34 //suggestion: (separate each string with space)
sum=154
200
11.15. Various pointer declarations
Declare a variable of type float?
float x;
Declare an array that holds 10 floating-point values?
float a[10];
Declare a function that takes a character as argument and returns a character as return value?
char fun(char);
Declare a pointer-to-float?
float *fptr;
Declare a function that returns a pointer-to-float?
float * fun(void);
Declare a pointer-to-function that takes a double argument and returns a double value?
double (*fun)(double);
Declare a pointer-to-10-integer element array?
int (*arrptr)[10];
Declare an array of integer pointers of size 10?
int *a[10];
Declare a pointer to char?
char *cptr;
Declare a pointer-to-pointer to a char?
char **cptr;
Declare a pointer-to-pointer-to-pointer to a char?
char ***cptr;
Declare a function that returns a pointer to the array of floats?
float (*fun())[10];
Declare an array of pointers to a function returning float?
float (*f[10])();
201
4) When we want to assign the address of un-initialized variable to a pointer, then that
assignment also leads to an error.
E.g., int val,*ptr;
ptr=&val; /*Error*/
5) When we want to compare pointers those point to different objects, that comparison lead to
an error
E.g., char name1[20],name2[20];
char *p1=name1;
char *p2=name2;
if(p1>p2)…. /*Error*/
11.17. Conclusion
A pointer is a special type of variable that holds address as a data item in it. The address is may be of a
variable, or of a constant, or of an array, or of a function, or of another pointer. Pointers play key role in
allocating memory as and when it is needed. In order to return more than one value to a calling function,
the concept of pointers is more helpful. It is very much needed in construction of complex data structures
like linked lists, trees and graphs. If we use pointers properly, it is very much helpful in diverse
applications. Its improper use causes the system to be hanged.
202
Structures, Unions,
enumerations and 12
bitfields
0
Chapter Outline
“United we stand, divided we fall."
-- Aesop (620 -560 B.C.) 12.1. Structures.
12.1.1. Introduction.
12.1.2. Working with
structures.
12.1.3. Nested structures.
12.1.4. Structures and arrays.
12.1.5. Structures and
We cannot afford to be separate. . . . We have pointers.
to see that all of us are in the same boat.
12.1.6. Structures and
-- Dorothy Height
functions.
12.2. Unions.
12.3. Enumerated data type.
12.4. Bitfields.
203
12.1.1. Introduction to structures
Suppose we want to represent a record in a file. A record is a collection of data items, each of different
data type. Then we require a different data type that can represent a record. That data type is called as a
structure.
Interview question #1
What is a structure?
Structure is heterogeneous collection of data items stored in contiguous memory
locations referred by same name
This definition has the following parts:
Structure consists of heterogeneous data items. That is, all the data items (or members of
structure) stored in a structure are of different types.
All members are stored in contiguous locations. That is, all members are stored one after other
in successive locations of memory (based on size of type of data items). Of course, fixed
amount of memory is allocated to a structure as a block of bytes.
All data items referred by same name. That is, each data item can be identified with the same
name.
struct <tag>
{
<data type1> <member(s)>;
<data type2> <member(s)>;
:
:
<data typeN> <member(s)>;
};
In this syntax,
struct is the keyword. <tag>, an optional one, serves as a name for this structure. It is used to
declare variable of the same structure type. It should be a valid identifier. The first line of this
declaration is called as structure header.
204
All the members of the structure should be enclosed in curly braces. These members may be
variables, constants, arrays, pointers and even other structures too. If there are more members of
same type, those should be separated with commas. All the declarations in the curly braces
collectively referred to as structure body.
It is important to note that the structure declaration should be ended with a semi colon. The structure
name or members of structure may be omitted, but both, should not be omitted. The declaration of
structure describes prototype or blue print or template of a structure.
Point to ponder #1
Structure declaration never assures the allocation of memory for it; only creation of a variable of that
type of structure assures it.
In this example, the structure student consists of the members: rno and age as integers, name and sex as
of char type and fees as of type float. However, the tag and names of members can be used as ordinary
variables with out any conflict in a program. Usually, this declaration can be placed at the top of source
code file, i.e., before the main().
Point to ponder #2
Declaration of structure outside of all functions never makes it global.
In this syntax,
struct is the keyword. <tag> is the name of the structure. <var1, var2 … varN> should be valid
identifiers.
Ex: struct student stud1,stud2;
The above statement declares two structure variables of type student: stud1, stud2. Usually, this
statement can be placed in body of main(). Once the variables are created, memory will be allocated for
them. The size of each variable is the sum of all the sizes of members of structure.
205
struct student struct student
{ 1 { 2
int rno,age; int rno,age;
char name[15],sex; char name[15],sex;
float fees; float fees;
}stud1,stud2; //creation of variables };
struct student stud1,stud2;
struct student typedef struct student
{ 3 { 4
int rno,age; int rno,age;
char name[15],sex; char name[15],sex;
float fees; float fees;
}; }STUDENTRECORD;
typedef struct student STUDENTRECORD; STUDENTRECORD stud1,stud2;
//renames the structure student //creation of variables
STUDENTRECORD stud1,stud2;
//creation of variables
typedef struct struct
{ { 6
5
int rno,age; int rno,age;
char name[15],sex; char name[15],sex;
float fees; float fees;
}STUDENTRECORD; }stud1,stud2;
STUDENTRECORD stud1,stud2; //creation of variables
//creation of variables
1) In method-1 and method-6, the structure variables are declared before the semicolon at the end of
structure declaration.
2) In method-3,method-4 and method-5, the structure variables are declared with the help of their
respective aliases (duplicate names).
3) The creation of structure variables in method-2 can be done outside of main() or within the main().
Interview question #2
Would the following declaration work?
typedef struct s
{
int a;
float b;
}s;
Yes. We can declare a structure variable same as the name of structure.
Point to ponder #3
The size of a structure variable is not always equal
206 to sum of sizes of all members of structure.
Interview question #3
What is the purpose of typedef?
The typedef is the keyword that is used to define new data types that are equivalent to existing data
types. Once a user-defined data type is declared, then new variables, arrays, structures and so on can
be declared in terms of these new data types.
Interview question #4
Why the ‘sizeof’ operator does sometimes results larger size than the calculated size for a
structure?
Padding (also called as buffering) is an important issue associated with structures. There may be some
alignment requirements enforced by the environment. E.g., ints may require to be aligned at even
numbered addresses and longs at address numbers divisible by 4. This is because, enforcing such
alignment boundaries help increase the access speed of the data stored in the memory and treat them
as a unit. E.g., in 8086 systems, a word size is 2 bytes. If a word is stored (i.e., aligned to start) in an
even address, the bytes can be read at a time. On the other hand, if it starts at an odd address, it is
accessed by two reads- obvious efficiency/time degradation. This leads to padding of bytes in the
structure. Due to this padding, the value returned by sizeof may not equal to sum of sizes of individual
structure members.
In this syntax,
<structure_variable> is the variable that is declared earlier.
<member_name> is the name of the member inside the body of structure.
Ex: The members of structure student are accessed with the help of structure variable stud1 and stud2 as
follows:
stud1.rno=26; stud2.rno=4;
stud1.age=18; stud2.age=18;
strcpy(stud1.name,”vamsee”); strcpy(stud2.name,”Sujitha”);
stud1.sex=’m’; stud2.sex=’f’;
207
stud1.fees=27500.00; stud2.fees=27500.00;
stud1
sizeof(stud1)=2+2+15+1+4=24 bytes
rno (2bytes) age (2 bytes) name(15 bytes) sex (1 byte) fees(4 bytes)
13 18 Balaji m 27500.00
Note:
A structure variable may be initialzed by means of assigning another structure variable of similar type.
E.g.,
struct student stud3=stud2;
assigns the data of stud2 to stud3. But, the structure variable at the right side of the assignment
statement has to be declared and initialized before the assignment.
By using scanf() statement
The input statement scanf() can be used to initialize the members of structure variables. scanf() function
can take members as arguments. Each member can be preceded with dot operator that is preceded with
structure variable. While reading members from keyboard, there is no necessity of reading these in the
same order as they are in structure declaration.
208
Ex: The structure variable stud1 of structure type student can be used to read all the members of
structure as follows:
scanf(“%d%d%s\n%c%f”,&stud1.rno,&stud1.age,stud1.name,&stud1.sex,&stud1.fees);
Program #1 Program #2
/* program to read 3 student details and /* program to read 2 Employee details and
print them*/ print them*/
#include<stdio.h> #include<stdio.h>
struct student main()
{ {
int rno,age; typedef struct employee
char name[15],sex; {
float fees; int empno,experience;
}; float salary;
main() char *ename,*designation;
{ }EMPRECORD;
struct student stud1,stud2;
struct student EMPRECORD e1,e2,e3;
stud3={3,18,”Sirisha”,’f’,27500.00};
printf(“\n enter first student rno , name , age , printf(“\n enter first employee number, name,
sex and fees”); designation, salary and work experience”);
scanf(“%d%s%d\n%c%f”,&stud1.rno, scanf(“%d%s%s%f%d”,&e1.empno,
stud1.name, &stud1.age, &stud1.sex, e1.ename, e1.designation, &e1.salary,
&stud1.fees); &e1.experience);
printf(“\n enter second student rno , name , age printf(“\n enter second employee number,
, sex and fees”); name, designation, salary and work
scanf(“%d%s%d\n%c%f”,&stud2.rno, experience”);
stud2.name, &stud2.age, &stud2.sex, scanf(“%d%s%s%f%d”,&e2.empno,
&stud2.fees); e2.ename, e2.designation, &e2.salary,
&e2.experience);
printf(“\n First student details”);
printf(“\n Roll number=%d”,stud1.rno); printf(“\n First employee details”);
printf(“\n Name=%s”,stud1.name); printf(“\n Employee number=%d”,e1.empno);
printf(“\n Age=%d”,stud1.age); printf(“\n Name=%s”,e1.name);
printf(“\n Sex=%c”,stud1.sex); printf(“\n Designation=%s”,e1.designation);
printf(“\n Fees=%f”,stud1.fees); printf(“\n Salary=%f”,e1.salary);
printf(“\n Work Experience=%d”,e1.experience);
printf(“\n Second student details”);
printf(“\n Roll number=%d”,stud2.rno); printf(“\n second employee details”);
printf(“\n Name=%s”,stud2.name); printf(“\n Employee number=%d”,e2.empno);
printf(“\n Age=%d”,stud2.age); printf(“\n Name=%s”,e2.name);
printf(“\n Sex=%c”,stud2.sex); printf(“\n Designation=%s”,e2.designation);
printf(“\n Fees=%f”,stud2.fees); printf(“\n Salary=%f”,e2.salary);
printf(“\n Work Experience=%d”,e2.experience);
printf(“\n Third student details”);
printf(“\n Roll number=%d”,stud3.rno); e3=e2;
printf(“\n Name=%s”,stud3.name); printf(“\n copied employee details”);
printf(“\n Age=%d”,stud3.age); printf(“\n Employee number=%d”,e3.empno);
printf(“\n Sex=%c”,stud3.sex); printf(“\n Name=%s”,e3.name);
printf(“\n Fees=%f”,stud3.fees); printf(“\n Designation=%s”,e3.designation);
printf(“\n Salary=%f”,e3.salary);
} printf(“\n Work Experience=%d”,e3.experience);
}
209
Interview question #5
What are the differences between array and structures?
Array Structure
An array is homogeneous collection of A structure is heterogeneous collection of data
elements stored in contiguous memory items stored in contiguous memory locations
locations referred by common name. referred by common name.
Individual data items in an array are called as Individual data items in a structure are called
elements. as members.
An array declaration reserves enough The creation of structure variables reserves
memory space for its elements. enough memory space for members of
structure.
There is no keyword to represent arrays but The keyword struct tells us that we are
the square brackets[] preceding the variable dealing with the structures.
name tells us that we are dealing with arrays.
Initialization of elements can be done during Initialization of members can be done only
array declaration. after the creation of structure variables.
The general format: The general format:
<data type> <array_name>[size]; struct <tag>
{
Ex: int a[10]; <data type1> <member(s)>;
<data type2> <member(s)>;
:
:
<data typeN> <member(s)>;
};
struct <tag> <var1,var2…varN>;
Array size is known at the time of declaration. The members and their respective data types
are known at the time of declaration.
An array name represents the address of The structure name is not the base address.
starting element (or base address).
The array elements are accessed by its name The members of the structure are accessed by
followed by the square brackets [] within using the dot operator. The following form will
which the index is placed. be helpful to access the members:
Ex: a[3] is used to access the 4th element in <structure_variable>.<member_name>
the array. Ex: stud1.age is used to access the member
age.
An array can not have bit fields. 210A structure can have bit fields.
12.1.3. Structure within a structure (Nested structure)
A structure can also be placed as a member in another structure. This can be done in two ways:
1. Place entire structure declaration along with structure variable in a structure (or)
2. Declare structure individually and place the structure variable in another structure.
The following example demonstrates this:
Method-1 Method-2
struct student //outer structure struct date_of_birth
{ {
int rno,age; int dd,mm,yy;
char name[15],sex; };
float fees; struct student
struct date_of_birth //Inner structure {
{ int rno,age;
int dd,mm,yy; char name[15],sex;
}dob; float fees;
}stud1,stud2; struct date_of_birth dob;
//structure variable of structure date_of_birth
}stud1,stud2;
Once the nested structure is declared, the inner structures become the members of outer structure. By
using the structure variable of outer structure, the inner structures variables get accessed. As dot operator
indicates membership, it should be used in between outer structure variable and inner structure variables
in order to access the members of inner structure.
e.g., In order to access the members of structure date_of_birth, the structure variables dob and stud1 are
used as follows:
stud1.dob.dd=8;
stud1.dob.mm=3;
stud1.dob.yy=1983;
Program #3 Program #4
/* program to read 3 student details and /* program to read 2 Employee details and
print them*/ print them*/
#include<stdio.h> #include<stdio.h>
struct student main()
{ {
int rno,age; struct address
char name[15],sex; {
float fees; char *street,*area,*city;
struct date_of_birth long int pincode;
{ };
int dd,mm,yy; typedef struct employee
}dob; {
}; int empno,experience;
main() float salary;
{ char *ename,*designation;
struct student stud1,stud2; struct address add;
struct student stud3={14,18,”amrutha”, }EMPRECORD;
’f’,27500.00,12,3,1991};
printf(“\n enter first student rno , name , age , EMPRECORD e1,e2,e3;
sex,fees”);
scanf(“%d%s%d\n%c%f”,&stud1.rno, printf(“\n enter first employee number, name,
stud1.name, &stud1.age, &stud1.sex, designation, salary and work experience”);
&stud1.fees); scanf(“%d%s%s%f%d”,&e1.empno,
211
printf(“\n Enter date-of-birth”); e1.ename, e1.designation, &e1.salary,
scanf(“%d%d%d”,&stud1.dob.dd,&stud1.dob.m &e1.experience);
m,&stud1.dob.yy);
printf(“\n Enter address ( street , area , city ,
printf(“\n enter second student rno , name , pincode )”);
age , sex and fees”); scanf(“%s%s%s%ld”,e1.add.street,e1.add.area,
scanf(“%d%s%d\n%c%f”,&stud2.rno, e1.add.city, &e1.add.pincode);
stud2.name, &stud2.age, &stud2.sex,
&stud2.fees); printf(“\n enter second employee number, name,
printf(“\n Enter date-of-birth”); designation, salary and work experience”);
scanf(“%d%d%d”,&stud2.dob.dd,&stud2.dob.m scanf(“%d%s%s%f%d”,&e2.empno, e2.ename,
m,&stud2.dob.yy); e2.designation, &e2.salary, &e2.experience);
printf(“\n Enter address ( street , area , city ,
printf(“\n First student details”); pincode )”);
printf(“\n Roll number=%d”,stud1.rno); scanf(“%s%s%s%ld”,e2.add.street,e2.add.area,
printf(“\n Name=%s”,stud1.name); e2.add.city, &e2.add.pincode);
printf(“\n Age=%d”,stud1.age);
printf(“\n Sex=%c”,stud1.sex);
printf(“\n Fees=%f”,stud1.fees); printf(“\n First employee details”);
printf(“\n Date-of-birth = %d / %d / % d ” , printf(“\n Employee number=%d”,e1.empno);
stud1.dob.dd, stud1.dob.mm, stud1.dob.yy); printf(“\n Name=%s”,e1.name);
printf(“\n Designation=%s”,e1.designation);
printf(“\n Second student details”); printf(“\n Salary=%f”,e1.salary);
printf(“\n Roll number=%d”,stud2.rno); printf(“\n Work Experience=%d”,e1.experience);
printf(“\n Name=%s”,stud2.name); printf(“\nstreet=%s\nArea=%s\nCity=%s\nPinco
printf(“\n Age=%d”,stud2.age); de=%ld”,e1.add.street,e1.add.area,e1.add.city,
printf(“\n Sex=%c”,stud2.sex); e1.add.pincode);
printf(“\n Fees=%f”,stud2.fees);
printf(“\n Date-of-birth = %d / %d / % d ” , printf(“\n second employee details”);
stud2.dob.dd, stud2.dob.mm, stud2.dob.yy); printf(“\n Employee number=%d”,e2.empno);
printf(“\n Name=%s”,e2.name);
printf(“\n Third student details”); printf(“\n Designation=%s”,e2.designation);
printf(“\n Roll number=%d”,stud3.rno); printf(“\n Salary=%f”,e2.salary);
printf(“\n Name=%s”,stud3.name); printf(“\n Work Experience=%d”,e2.experience);
printf(“\n Age=%d”,stud3.age); printf(“\nstreet=%s\nArea=%s\nCity=%s\nPinco
printf(“\n Sex=%c”,stud3.sex); de=%ld”,e2.add.street,e2.add.area,e2.add.city,
printf(“\n Fees=%f”,stud3.fees); e2.add.pincode);
printf(“\n Date-of-birth = %d / %d / % d ” , e3=e2;
stud3.dob.dd, stud3.dob.mm, stud3.dob.yy);
printf(“\n copied employee details”);
} printf(“\n Employee number=%d”,e3.empno);
printf(“\n Name=%s”,e3.name);
printf(“\n Designation=%s”,e3.designation);
printf(“\n Salary=%f”,e3.salary);
printf(“\n Work Experience=%d”,e3.experience);
printf(“\nstreet=%s\nArea=%s\nCity=%s\nPinco
de=%ld”,e3.add.street,e3.add.area,e3.add.city,
e3.add.pincode);
}
Note: A structure can not be nested inside the same structure. For example,
struct student
{ int rno,age;
char name[15],sex;
float fees;
struct student stud1; //invalid statement
}; is not a valid nested structure.
212
12.1.4. Arrays and structures
12.1.4.1. Array within a structure
An array can also be placed as a member in the structure declaration. It can be initialized and accessed as
follows:
Ex: /*program to read 3 subjects marks, calculate grade on sum of these marks*/
#include<stdio.h>
#include<string.h>
struct student
{
int rno;
char name[15],grade[15];
int marks[3]; //array with in a structure
int total;
}stud1;
main()
{
printf(“\n Enter student rno,name”);
scanf(“%d%s”,&stud1.rno,stud1.name);
printf(“\n Enter student 3 subjects marks:”);
for(i=0;i<3;i++)
scanf(“%d”,&stud1.marks[i]);
stud1.total=0;
for(i=0;i<n;i++)
{
printf(“\nSubject%d=%d”,i+1,stud1.marks[i]);
stud1.total+=stud1.marks[i];
}
213
Program #5 Program #6
214
12.1.5. Structures and pointers
12.1.5.1. Pointer-to-structure
The members of a structure can not only be accessed with the help of structure variable, but also with a
pointer to a structure. The following example demonstrates this:
Ex: 1. First, create a pointer to the structure as follows:
struct student
{ int rno;
char name[15],sex;
float fees;
struct date_of_birth
{
int dd,mm,yy;
}dob;
};
struct student *stdptr; //pointer to structure
2. Secondly, Initialize that structure pointer with the address of a structure variable.
struct student std1;
stdptr=&std1; //initialization
Point to ponder #4
Pointer-to-structure holds the address of first byte of first member in structure declaration.
3. Finally, access the members of that structure using structure pointer as follows:
Method-1 (by using arrow operator) Method-2 (by using Indirection operator)
stdptr->rno=28 (*stdptr).rno=28
strcpy(stdptr->name,”Harish”); strcpy((*stdptr).name,”Harish”);
stdptr->sex=’m’; (*stdptr).sex=’m’;
stdptr->fees=27500.00; (*stdptr).fees=27500.00;
stdptr->dob.dd=12; (*stdptr).dob.dd=12;
stdptr->dob.mm=03; (*stdptr).dob.mm=03;
stdptr->dob.yy=1991; (*stdptr).dob.yy=1991;
Interview question #6
The way mentioning the array name or function name with out [] or () yields their base
address, what do you obtain on mentioning structure name?
The entire structure itself and not its base address.
215
12.1.5.2. Self-referential structures
Interview question #7
What is a self-referential structure?
Self-referential structure is the structure that contains a pointer that points to the same structure as a
member. E.g., the structure declaration
struct Node
{
int data;
struct Node *next;
};
declares a type struct Node. The type struct Node has two members: data of type int and a pointer
member next. The member next points to a structure of type struct Node- a structure of the same type
as the one being declared here, hence the term “self-referential structure”. The member next is
referred to as a link- i.e., the next can be used to tie a structure of type struct node to another
structure of the same type.
Self-referential structures can be linked together to form useful data structures such as linked
lists, trees, graphs, stacks and queues.
if(firstnode==NULL)
firstnode=newnode;
else
prevnode->next=newnode;
prevnode=newnode;
scanf(“%d”,&value);
}
printf(“\n The Linked list:Head->”);
while(firstnode!=NULL)
{ printf(“%d->”,firstnode->data);
firstnode=firstnode->next;
}
printf(“NULL”);
}
216
12.1.5.3. Structure pointer and dynamic memory allocation
Memory is allocated dynamically for structure pointer also same as to integer pointers to hold multiple
values. However, when the memory is allocated, the generic pointer that is returned by malloc() should be
converted to the structure pointer. The following program demonstrates this concept:
/* program to read multiple student details and print them*/
#include<stdio.h>
struct student
{
int rno,age;
char name[15],sex;
float fees;
struct date_of_birth
{
int dd,mm,yy;
}dob;
};
main()
{
struct student *stud;
int i,n;
printf(“\n Howmany records:”);
scanf(“%d”,&n);
for(i=0;i<n;i++)
stud=(struct student *)malloc(n*sizeof(struct student));
for(i=0;i<n;i++)
{
printf(“\n enter student %d rno , name , age , sex,fees”,i+1);
scanf(“%d%s%d\n%c%f”,&stud[i].rno, stud[i].name, &stud[i].age, &stud[i].sex, &stud[i].fees);
printf(“\n Enter date-of-birth”);
scanf(“%d%d%d”,&stud[i].dob.dd,&stud[i].dob.mm,&stud[i].dob.yy);
}
printf(“\n======================================================”);
printf(“\nRno\tName\tAge\tSex\tfees\tdate-of-birth”);
printf(“\n======================================================”);
for(i=0;i<n;i++)
{
printf(“\n%d\t%s\t%d\t%c\t%f\t%d/%d/%d”, std[i].rno,stud[i].name,stud[i].age,stud[i].sex,
stud[i].fees,stud[i].dob.dd,stud[i].dob.mm, stud[i].yy);
}
printf(“\n======================================================”);
}
217
/* program to sort multiple student details based on rank*/
#include<stdio.h>
struct student
{
int rno,rank;
char name[15];
};
void sort(struct student *[],int);
void swap(struct student *,struct student *);
main()
{
struct student *stud[10]; //array of structure pointers
int i,n;
printf(“\n Howmany records:”);
scanf(“%d”,&n);
for(i=0;i<n;i++)
{
stud[i]=(struct student *)malloc(sizeof(struct student); //allocate memory individually
printf(“\n enter student %d rno , name and rank”,i+1);
scanf(“%d%s%d”,&stud[i]->rno,stud[i]->name,&stud[i]->rank);
}
sort(stud,n);
}
void sort(struct student *stud[],int n)
{
for(i=0;i<n;i++)
{ for(j=i+1;j<n;j++)
{ if(stud[i]->rank>=stud[j]->rank)
swap(stud[i],stud[j]);
}
}
}
218
#include<stdio.h>
struct date
{
int day,month,year;
};
void display(struct date);//function prototype
main()
{
struct date today;
today.day=10;
today.month=3;
today.year=2009;
display(today); //function call
}
void display(struct date one) //function defintion
{
printf(“%d\t%d\t%\td”,one.day,one.month,one.year);
}
COMPLEX add(COMPLEX,COMPLEX);
COMPLEX sub(COMPLEX,COMPLEX);
COMPLEX mul(COMPLEX,COMPLEX);
COMPLEX div(COMPLEX,COMPLEX);
main()
{
COMPLEX c1,c2,c3;
220
12.1.6.3. Array of structures as an argument
As an array can be passed as an argument, an array of structures can also be passed as an argument.
Because we are passing the name of the array as an argument and the array name acts as reference, this
method of passing an array argument is the call-by-reference.
/* program to read multiple student details and print them*/
#include<stdio.h>
struct student
{ int rno,age;
char name[15],sex;
float fees;
struct date_of_birth
{
int dd,mm,yy;
}dob;
};
void display(struct student [],int);
main()
{ struct student stud[15];
int i,n;
printf(“\n Howmany records:”);
scanf(“%d”,&n);
for(i=0;i<n;i++)
{ printf(“\n enter student %d rno , name , age , sex,fees”,i+1);
scanf(“%d%s%d\n%c%f”,&stud[i].rno, stud[i].name, &stud[i].age, &stud[i].sex, &stud[i].fees);
printf(“\n Enter date-of-birth”);
scanf(“%d%d%d”,&stud[i].dob.dd,&stud[i].dob.mm,&stud[i].dob.yy);
}
display(stud,n);
}
void display(struct student stud[15],int n)
{ printf(“\n=================================================”);
printf(“\nRno\tName\tAge\tSex\tfees\tdate-of-birth”);
printf(“\n=================================================”);
for(i=0;i<n;i++)
{printf(“\n%d\t%s\t%d\t%c\t%f\t%d/%d/%d”,std[i].rno,stud[i].name,stud[i].age,stud[i].sex,
stud[i].fees, stud[i].dob.dd,stud[i].dob.mm, stud[i].yy);
}
printf(“\n=================================================”);
}
221
/*program to exchange two numbers /*program to exchange two numbers
(call-by-value)*/ (call-by-reference)*/
struct exchange
{ struct exchange
int a,b; {
}; int a,b;
void swap(struct exchange); //function prototype };
main() void swap(struct exchange*);
{ //function prototype
struct exchange ex; main()
ex.a=20; {
ex.b=10; struct exchange ex;
printf(“\nBefore swap a=%d\tb=%d”,ex.a,ex.b); ex.a=20;
swap(ex); //function call ex.b=10;
printf(“\nAfter swap a=%d\tb=%d”,ex.a,ex.b); printf(“\nBefore swap a=%d\tb=%d”,ex.a,ex.b);
} swap(&ex);
void swap(struct exchange e)//function definition //function call: address as an argument
{ printf(“\nAfter swap a=%d\tb=%d”,ex.a,ex.b);
int temp; }
temp=e.a; //function definition
e.a=e.b; void swap(struct exchange *e)
e.b=temp; {
} int temp;
temp=e->a;
e->a=e->b;
e->b=temp;
}
12.1.6.5. Pointer-to-structure as a return value
Returning pointer-to-structure has the same syntax as returning pointer to ordinary variable. The
following program demonstrates this:
/*program to print the details of highest salary paid employee*/
#include<stdio.h>
main()
{
struct address
{
char *street,*area,*city;
long int pincode;
};
typedef struct employee
{
int empno,experience;
float salary;
char *ename,*designation;
struct address add;
}EMPRECORD;
EMPRECORD e[10];
EMPRECORD *temp;
int i,n;
222
printf(“\n Howmany records:”);
scanf(“%d”,&n);
for(i=0;i<n;i++)
{
printf(“\n enter %d employee number, name, designation, salary and work
experience”,i+1);
scanf(“%d%s%s%f%d”,&e[i].empno, e[i].ename, e[i].designation, &e[i].salary,
&e[i].experience);
}
void insert(struct student s[],int n)
{
struct student new;
int pos,i;
printf("\n Enter new student details(rno,name,rank and date of birth):");
scanf("%d%s%d%d%d%d",&new.rno,new.name,&new.rank,&new.dob.day,&new.dob.month,
&new.dob.year);
printf("\n Enter the position:");
scanf("%d",&pos);
for(n++,i=n-1;i>pos-1;i--)
s[i]=s[i-1];
s[pos-1]=new;
display(s,n);
}
224
void delete(struct student s[],int n)
{
int pos,i;
printf("\n Enter the position:");
scanf("%d",&pos);
for(i=pos-1;i<n;i++)
s[i]=s[i+1];
display(s,n);
}
void search(struct student s[],int n)
{
int rollnum,flag=0,pos,i;
printf("\n Enter the roll number to be searched:");
scanf("%d",&rollnum);
for(i=0;i<n;i++)
{
if(s[i].rno==rollnum)
{
pos=i;
flag=1;
break;
}
}
if(flag==1)
{
printf("\n The student details are:");
printf("%d\t%s\t%d\t%d/%d/%d",s[pos].rno,s[pos].name,s[pos].rank,s[pos].dob.day,
s[pos].dob.month,s[pos].dob.year);
}
else
printf("\n The record is not found");
}
2) /* A program to add two matrices using structures*/
#include<stdio.h>
typedef struct
{
int **data;
int row,col;
}matrix;
main()
{
matrix m1,m2,m3;
int i,j;
printf("\n Enter first matrix order:");
scanf("%d%d",&m1.row,&m1.col);
printf("\n Enter second matrix order:");
scanf("%d%d",&m2.row,&m2.col);
if(m1.row!=m2.row||m1.col!=m2.col)
printf("\n Sorry, addition is not possible");
else
{
m1.data=(int **)malloc(m1.row*sizeof(int));
for(i=0;i<m1.row;i++)
m1.data[i]=(int *)malloc(m1.col*sizeof(int));
225
printf("\n Enter first matrix elements:");
for(i=0;i<m1.row;i++)
for(j=0;j<m1.col;j++)
scanf("%d",&m1.data[i][j]);
m2.data=(int **)malloc(m2.row*sizeof(int));
for(i=0;i<m1.row;i++)
m2.data[i]=(int *)malloc(m2.col*sizeof(int));
m3.row=m1.row;
m3.col=m1.col;
m3.data=(int **)malloc(m3.row*sizeof(int));
for(i=0;i<m3.row;i++)
m3.data[i]=(int *)malloc(m3.col*sizeof(int));
12.2.1. Unions
Interview question #8
What is a union?
Union is also a user-defined data type like a structure, except that it provides a way to manipulate
different kinds of data in a single area of storage.
For different situations in a program, some variables may not be relevant, but other variables
are- so a union shares the space instead of wasting storage on variables that are not being used. The
members of a union can be of any data type. The number of bytes used to store a union must be at
least enough to hold the largest member. In most cases, unions contain two or more data types. Only
one member, and thus one data type, can be referenced at a time.
226
12.2.1. Working with unions
In order to work with a union, one should do these things:
Declare its prototype.
Create variable(s) of that union.
Access the members of that union.
227
In this syntax,
union is the keyword. <tag> is the name of the union. <var1, var2 … varN> should be valid identifiers.
Ex: union student s1,s2;
The above statement defines two union variables of type student: s1, s2. Usually, this statement can be
placed in body of main().
1) Initialization
Though we can initialize all the members of a union at a time, only one member is always active.
Because all the members share the same memory location, the value of one member overwrites
the value of other member that is there in memory. The following program demonstrates this:
#include<stdio.h>
main()
{
union student
{
int rno,age;
char name[15],sex;
float fees;
}s1;
s1.rno=6;
strcpy(s1.name,”Divya”);
s1.age=18;
s1.sex=’f’;
s1.fees=27500.00;
printf(“%d\t%s\t%d\t%c\t%f”,s1.rno,s1.name,s1.age,s1.sex,s1.fees);
}
Output: only the value of fees gets printed properly. All others are garbage values and zeros.
228
2) Size of a union
The size of a union is always the size of the largest member in that. The following program
demonstrates this:
#include<stdio.h>
main()
{
union student
{
int rno,age;
char name[15],sex;
float fees;
}s1;
printf(“\nsizeof union=%d bytes”,sizeof(s1));
}
Output: sizeof union=15 bytes
Note:
1) A union can also be placed as a member in a structure. How ever, it should be placed after all the
members of structure are declared.
2) A pointer to a union can also be declared. All the members of a union can also be accessed by
using pointer with the help of -> operator.
3) Union can also be initialized when the union variable is declared. But, unlike structures, it can be
initialized only with a value of the same type as the first member. E.g.,
union item
{
int itemno;
float price;
int qty;
};
union item i1={23}; is valid. But, the declaration
union item i1={235.46} is not valid.
Interview question #9
Can a union be self-referenced?
No, a union can not be self-referenced. How ever, a union can contain a pointer to that union as a
member in it. Hence, the following declaration is perfectly valid:
union list
{
long int data;
union list *next;
};
For the above union type, only 8 bytes of memory will be allocated. These 8 bytes of memory can
be shared by both data and pointer next one after other. Hence, there are chances that the values
of these members can overlap each other which lead to data corruption.
229
Interview question #10
What are the differences between structures and unions?
Structure Union
Each member in a structure occupies and uses All the members of a union use the same
its own memory space. memory space.
The keyword struct tells us that we are The keyword union tells us that we are
dealing with structures. dealing with unions.
More memory space is required since each Less memory space is required since all
member is stored in a separate memory members share the same memory location.
location.
The general format: The general format:
struct <tag> union <tag>
{ {
<data type1> <member(s)>; <data type1> <member(s)>;
<data type2> <member(s)>; <data type2> <member(s)>;
: :
: :
<data typeN> <member(s)>; <data typeN> <member(s)>;
}; };
struct <tag> <var1,var2…varN>; union <tag> <var1,var2…varN>;
All the members of a structure can be Only first member of union can be initialized.
initialized. e.g., union student stud1 = {46,18,”ravi
kumar”,’m’,27500.00}; is invalid.
e.g., struct student stud1 = {46,18,”ravi
But, union student stud1={46}; is valid.
kumar”,’m’,27500.00};
Any member can be accessed at any time with Since only one member can be handled at a
out loss of data. time, care should be taken to retrieve the data
type from the union variable as the type most
recently used.
Different interpretations for the same memory Different interpretations for the same memory
location are not possible. location are possible.
230
12.3. Enumerated data type
Interview question #11
What is an enumerated data type?
An enumerated data type is a set of values represented by identifiers called enumerators. The
values of each enumerator can be specified when the type is specified. An enumerated data type
is declared as follows:
enum <tag> {<enumerator-1>,<enumerator-2>,<enumerator-3>,…,<enumerator-n>};
In this syntax,
enum is the keyword. <tag> is the name of the enumerated data type.
<enumerator-1>,<enumerator-2>…<enumerator-n> are valid identifiers. All the enumerators
should be separated with commas and enclosed in curly braces.
Ex: enum color{red,green,blue};
Once the enumerators are declared in an enumerated data type, each enumerator holds an integer
constant. Usually, these constant start from 0. So, from the above example, it is clear that the
enumerators hold these constants: red=0, green=1, blue=2
#include<stdio.h>
main()
{
enum color{red,green,blue};
printf(“Red=%d\tGreen=%d\tBlue=%d”,red,green,blue);
}
Output: Red=0 Green=1 Blue=2
We can also specify our own integer constants to enumerators as follows:
#include<stdio.h> #include<stdio.h>
main() main()
{ {
enum color{red,green=234,blue}; enum color{red=12,green=234,blue=423};
printf(“Red=%d\nGreen=%d\nBlue=%d”, printf(“Red=%d\nGreen=%d\nBlue=%d”,red,green,blue);
red,green,blue); }
} Output: Red=12
Output: Red=0 Green=234
Green=234 Blue=423
Blue=235
Note: we can assign enumerators to the variables of enumerated data type and variables of int type also
as follows:
enum day
{sun,mon,tue,wed,thu,fri,sat
} day1,day2;
day1=wed; // day1 holds the value of enumerator-wed. i.e., day1=3
day2=sat; // day2 holds the value of enumerator- sat. i.e., day2=6
int val=wed; // val holds the value of enumerator-wed. i.e., val=3
231
Point to ponder #4
The values of enumerators are fixed; they can never be changed throughout program. When assigned
to a variable, the value in variable can be changed. But that change won’t affect enumerator.
12.4. Bitfields
If a variable in a program takes only one of two values: 0 or 1, we really need a single bit to store it.
Similarly, if a variable is to take values from 0 to 3, then two bits are sufficient to store these values. And
if a variable is to take values from 0 through 7, then three bits will be enough, and so on.
Why do we waste an entire integer (16 bits) when one or two or three bits are sufficient for a variable
to take a value? Well, C provides a concept, i.e., bit field that is used to pack a value in a less number of
bits.
232
Interview question #13
What is a bit field?
C enables programmers to specify the number of bits in which an unsigned or int member of a
structure or union is stored. This is referred to as a bit field. Bit fields enable better memory utilization
by storing data in the minimum number of bits required. Bit field members must be declared as int or
unsigned.
Ex: struct employee
{
unsigned gender:1;
unsigned mar_status:2;
};
The colon in the above declaration tells the compiler that we are talking about bit fields and the
number after it tells how many bits to allot for the field. Once we have established a bit field, we can
refer to it just like other structure member.
Chapter Outline
“Pain is never permanent."
-- St. Teresa of Avila 13.1. Introduction.
13.5. Error-handling
234
13.1. Introduction
Storage of data in variables and arrays is temporary- all such data are lost when a program terminates.
Files are used for permanent maintenance of large amounts of data. Computers store files on secondary
storage devices, especially on disks. Usually, a file is a collection of related records. Each record is a
collection of data items (or fields). E.g., a company maintains employee payroll file, which stores records
about the salaries paid to all employees. Each record in that file may include the fields like empno, name,
department, salary … etc. All these records in payroll file should be organized in such a way that each
record should be retrieved very easily.
To facilitate the retrieval of specific records from a file, at least one field in each record is chosen as
a record key. A record key identifies a record as belonging to a particular person or entity. E.g., empno
in payroll file is used to retrieve the specific record easily.
Interview question #1
What is a file?
“A file is a collection of data that is stored permanently on disk”.
(or)
“A file is a stream of bytes of arbitrary length, which is used to hold data”.
A file is a sequence of bytes that will be implemented by the operating system to provide persistent (or
permanent) storage. Each file is owned by some user and is protected from unauthorized use by other
users. File provides reliable data storage and it will provide simple, easy-to-use operations to access
data.
Interview question #2
Why file is also called as an “external data structure”?
Data structure (or Abstract Data Type) is an organized collection of data and operations on that data. It
gives the model of particular organization of data. File is also a data structure that deals with data that
is stored on external storage device (i.e., disk). The data in an external storage device (i.e., secondary
memory) can be brought to internal storage device (i.e., primary memory), various operations such as
read, write and append can be carried out there in primary memory and the changed data can be
brought back to external storage device. Because file is very helpful in doing these activities on
external storage device, we can call it as an “external data structure”.
Interview question #3
Why do we need files?
We need files in order
1. To store data permanently. i.e., the content in the file can never be lost even after program
termination. It can be recalled as and when it is needed.
2. To maintain large amount of data. i.e., it is easy to handle voluminous data during execution.
3. To make disk user-friendly. i.e., the complex interface of disk can be converted to user-friendly
interface by using file so that user can interact with it.
4. To have its storage capacity more. i.e., a file can have its content till there is no space in
storage device.
235
13.2. Types of files
Types of Files
There are two ways to link and access files in a program. These are: by means of library functions and by
means of system-calls of operating system.
1. The files linked and accessed through the library functions are known as stream-oriented files.
These are also called as high-level files, since these involve high-level (programming language
level) functions.
2. It is also possible to link and access files directly by means of an operating system. The system
calls of operating system connect the files with the program. The files linked and accessed using
system calls known as system-oriented files. These are also known as low-level files because
low-level (system level) commands or functions are involved.
Stream-oriented files are supported by C library functions which are common for all operating systems.
But system-oriented files are not at all common to all operating systems because system calls for each
operating system are different.
Stream-oriented files are easier to work with than the system-oriented files because the same library
functions may be used regardless of the device or disk files are involved. Also, the data can be stored in a
manageable form such as one byte at a time.
Stream-oriented files can be subdivided into two categories: text files and binary files. The text files
consist of consecutive characters. These characters can be interpreted as individual data items or as
components of strings or numbers. The manner in which these characters are interpreted is determined
either by the particular library functions used to transfer the information, or by the format specifiers those
start with % with in the library function.
The binary files organize data into blocks containing contiguous bytes of information. These blocks
represent more complex data structures such as arrays and structures. A separate set of library functions
is available for processing these binary files. These library functions provide single instructions that can
transfer entire arrays or structures to or from files. These binary files are very useful to handle file
containing machine language contents, e.g., .exe or .com files.
236
To understand the stream-oriented files, first, it is necessary to understand the concept of stream.
Interview question #3
What do you mean by a stream?
The ANSI standard I/O functions support the stream-oriented files in which input and output are
treated as a continuous stream of bytes. A stream is a source or destination of data that may be
associated with a disk or other I/O devices. The source stream provides data to a program and it is
known as input stream. The destination stream receives the output from the program and is known
as output stream. The generic term I/O stream is used for any file, device or facility on which a
program may perform I/O operations.
An I/O stream can be treated as a flowing sequence of characters. It can be a text stream or
binary stream. A text stream is a sequence of lines of text. In a text stream, each character can be
represented by using ASCII. Each line consists of zero or more characters and a terminating new line
character. ANSI C allows atleast 254 characters in a line. The characters in a text stream may be
modified, added or deleted during I/O operations. A file that contains data written using a text stream
is called a text file. Input from/output to a terminal are mostly performed using text streams. Hence,
a terminal is also associated with the I/O streams in text file.
A binary stream is a sequence of unprocessed bytes. A binary stream, represents raw data
without any conversion unlike a text stream. For example, the character ‘\n’ in a text stream is mapped
to carriage return and line feed. But, in a binary stream, it is never modified. If the data are only stored
as backup for the purpose of reading them afterwards, it is more efficient in using binary streams. A
binary file contains data written in it using binary stream.
All the stream-oriented files (whether text files or binary files) are of two types based on the way of
accessing them. Sequential-access files are the stream-oriented files in which the data can be accessed
sequentially. E.g., if a file contains 100 records and we want to access 57 th record in that file. Then we
should first access all the previous 56 records in sequence and then only we can access 57 th record.
Random-access files are the stream-oriented files in which the data can be accessed directly.
E.g., if a file contains 100 records and we want to access 57 th record in that file, then it is not necessary to
access all the previous 56 records first. We can directly place our file pointer to 57 th record directly. The
random-access files are called as direct-access files.
In order to process the sequential-access file, first we should learn basic operations on files:
237
13.3. Basic operations on files
The standard library in C has many file I/O functions. The file-handling functions in C are easy to use,
powerful and complete. The console I/O functions such as scanf() and printf() help the user to read
from keyboard and write to monitor (The term console refers to keyboard-monitor pair). But the file I/O
functions read from a file and write to another file (or to the same file).
File I/O is always done in a program in the following sequence:
1. Open the file.
2. Read from or write to the file.
3. Close the file.
13.3.1. Opening a file
Before performing any file I/O, the file must be opened. While opening the file, the following are to be
specified:
The name of the file and
The manner (or mode) in which it should be opened (i.e., for reading, writing, reading and writing,
appending at the end of file, or overwriting the file …etc).
The function fopen() is used to open a file. It accepts two strings as arguments with the following form:
FILE *fopen(filename,mode);
From this prototype, it is clear that the function fopen() has:
Arguments:
o file name is the name of the file to opened. As it is a string, it should be enclosed with in double
quotation marks. If we want to specify the full path name for the file, we should use double
backslash (as in DOS) or a single front slash (as in UNIX).
o mode is used to specify the manner in which a file should be opened. As it is a string, it should be
enclosed with in double quotation marks. The possible modes are:
File Opening Meaning
Mode
r (read-only) Open an existing file for reading only.
w(write-only) Open a new file for writing only. If a file with specified filename currently exists, it
will be destroyed and a new file with the same name will be created in its place.
a (append-only) Open an existing file for appending (i.e., for adding new information at the end of
file). A new file will be created if the file with the specified filename does not exist.
r+ (read & write) Open an existing file for update (i.e., for both reading and writing).
w+ (write & read) Open a new file for both writing and reading. If a file with the specified filename
currently exists, it will be destroyed and a new file will be created in its place.
a+(append & read) Open an existing file for both appending and reading. A new file will be created if
the file with specified filename does not exist.
Return value:
On success, fopen() returns a pointer to the predefined structure FILE, whose definition is
available in stdio.h.
On failure, it returns NULL.
238
Ex: FILE *fp; //statement-1
fp=fopen(“sample.txt”,”w”); //statement-2
if(fp==NULL) //statement-3
{
printf(“\n Unable to open a file”);
exit(0);
}
When working with a stream-oriented file, the first step is to establish a buffer area, where the
information is temporarily stored while being transferred between the computer’s memory and the file.
This buffer area allows information to be read from of written to the data file more rapidly. The buffer area
is established by writing:
FILE *fp;
where FILE (upper case letters required) is a special structure type that establishes the buffer area and
fp is a pointer variable that indicates the beginning of the buffer area.
Statement-1 declares fp, the pointer to the pre-defined structure FILE (available in stdio.h). Usually, the
pointer fp is referred to as a stream pointer.
Statement-2 helps us in opening the file sample.txt in writing mode. If there is no file with name
sample.txt in the current directory, then it is created. If already exists, then its content will be erased and
the file is ready for writing the new content. As fopen() returns pointer to the structure FILE, it is handled
with the pointer fp. This pointer will be very helpful in subsequent operations such as read,write…etc.
Statement-3 helps us to handle the failure situation of fopen(). If it is not handled, then there will be
problems such as system crash.
13.3.2. Writing to a file
The functions printf(), puts() and putchar() are used to write the content to monitor. To write to a file,
the functions fprintf(), fputs() and fputc() are used. All these functions accept a file pointer as one of
the parameters along with other parameters required by the standard output functions.
1) Writing a character to a file: To write a character to a file, do the following:
Open the existing file in “w”,“w+”,”a” or “a+” mode using fopen() and handle the file
pointer that is returned.
Read the character from keyboard using getchar() or scanf().
Input that character as an argument to the function fputc() along with the file pointer as
follows:
int fputc(character,pointer_to_FILE);
239
Ex: FILE *fp;
char ch;
fp=fopen(“sample.txt”,”w”); //step-1:open file in writing mode
printf(“\n Enter the text to the file (ctrl+d to end):”);
ch=getchar(); //step-2: reads a character from keyboard
while(ch!=EOF) //write character-by-character till the end-of-file is reached
{
fputc(ch,fp); //step-3
ch=getchar();
}
2) writing a String to a file: To write a string to the file, do the following:
Open the existing file in “w”,“w+”,”a” or “a+” mode using fopen() and handle the file
pointer that is returned.
Read the string from keyboard using gets() or scanf().
Input that string as an argument to the function fgets() along with the file pointer as
follows:
int fputs(string,pointer_to_FILE);
From this prototype, it is clear that:
o fputs() takes two arguments: first argument is a string that is to be written to the file
and second argument is file pointer.
o fputs() writes the string to the specified file. On success, it returns an unsigned integer.
On failure, fputs() returns EOF.
Ex: FILE *fp;
char str[25];
fp=fopen(“normal.txt”,”w”); //step-1 : Open file in write mode
printf(“\n Enter any string to write to the file:”);
scanf(“%s”,str); //step-2: read a string from keyboard
fputs(str,fp); //step-3 : write that string to file
3) writing formatted data to a file: To write formatted data from a file do the following:
Open the existing file in “w”,“w+”,”a” or “a+” mode using fopen() and handle the file
pointer that is returned.
Read the formatted data from keyboard using scanf().
Input that formatted data to function fscanf() along with the file pointer as follows:
240
main()
{ FILE *fp;
fp=fopen(“student.dat”,”w”); //step-1:open file in write mode
printf(“\n Enter student details( rno,name,rank and fees):”);
scanf(“%d%s%d%f”,&s1.rno,s1.name,&s1.rank,&s1.fees); //step-2: read content from keyboard
fprintf(fp,”%d\t%s\t%d\t%f”,s1.rno,s1.name,s1.rank,s1.fees); //step-3: write content to file
}
int fgetc(pointer_to_FILE);
a. Open the existing file in “r” or “r+” mode using fopen() and handle the file pointer that is
returned.
b. Use the function fgets() that is used to read a string of specified length from file which has
the following form:
char * fgets(string,size,pointer_to_FILE);
241
o fgets() takes three arguments: first argument is a string, second argument is used to
specify the size of string that is to be read and third argument file pointer.
o fets() reads the next line from the specified file. On success, the string of specified size
that is read will be stored in the first argument. On failure, fgets() returns NULL.
3) Reading formatted data from a file: To read formatted data from a file do the following:
a. Open the existing file in “r” or “r+” mode using fopen() and handle the file pointer that is
returned.
b. Use the function fscanf() that is used to read formatted data (i.e., different forms of data
at a time) from file which has the following prototype:
int fclose(pointer_to_FILE);
242
From this prototype, it is clear that:
o fclose() function takes one argument: the file pointer to which we want to close.
o On success, it returns 0. on failure, it returns EOF.
Ex: FILE *fp;
fp=fopen(“sample.txt”,”w”);
…………..
………….
fclose(fp); //closes the file sample.txt
Program #1
Write a program to create a file, write some text to it and print that text on monitor.
#include<stdio.h>
main()
{
char filename[15],ch;
FILE *fp;
printf(“\n Enter the file name to be created:”);
scanf(“%s”,filename);
fp=fopen(filename,”w”); //first, open file in write mode
if(fp==NULL)
{
printf(“\n unable to open”);
exit(0);
}
printf(“\n Enter some text to file (ctrl+d to end):”);
ch=getchar(); //read a character from key board
while(ch!=EOF) // check that the entered character is not ctrl+d
{
fputc(ch,fp); //write that character to file
ch=getchar(); //again, read a character from key board
}
fclose(fp); // close the file
Interview question #5
What are pre-defined streams?
stream Meaning
stdin Standard input device (opened for input).
stdout Standard output device (opened for output).
stderr Standard error output device (opened for error output).
stdaux Standard auxiliary device (opened for both input and output).
stdprn Standard printer (Opened for output).
The output of a function like printf() goes to the stream stdout. A function like scanf() receives its input
from the stream stdin. We can write to any of the output streams by using functions like
fputc(),fputs()…etc and read from any of input streams by using functions like fgetc(),fgets()…etc.
These streams are considered to be files. Usually, stdin is connected to the keyboard, stdout and stderr
are connected to monitor, stdaux is connected to serial port com1 and stdprn is connected to lpt1.
Interview question #6
What is the purpose feof()?
The feof() is a pre-defined function that checks the given stream for an end-of-file indicator. It has the
following form:
int feof(pointer_to_FILE);
244
Program #2
Write a program to copy the content of one file to another.
#include<stdio.h>
main()
{
char source[15],destination[15],ch;
FILE *fp1,*fp2;
printf(“\n Enter the an existing file name to be opened:”);
scanf(“%s”,source);
printf(“\n Enter the file name to which the content should be copied”);
scanf(“%s”,destination);
fp1=fopen(source,”r”); //open source file in read mode
if(fp1==NULL)
{
printf(“\n unable to open”);
exit(0);
}
fp2=fopen(destination,”w”); //open destination file in write mode
if(fp2==NULL)
{
printf(“\n unable to open”);
exit(0);
}
245
Program #3
Write a program to count number of characters, alphabets, digits, white spaces and special
symbols in an existing file.
#include<stdio.h>
main()
{
char filename[15],ch;
FILE *fp;
int ccount,acount,dcount,scount,sscount;
printf(“\n Enter an existing file name to be read:”);
scanf(“%s”,filename);
fp=fopen(filename,”r”); //open an existing file in read mode
if(fp==NULL)
{
printf(“\n Unable to open file”);
exit(0);
}
ccount=acount=dcount=scount=sscount=0; //initially, all counts are 0
ch=fgetc(fp); //read a character from file
while(ch!=EOF)
{
ccount++; //increment character count by 1
if(toupper(ch)>=’A’ &&toupper(ch)<=’Z’) //if it is alphabet
acount++; //increment alphabet count by 1
else if(ch>=’0’ && ch<=’9’) //if it is digit
dcount++; //increment alphabet count by 1
else if(ch==’ ‘ || ch==’\t’ || ch==’\n’) //if it is white space
scount++; //increment space count by 1
else
sscount++; //increment special symbol count by 1
ch=fgetc(fp); //again, read a character from file
}
fclose(fp); //close the file
printf(“\n No.of characters=%d”,ccount);
printf(“\n No.of Alphabets=%d”,acount);
printf(“\n No.of digits=%d”,dcount);
printf(“\n No.of spaces=%d”,scount);
printf(“\n No.of special symbols=%d”,ccount);
}
Output:
Enter an existing filename to be read: master.txt
No.of characters=160
No.of Alphabets=122
No.of digits=2
No.of spaces=30
No.of special symbols=6
246
Program #4
Write a program to write student records to a sequential file and access them
#include<stdio.h>
struct student
{
int rno,rank;
char name[15];
float fees;
struct date_of_birth
{
int day,month,year;
}dob;
}s1;
main()
{
FILE *fp;
char ch;
fp=fopen(“sturecords”,”w”); //create a new file
if(fp==NULL)
{
printf(“\n Unable to open file”);
exit(0);
}
do
{
printf(“\nEnter student details (rno,name,rank,fees and date of birth):”);
scanf(“%d%s%d%f%d%d%d”,&s1.rno,s1.name,&s1.rank,&s1.fees,&s1.dob.day,&s1.dob.month,&s1.d
ob.year); //read the student record from keyboard
fprintf(fp,”%d\t%s\t%d\t%f\t%d/%d/%d”,s1.rno,s1.name,s1.rank,s1.fees,s1.dob.day,
s1.dob.month,s1.dob.year); //write the student record to file
printf(“\n Do u want to add one more record (y/n):”);
scanf(“\n%c”,&ch);
}while(toupper(ch)!=’N’);
fclose(fp);
size_t fwrite(ptr,size,n,pointer_to_FILE);
The function fread() is used to read formatted data from the file. It has the following form:
size_t fread(ptr,size,n,pointer_to_FILE);
From this prototype, it is clear that:
o fread() takes four arguments: ptr is a pointer to the block into which data is read. Size is a
value of type size_t, an unsigned integer, used to hold the length of each item read, in
bytes. n is a value of type size_t, an unsigned integer, used to hold number of data items to
read. Pointer_to_FILE is the pointer to the file in which the data is to be read.
o On success, it returns the number of items (not bytes) actually read. On end-of-file or error,
it returns 0.
Ex: struct student s1;
fread(&s1,sizeof(s1),1,fp);
By using fread() and fwrite() functions, fixed-length records are written or read. By using fprintf() and
fscanf() functions, variable-length records are written or read.
By using fread() and fwrite(), the above program can be modified as follows:
248
Program #5
Write a program to write student records to a sequential file and access them
#include<stdio.h>
struct student
{
int rno,rank;
char name[15];
float fees;
struct date_of_birth
{
int day,month,year;
}dob;
}s1,s2;
main()
{
FILE *fp;
char ch;
fp=fopen(“sturecords”,”w”); //create a new file
if(fp==NULL)
{
printf(“\n Unable to open file”);
exit(0);
}
do
{
printf(“\nEnter student details (rno,name,rank,fees and date of birth):”);
scanf(“%d%s%d%f%d%d%d”,&s1.rno,s1.name,&s1.rank,&s1.fees,&s1.dob.day,&s1.dob.month,&s1.d
ob.year); //read the student record from keyboard
fwrite(&s1,sizeof(s1),1,fp); //write the student record to file
printf(“\n Do u want to add one more record (y/n):”);
scanf(“\n%c”,&ch);
}while(toupper(ch)!=’N’);
fclose(fp);
int fseek(pointer_to_FILE,offset,location);
void rewind(pointer_to_FILE);
ftell() function: The function ftell() is used to get the current file position pointer. It has the following
prototype:
long ftell(pointer_to_FILE);
250
From this prototype, it is clear that:
o ftell() function takes one argument: file pointer.
o on success, it returns the current file pointer position. On error, it returns -1 and sets errno to a
positive value.
Program #6
}
Output:
Enter the text into file (end with ctrl+d):
pradeep is a good boy.
251
Program #7
Write a program to reverse the content of file.
#include<stdio.h>
main()
{
FILE *fp1,*fp2;
char ch;
fp1=fopen("sample.txt","w+");
if(fp1==NULL)
{
printf("\n Unable to open file:");
exit(0);
}
printf("\n Enter the text into file (end with ctrl+d):");
ch=getchar();
while(ch!=EOF)
{
fputc(ch,fp1);
ch=getchar();
}
fp2=fopen(“reverse.txt”,”w”);
fseek(fp1,0,2);
while(fseek(fp1,-2,1)= =0)
{
ch=fgetc(fp1);
putchar(ch);
fputc(ch,fp2);
}
fclose(fp1);
fclose(fp2);
}
Output:
Enter the text into file (end with ctrl+d):
Files topic is easy one.
.eno ysae si cipot seliF (content of reverse.txt)
Program #8
Write a program to print the transpose of matrix in a file
#include<stdio.h>
main()
{
FILE *fp;
int i,j;
int matrix[2][3]={{1,2,3},{4,5,6}};
fp=fopen(“mat”,’w”);
fprintf(fp,”\t Transpose matrix\n”);
for(i=0;i<2;i++)
{
for(j=0;j<3;j++)
fprintf(fp,”%d\t”,matrix[j][i]);
fprintf(fp,”\n”);
}
fclose(fp);
}
Output:Content of file “mat”
1 4
2 5
3 6
252
Program #9
Write a program to demonstrate a random-access file
#include<stdio.h>
main()
{
struct student
{
int rno,rank;
char name[15];
float fees;
struct date_of_birth
{
int day,month,year;
}dob;
}s1;
FILE *fp;
char ch;
int sz,len,n,i;
fp=fopen(“sturecords”,”w”); //create a new file
if(fp==NULL)
{
printf(“\n Unable to open file”);
exit(0);
}
do
{
printf(“\nEnter student details (rno,name,rank,fees and date of birth):”);
scanf(“%d%s%d%f%d%d%d”,&s1.rno,s1.name,&s1.rank,&s1.fees,&s1.dob.day,&s1.dob.month,&s1.d
ob.year); //read the student record from keyboard
fwrite(&s1,sizeof(s1),1,fp); //write the student record to file
printf(“\n Do u want to add one more record (y/n):”);
scanf(“\n%c”,&ch);
}while(toupper(ch)!=’N’);
fclose(fp);
sz=sizeof(s1);
len=ftell(fp);
n=len/sz;
fp=fopen(“sturecords”,”r”); //open the file in read mode
if(fp==NULL)
{
printf(“\n Unable to open file”);
exit(0);
}
do
{
printf(“\n Enter the record number to read (o to stop):”);
scanf(“%d”,&i);
if(i>0 && i<=n)
{
fseek(fp,(i-1)*sz,SEEK_SET);
fread(&s1,sz,1,fp);
printf(”\n%d\t%s\t%d\t%f\t%d/%d/%d”,s2.rno,s2.name,s2.rank,s2.fees,s2.dob.day,
s2.dob.month,s2.dob.year);
}
}while(i);
fclose(fp);
}
253
Output:
Enter student details (rno,name,rank,fees and date of birth):
1 master 1 27500.00 12 3 1990
Do you want to add one more record (y/n):y
Enter student details (rno,name,rank,fees and date of birth):
2 maya 13 23500.00 11 9 2004
Do you want to add one more record (y/n):y
Enter student details (rno,name,rank,fees and date of birth):
3 maneesha 14 22500.00 23 3 1982
Do you want to add one more record (y/n):n
Program #10
Write a program to merge multiple files into one file using command line arguments
#include<stdio.h>
main(int argc,char *argv[])
{
FILE *fp,*fp2;
int i;
fp2=fopen(“ans”,”a”);
for(i=1;i<argc;i++)
{
fp=fopen(argv[i],”r”);
while((ch=fgetc(fp))!=EOF)
fputc(ch,fp2);
}
fclose(fp);
fclose(fp2);
}
Output:
$./a.out stud.txt sample.txt master.txt
content of file ans
=========
pradeep is a good boy.
Mater minds are not made.
Master minds are born.
Master minds are not born. They are made.
But master minds are mad.
Master minds’ numbers consist of digits: 0-9
The persons who read this text are master minds
254
Program #11
Write a program to search for particular word in a file
#include<stdio.h>
#include<string.h>
main()
{
FILE *fp;
char ch,temp[15],word[15],filename[15];
int count=0;
255
Program #12
Write a program convert the text in file into upper case
#include<stdio.h>
main()
{
FILE *fp1,*fp2;
char ch;
fp1=fopen(“master.txt”,”r”);
fp2=fopen(“case.txt”,”w”);
ch=fgetc(fp1);
while(ch!=EOF)
{
fputc(toupper(ch),fp2);
ch=fgetc(fp1);
}
fclose(fp1);
fclose(fp2);
fp2=fopen(“case.txt”,”r”);
ch=fgetc(fp2);
while(ch!=EOF)
{
printf(“%c”,ch);
ch=fgetc(fp2);
}
fclose(fp2);
}
output:
content of master.txt
=======
Master minds are not born. They are made.
But master minds are mad.
Master minds’ numbers consist of digits: 0-9
The persons who read this text are master minds
content of case.txt
=========
MASTER MINDS ARE NOT BORN. THEY ARE MADE.
BUT MASTER MINDS ARE MAD.
MASTER MINDS’ NUMBERS CONSIST OF DIGITS: 0-9
THE PERSONS WHO READ THIS TEXT ARE MASTER MINDS
13.5. Error-handling
While processing files, we usually assume that:
o The file that is opened exists.
o There is enough space on the disk for the file.
o The functions fseek(), fread(), fwrite()…etc carry out the requested job successfully.
It is important to note that these assumptions are not always true. There is possibility of the following
errors in manipulating files:
256
Error Reason
File not found Wrong file name used (spelling mistake, error in the path specified) or file actually
not present.
Disk full When writing to a disk with no more free sectors.
Disk write protected The disk has its write protect tag put on or some software has disabled writes to the
disk.
Unexpected EOF File length is zero of file length is less than that expected.
Sector not found (i) Reading and writing to two different streams, one as read only and the
other write only, but the file used for these streams is the same.
(ii) The disk head is not aligned on the physical sectors.
The argument msg points to an optional user-defined message. This message is printed first, followed
by a colon and the implementation-defined message that describes the most recent error. If you call
perror() when no error has occurred, the message displayed is no error.
Program #13
Write a program to demonstrate perror() function
#include <stdio.h>
#include <stdlib.h>
main()
{
FILE *fp;
char filename[80];
257
Interview question #7
What is the purpose ferror()?
The ferror() is a macro that tests the given file pointer for a read or write error. It has the following
prototype:
Program #14
Write a program to demonstrate ferror()
#include<stdio.h>
main()
{
char filename[15],ch;
FILE *fp;
printf("\n Enter file name:");
scanf("%s",filename);
fp=fopen(filename,"r");
if(fp==NULL)
{
printf(“\n Unable to open file”);
exit(0);
}
fputc(ch,fp);
if(ferror(fp)>0)
{
perror("error");
}
fclose(fp);
}
Output:
Enter file name: master.txt
error: Bad file descriptor.
258
when we try to count the number of characters of a text file, each new line character contributes
by one.
2) The eof character: The eof character in text files corresponds to the character having ASCII code
26. In binary files, there is no such explicit eof character. The binary files do not store any special
character at the end of the file and their file-end is verified by using their size itself.
3) While discussing binary files, one more point is worth mentioning and corresponds to storage of
numbers in binary format. The numbers can be written to files using fprintf() statement as a
sequence of characters. E.g., the number 1001 can be written using fprintf() as a sequence of
characters: ‘1’,’0’,’0’,’1’. It means that storage of 4-digit number will take 4 bytes. But on a 16-bit
computer, an integer needs 2 bytes of storage and this concept can be utilized with help of fwrite()
statement. The fwrite() function will store every integer value by taking two bytes.
13.7. Conclusion
File is a collection of related data that is stored permanently on disk. There are two types of files namely
stream-oriented files and system-oriented files. In this chapter, we have studied only stream-oriented
files: text files and binary files. Based on the type of access, the stream-oriented files are broadly
classified as sequential-access files and random-access (or direct access) files.
259