Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                

C Language PDF

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

Introduction to C

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

“Focus on the journey, not on the destination.


Joy is found not in finishing an activity but in
doing it.”
–Greg Anderson

“Time is a companion that goes with us on journey.


It reminds us to cherish each moment, because it
will never come again. What we leave behind is not
as important as how we have lived.”
–Jean Luc Picard

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.

2. C is modular (or) C is procedure-oriented programming language.


C is modular. The C code should be written in routines called functions. These functions can be reused in
other applications or programs. By passing pieces of information to these functions, we can create useful
and reusable code.

3. C is a language of few words.


C contains a handful of terms called keywords (some times called as reserved words), which serve as the
base on which the language’s functionality is built. High-level languages have many more keywords (e.g.,
BASIC has more than 100 keywords). C has 37 keywords (C89 standard defined 32 and C99 standard
defined 5 more).

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.

5. C is a powerful and flexible language.


What you can accomplish with C is limited only by our imagination. The language itself places no
constraints on us. C is used for projects as diverse as operating systems, word processors, graphics,
spreadsheets and even compilers for other languages.

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

“Success is neither magical nor mysterious. Success


is the natural consequence of consistently applying
the basic fundamentals.”
–Jim Rohn

5
2.1. Introduction

Alphabets Words Sentences Paragraphs Stories

Steps in learning English Language

Characterset Tokens Instructions Functions Programs

Steps in learning C Language

 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.

2.2. Character Set


When we wish to write a program, we write it as a collection of text lines containing characters from a
collection of characters. This collection can be called as character set. A C program can be written using
the following character set:

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

Type-related Storage-related Control-flow


keywords keywords related 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 #1: An identifier should not be a keyword.


Ex: salary, name, GOTO (valid)
int, goto (invalid)

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

2.3.3. Constants (or) Literals


A program needs some input to be processed. During processing instructions, the input should be stored
in memory. The input that is being stored in memory called as a literal.

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

Integer Real Character String


constants constants constants constants

Note: The word “constant” in C has two meanings:


1. The value that remains unchanged (or fixed) during the execution of program.
2. The value that is being input to a program.

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

123245353UL Unsigned long decimal integer constant

2.3.3.2. Floating-point constants or Real constants


A floating-point constant can be expressed in any one of these two notations:

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.

Examples of floating-point constants: (Decimal notation)


Real constant Description
Precision=
2.3456 Double-precision floating-point constant. (by default)
digits after a
2.3456F Single-precision floating-point constant. decimal
point.
2.3456L Long double precision floating-point constant.

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.

Examples of floating point constants: (Exponential notation)


Number In powers of 10 Exponential notation
53876 5.3876*10 4
5.3876e4
0.00000000004 4*10-11 4E-11
100000 1*105 1e+5
0.007321 7.321*10-3 7.321E-3
32000 3.2*104 3.2E4
0.0000005 0.5*10-6 0.5E-6

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.

2.3.3.3. Character constants


A character constant is a sequence of one or more characters enclosed in single quotes. The character
may be an alphabet, digit, special symbol or a blank space. The value of a character constant with only
one character is the numeric values of the character in the machine’s character set at execution time. The
value of multi-character constant is implementation-defined.

Ex: ‘a’ ‘9’ ‘@’ ‘\0’ (valid)


‘abc’ ‘123’ ‘a&b’ ‘’’(invalid)

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

\a Audible alert (bell)

\\ Backslash

\? Question mark

\’ Single quote

\’’ Double quote

\000 Octal number

\xhh Hexa-decimal number

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.

2.3.3.4. String constants


A string constant is a sequence of characters surrounded by double quotes. The characters may be of
letters, numbers, escape sequences and spaces. In C, a string can be represented as an array of
characters terminated by a null character (\0).
Ex: “234” “Civil \n Engineering” “Rama&Co.” (valid)
“”” (invalid)
Note:
1) A string constant never contain the characters: “ (double quotation mark), new line. To include
this, one should use their corresponding escape sequences.
2) Adjacent string literals are concatenated into a single string. After concatenation, a null byte \0 is
appended to the string so that program that reads the string can find its end.

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

Int 2 bytes or one word (varies from one -32768 to +32767


compiler to another).
float 4 bytes or one word. -3.4e38 to +3.4e38 with 6
digits of precision.
double 8 bytes or two words. -1.7e308 to +1.7e308 with
10 digits of precision
char 1 byte. -128 to +127

void 0 bytes. Valueless

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.

Declaring a variable: (Declarative instruction)


All variables should be declared before we use them in the program. The variable declaration tells the
compiler two things:
1. What the name(s) of variables are?
2. Where the values are being stored?
Usually, the declarative instruction is written as a first statement before all the executable statements.
The declarative instruction has the following syntax:

[Storage class] <data type> <variable name(s)>;

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.

Ex: int a,b,c; //a,b and c are integer variables


long double m; // m is a long double variable.
char sex; // sex is a character variable
char name[20]; //name is a character array that can hold 19 characters.

15
Initializing a variable: Initializing a variable is the process of assigning a value to the variable. The
initialization can be done as follows:

[Storage class] <data type> <variable name>=<value>; ….(1)


(or)
<variable Name>=<value>; ….(2)

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;

While initializing a variable, one should observe this:


If the variable and assigned values are of different types, then the assigned value will be converted to
type of variable.
E.g., float a=20;
In this example, a is floating-point variable and 20 is an integer. When this initialization is carried out, the
variable a holds 20.000000, a floating-point value.

1. Write appropriate declarations for each group of variables and arrays


a) Integer variables: p,q
Floating-point variables: x,y,z
Character variables: a,b,c
b) Long integer variable: counter

Q Short integer variable: flag

U Unsigned integer variable: cust_no


c) Double-precision variables: gross, tax, net
E
80-element character array: message
S
2. Write the declarations of various variables required for calculating simple interest?
T
3. Write appropriate initialization statements for these: (initial value)
I
a) Integer variable: a (120)
O Floating point variable: x (32.34f)
N b) character variable: c (‘p’)
S 15-element character array: name (“pradeep”)
4. Write appropriate initialization statements for your details (rollno, name, age, sex,
fees)?

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:

const [Storage class] <data type> <variable name>=<value>;

Ex: const double PI=3.1412;


This initialization tells the compiler that the value of PI must not be modified by the program.
However, it can be used on the right hand side of assignment statement like other variable.
Ex: double x;
x=PI;
 Making a variable as modifiable externally: In order to make variable’s value modifiable at any
time by some external sources (from outside program), we use type qualifier volatile. For example,
volatile int x;
The value of x may be altered by some external factors even if it does not appear on the
left-hand side of an assignment statement. When we declare a variable as volatile, the compiler
will examine the value of the variable each time it is encountered to see whether any external
alteration has changed the value.

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.

“Success is neither magical nor mysterious. Success


is the natural consequence of consistently applying
the basic fundamentals.”
–Jim Rohn

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

Procedure#1 Procedure#2 Procedure#N

4.2. Structure of a C program


A C program can be viewed as a group of building blocks called functions. A function is also called as a
subroutine that may include one or more statements designed to perform a specific task. To write a C
program, we first create our own functions or consider built-in functions and then put them together.
A C Program may contain one or more sections as shown below:
Documentation Section
Link Section
Definition Section
Global Declaration section
main( )
{
Declaration Part
Executable Part
}
Sub Program Section
Function-1
Function-2
Function-3
:
:
Function-n 19
The Documentation section consists of a set of comment lines giving the name of the program, the
author and other details, which the programmer would like to use later. Usually, this section can be
included at any place in the program and will be ignored by the C compiler. Comment lines will help the
user to understand the program clearly and easily. Hence, the comment lines increase the readability of
the program. The comment lines can be defined as follows:

/* 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:

# define const_name value

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.

Step 3: Running the C program


Running the C program is simple task. The command ./a.out would load the executable object code into
the computer memory and execute the instructions. During execution, the program may request for some
data to be entered through the keyboard. Sometimes, the program does not produce the desired result.
Perhaps, there is some thing wrong with the data or logic. Then it would be necessary to correct the
source program or the data. If the source code is modified, then the entire process of compilation and
running the program should be repeated.

4.4. Language processors for executing a C program


Language processors are the system softwares that play key role in translating a source file into an
executable file. These language processors include: preprocessor, compiler, linker and loader. The
translation process from source file into an executable file is depicted as follows:
1. A C program must be typed into the computer and saved to a file. A text editor is used for this
task. The statements written by the programmer are called source code and the file in which the
statements are saved is called as source file.
2. After the source code is saved to a file, the process of translating it to machine language can begin.
During the first phase of this process, a program called the preprocessor reads the source code.
The preprocessor searches for special lines that begin with the # symbol. These lines (usually,
called as preprocessor directives) contain commands that cause the preprocessor to modify the
source code in someway. The preprocessor modifies the existing source code and stores modified
source code into another file.
3. During the next phase, the compiler steps through the preprocessed source code, translating each
modified source code instruction into the appropriate machine language instruction. This process
will uncover any syntax error that may be in program. If the program is free of syntax errors, the
compiler stores the translated machine language instructions, which are called object code, in an
object file.

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?

5. Inability to include header files for


using library functions (In case it is
No
essential in the compiler you are
using). Execute program
Ex:
main()
{
Run-time
float x;y; /*Error: semicolon at error?
wrong place*/
Yes
x=5.00 /*Error: No semicolon at
No
the end of statement*/
y=4.00;
Done
k=3;
int k; /*Error: Declaration after
use*/
printf(“k=%d,k); /*Error: Failure to
close format string*/}

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);
}

Fill in the blanks of the following programs:


/*program to find area volume of sphere…… .....program to calculate area of triangle with
#..............<stdio.h> base and height…….
Q #.............. PI 3.1412 #include<stdio.h>
U …………….() main()
{ …..
E ………………. int base,height;
S printf(….Enter radius value:…….)…….. ……………………..
scanf(“……...”,……radius); printf(“\n Enter base and height values:”);
T area=………………………………………….; scanf(“%d%d”,&base,&height);
volume=…………………………………….; area=……………………………………….
I printf(“\n Area=%f\tVolume=%f”……); pintf(“\n Area of triangle=……”,area);
O ………….
}
N
S
Write equivalent C arithmetic expressions for the following algebraic
expressions
1. ax3+bx2+c
2. s( s  a)(s  b)(s  c)
3. ( x) 2   x 2
1 a
4. (loge( ))
k ax
5
5. c  ( F  32)
9
ax2  bx  c
6.
ax2  bx  c

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

We may also achieve this by specifying an option in the cc command as follows: cc –o


name source_file
This will store the executable object code in the file name and prevent the old file a.out
from being destroyed.

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.

5.2. Types of operators


C has a rich set of operators. Based on the type of operation performed, operators are broadly classified
as follows:
1. Assignment operator.
2. Binary arithmetic operators.
3. Unary arithmetic operators.
4. Relational operators.
5. Logical operators.
6. Bitwise operators.
7. Special operators

5.2.1. Assignment operator


Assignment operator is used to assign (or give) a value to a variable or constant. The assignment operator
is = (can be read as “assigns to”). The assignment operator can be used to form an expression as follows:

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

5.2.2. Binary arithmetic operators


C language provides operators for basic arithmetic operations such as addition, subtraction, multiplication
and division. There are five binary arithmetic operators and these operators act on two operands at a
time.
These are:
Operator Operation
+ Returns the sum of values of two operands.
- Returns the difference of values of two operands.
* Returns the product of values of two operands.
/ Returns the quotient after division of two operands.
% Returns the remainder after division of two operands.

These operators can be used to form an arithmetic expression as follows:

Operand_1 Binary_arithmetic_operator Operand_2

Ex: a+b, a-b, a*b, a/b, a%b


The above expressions are called as binary arithmetic expressions. The operands may be of any
one of data types. If both operands are integer values, then that expression is called as integer
arithmetic expression. If both are floating-point values, then that expression is called as real-
arithmetic expression. If both are of different values, then that expression is called as mixed-mode
arithmetic expression.
34
When binary operations are applied to numeric arguments of different types, numeric promotion
is performed before the operation takes place. The numeric promotion consists of converting the values of
the operands to a common type.
The rules for this type conversion are as follows:
 If one of the operands is a long double, then the other is converted a long double.
 Otherwise, if one of the operands is a double, then the other is converted to a double.
 Otherwise, if one of the operands is a float, then the other is converted to a float.
 Otherwise, if one of the operands is a long, then the other is converted to a long.
 Otherwise, if one of the operands is unsigned int, the other is converted to unsigned to int.
 Otherwise, both operands are converted to int values.
Ex: 2.3 (a double value) +3 (an int value) =5.3 (a double result)
The integer value in this expression gets promoted to double; addition is performed and the result is of
type double is returned.
Program #2
Write a program to perform all arithmetic operations
/*program to perform all arithmetic operations*/
#include<stdio.h>
main()
{
int a,b;
printf(“\nEnter any two numbers: ”);
scanf(“%d%d”,&a,&b);
printf(“\nAddition=%d”,a+b);
printf(“\nSubtraction=%d”,a-b);
printf(“\nMultiplication=%d”,a*b);
printf(“\nQuotient=%d”,a/b);
printf(“\nRemainder=%d”,a%b);
}
Output:
Enter any two numbers: 5
6
Addition=11
Subtraction=-1
Multiplication=30
Quotient=0
Remainder=5

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

1)#include<stdio.h> 4)#include<stdio.h> 7)#include<stdio.h>


main() main() main()
{ { {
int x; printf(“%d”,4/3); float a=4;
x=-3+4-7*8/5%10; printf(“%d”,4/-3); int i=2;
OBSERVABLE printf(“x=%d”,x); printf(“%d”,-4/3); printf(“%f%d”,i/a,i/a);
} printf(“%d”,-4/-3); printf(“%d%f”,i/a,i/a);

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.

These operators can be used to form an expression as follows:

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.

Ex: int a=10; Ex: int a=10;


a++; ++a;
printf(“a=%d”,a); printf(“a=%d”,a);
Output: a=11 Output: a=11

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.

Ex: int a=10; Ex: int a=10;


x=50+a++; x=50+(++a);
printf(“x=%d,a=%d”,x,a); printf(“x=%d,a=%d”,x,a);
Output: x=60,a=11 Ouput: x=61,a=10

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()
{
{

P int x=3,z; int x=3,z; int x=3,z;


z=++x +10; z=x----1; z=x/++x;
printf(“x=%d z=%d”,x,z); printf(“x=%d z=%d”,x,z); printf(“x=%d

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);
} } }

5.2.4. Relational operators


The relational operators are used to compare two operands. There are six relational operators available.
All these operators are binary operators. These are used to form an expression that is either true or false.
The following table lists all the relational operators.
Operator Operation
== (is equal to) Checks whether first operand is equal to second operand or not.
!= (is not equal to) Checks whether first operand is not equal to second operand or not.
> (is greater than) Checks whether first operand is greater than the second operand.
>=(is greater than or Checks whether first operand is greater or equals to second operand.
equal to)
< (is lesser than) Checks whether first operand is lesser than the second operand.
<= (is lesser than or Checks whether first operand is lesser or equals to the second operand.

39
equals to)
A relational expression is of the following form:

Operand_1 relational_operator Operand_2

Where operand_1 and Operand_2 are variables or constants or arithmetic expressions.


Ex: int i=7;
Expression Value
float f=5.5;
f>5 1 (true)
char c=’w’;
(i+f)<=10 0 (false)
c==119 1 (true)
c!=’p’ 1 (true)
c>=10*(i+f) 0 (false)
Program #4
Write a program to demonstrate relational operators
/*program to demonstrate relational operators*/
#include<stdio.h>
main()
{
int num1,num2;
num1=20;
num2=30;
printf(“\n Is equal to condition=%d”,(num1==num2));
printf(“\n Is not equal to condition=%d”,(num1!=num2));
printf(“\n Is greater than condition=%d”,(num1>num2));
printf(“\n Is greater than or equal to condition=%d”,(num1>=num2));
printf(“\n Is lesser than condition=%d”,(num1<num2));
printf(“\n Is lesser than or equal to condition=%d”,(num1<=num2));
}
Output:
Is equal to condition=0
Is not equal to condition=1
Is greater than condition=0
Is greater than or equal to condition=0
Is lesser than condition=1
Is lesser than or equal to condition=1

5.2.5. Logical operators (or) Compound relational operators


The logical operators are used to combine the relational expressions and evaluate them. There are three
logical operators. These work on the values of operands that are either true or false. Both Logical AND and
Logical OR operators are binary operators whereas Logical NOT is only unary operator. The following table
lists them:
Operator Operation
&& (Logical AND) Performs Logical AND operation on two operands.
|| (Logical OR) Performs Logical inclusive OR operation on two operands.
! (Logical NOT) Reverses the value of operand.

40
The logical operators are used to form logical expressions as shown below:
1) Logical AND 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 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)

where Expression_1 is any expression that returns either true or false.

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

1)#include<stdio.h> 4)#include<stdio.h> 7)#include<stdio.h>


main() main() main()
{ { {
int x,y,z; int x,y,z; int x=10,y=5,p,q;
x=y=z=1; x=y=z=-1; p=x>9;
z=++x||++y&&++z; z=++x||++y&&++z; q=x>3&&y!=3;
printf(“%d %d %d”,x,y,z); printf(“%d %d %d”,x,y,z); printf(“%d %d”,p,q);
} } }

2)#include<stdio.h> 5)#include<stdio.h> 8)#include<stdio.h>


main() main() main()
OBSERVABLE
{ { {

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 } }

10)#include<stdio.h> 11)#include<stdio.h> 12)#include<stdio.h>

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:

Condition? Expression_1: Expression2;


In this syntax,
Condition is any expression to be tested and it returns either true or false. Usually, it is either a relational
expression or compound relational expression.
Expression_1 and Expression_2 are any statements that are to be executed.
When the conditional operator is encountered, first, the Condition is tested. It returns either
true or false. If the condition is true, Expression_1 is executed. If the condition is false, Expression_2
is executed. This is shown as in the following chart:

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);
}
}

5.2.7. Bitwise operators

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:

Compared bits Result

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.

Bitwise Inclusive OR (|)


The operator | performs a bitwise inclusive 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 are 0; otherwise, the result is 1 as shown below:

Compared bits Result

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:

Compared bits Result

0^0 0
0^1 1

1^0 1

1^1 0

Bitwise Right shift operator (>>)


The right shift operator >> moves the bits to the right based on specified number of positions. The
general form of right shift expression is:

Constant >> n
(or)
variable >>n

where n is the number of bit positions to be shifted.


Ex: int a=10;
x=a>>3;
The right shift operator shifts the bits in the variable ‘a’ thrice.

Bitwise Right shift operator (<<)


The left shift operator << moves the bits to the left based on specified number of positions. The general
form of left shift expression is:

Constant << n
(or)
variable <<n

where n is the number of bit positions to be shifted.


Ex: int a=10;
x=a<<3;
The left shift operator shifts the bits in the variable ‘a’ thrice.
One’s complement operator (~)
One’s complement operator is a unary operator. It acts on one operand at a time. One’s complement
operator converts all the 1-bits to 0 and all 0-bits to 1 of the binary pattern of the operand. The one’s
complement operator should be preceded with operand as follows:

~operand1

Where operand1 is a variable or a constant.


Ex: int a=10;
x=~a;

46
Interview question #2

What are uses of shift operators?


 To divide an integer by 2n, a right shift by n bit positions is applied.
 To multiply an integer by 2n, a left shift by n positions is applied.

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.

Operand_1 short-hand operator Operand_2

Usually, Operand_1 should be a variable and Operand_2 can be a variable or a constant.


When compound assignment operator is encountered, the desired operation is performed between
Operand_1 and Operand_2 and the result gets stored in Operand_1.
Ex: a+=2 means a=a+2
int a=20;
a+=2; ans: a=22

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 */

1) Are the following two statements same (yes /no)


a<=20?b=30:c=20;
(a<=20)?b:c=30;
2) We want to round of x, a float to an int value. The correct way to do so
OBSERVABLE
would be:

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));
}

5.2. Operators’ precedence and associativity


Precedence of an operator is the priority of it in the evaluation of an expression.
Associativity of an operator is its order of evaluation in an expression. The evaluation continues
according to the associativity individually as well as when all the operators in the expression have the
same precedence.

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

5 2 << >> Left-to-Right

6 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

5.3. Evaluating an expression


Evaluation of an expression is the process of calculating the result from it based on operators’ precedence
and associativity.

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

unsigned int Narrowing


conversion
int

short char

This type conversion can be done either implicitly or explicitly.


Implicit type conversion: C permits mixing of constants and variables of different data types in an
expression. C automatically converts any intermediate values to the proper type so that expression can be
evaluated with out loosing any significance. This automatic conversion is known as implicit type
conversion.
During evaluation, the lower type is automatically converted to the higher type, according to strict
rules of type conversion. The rules for this type conversion are as follows:
1. If one of the operands is a long double, then the other is converted a long double.
2. Otherwise, if one of the operands is a double, then the other is converted to a double.
3. Otherwise, if one of the operands is a float, then the other is converted to a float.
4. Otherwise, if one of the operands is an unsigned long, then the other is converted to an unsigned
long.
51
5. Otherwise, if one of the operands is a long, then the other is converted to a long.
6. Otherwise, if one of the operands is unsigned int, the other is converted to unsigned int.
7. Otherwise, both operands are converted to int values.

Ex: int i=10,x;


float f=3.4f;
double d=7.4;
long int l=214L;
x=l/i+i*f-d

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.

Ex: int a=10,b=25,c=32; Ex: int a=10,b=25,c=32;


float d; float d;
d=(a+b+c)/3; d=(float)(a+b+c)/3;
printf(“%f”,d); printf(“%f”,d);
output: 22.000000 output: 22.333334
From the above example, it is clear that the coercion helps us to avoid truncation in division.

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

Conditional Looping Jumping


Control-flow Control-flow Control-flow
Statements Statements Statements

 if statement  while statement  break statement


 switch statement  do…while statement  continue statement
 for statement  goto statement

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:

Note: if…else statement behaves same as the conditional operator ( ? : ) works.


Ex: if(n%2==0)
printf(“\nEVEN”); is same as (n%2==0)?printf(“\n EVEN”):printf(“\n ODD”);
else
printf(“\n ODD”);

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

6.2.1.4. else if ladder


Else if ladder is one of the conditional control-flow statements. It is used to make a decision among
multiple choices. It has the following form:
if(<condition1>)
if-body
else if(<condition2>)
else-if-body1
else if(<condition3>)
else-if-body2
else if(<condition4>)
else-if-body3
:
:
else if(<conditionN>)
else-if-bodyN
else
else-body
Next-statement

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;

2) Determine whether the following are true or false


U a) When if statements are nested, the last else gets associated with the nearest if without an
else.
E b) One if can have more than one else statement.
c) A switch statement can always be replaced by a series of if…else statements.
S d) A switch expression can be of any type
e) A program stops its execution when a break statement is encountered?

T 3) Find out errors, if any, in each of the following segments


a) if(x+y=z &&y>0)
I printf(“ “);
b) if(code>1);
a=b+c
O else
a=0
N c) if(p<0)||(q<0)
printf(“\n Sign is negative”);
S

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”);
}

/* A program to calculate income tax /* A program to calculate grade


based on following conditions based on following conditions (3 subjects)
Income Tax if any subject is scored lesser than 35, failed
Below 50000 No tax avg grade
Rs 50000-100000 10% Above 70 First class with distinction
Rs 100000-1.5 lakhs 20%+1000 60-70 First class
Above 1.5 lakhs 30%+3000*/ 50-60 Second class
#include<stdio.h> Below 50 third class*/
main() #include<stdio.h>
{ main()
double gross,tax; {
printf(“Enter annual income:”); int m1,m2,m3;
scanf(“%lf”,&gross); float avg;
if(gross>=50000) printf(“\n Enter 3 subjects marks:”);
tax=0; scanf(“%d%d%d”,&m1,&m2,&m3);
else if(gross>=50000 &&gross<100000) if(m1<35||m2<35||m3<35)
tax=(gross*10)/100.0; printf(“\n You are failed”);
else if(gross>=100000 &&gross<150000) else
tax=1000+(gross*20)/100.0; {
else avg=(m1+m2+m3)/3.0;
tax=3000+(gross*30)/100.0; if(avg>=70)
printf(“\n Tax to be paid=Rs. %.2lf”,tax); printf(“\n First class with distinction”);
} else if(avg>=60 && avg<70)
printf(“\n First class”);
else if(avg>=50 && avg<60)
printf(“\n Second class”);
else
printf(“\n Third class”);
}
}

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.

7.2. Looping control-flow statements

Looping Control-flow Statements

while statement do-while statement for statement

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

false condition true

Next_statement while loop body

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

for loop body

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.

The syntax for “do-while” statement is as follows:

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

do-while loop body

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:

Jumping Control Statements

break continue goto

7.3.1. break statement


The “break” statement is used with in the looping control statements, switch statement and nested loops.
When it is used with the for, while or do-while statements, the control comes out of the corresponding
loop and continues with the next statement.
When it is used in the nested loop or switch statement, the control comes out of that loop / switch
statement within which it is used. But, it does not come out of the complete nesting.

The syntax for the “break” statement is:

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

7.3.2. continue statement


A continue statement is used within loops to end the execution of the current iteration and proceed to
the next iteration. It provides a way of skipping the remaining statements in that iteration after the
continue statement. It is important to note that a continue statement should be used only in loop
constructs and not in selective control statements. The syntax for continue statement is:

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>;

Ex: even: printf(“\n Given number is even”);


Note: As with any other C statement, we can include a label before a null statement. To label an item that
is not a statement, such as the closing brace of a compound statement, we can label a null statement and
insert it immediately before the item to get the same effect.

7.3.3. goto statement


The goto statement transfers the control to the specified location unconditionally. There are certain
situations where goto statement makes the program simpler. For example, if a deeply nested loop is to be
exited earlier, goto may be used for breaking more than one loop at a time. In this case, a break
statement will not serve the purpose because it only exits a single loop.

The syntax for goto statement is:


label:
{
statement_1;
statement_2;
:
}
:
goto label;

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
usto 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*/
}

7.4. Additional topics

7.4.1. Nested loops:


whenever a looping control statement appears within another looping control statement, it is said to be
nested loop structure. The loop should not overlap each other. That is, the names used in expressions of
one loop statement must be different from other.
Ex: for(i=1;i<=5;i++) //outer loop
{ Output: 1

for(j=1;j<=i;j++) // inner loop 12

printf(“%3d”,j); 123

printf(“\n”); 1234

} 12345

7.4.2. Infinite loop:


An infinite loop is a sequence of instructions in a computer program which loops endlessly, either due to
the loop having no terminating condition or having one that can never be met.
Ex: int a;
for (a = 0; a < 5; a++)
{
//code
a = 2;
printf(“%d”,a);
}

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.4.4. Entry-controlled looping construct vs Exit-controlled looping construct:


The "for" and "while" loops test the condition before executing the loop body. Hence these are called as
entry-controlled looping constructs. This implies that “for” and “while” loops might not execute the loop
body even once.
The “do-while” loop tests the condition after executing the loop body. Hence, it is called as an exit-
controlled looping construct. This implies that “do-while” loop execute the loop body at least once even
when the condition is false.

7.4.5. Counter-controlled loop vs Sentinel-controlled loop:


When we know in advance exactly how many times the loop will be executed, we use a counter-controlled
loop( definite repetition loop). When we don’t the number of repetitions exactly, we use a sentinel-
controlled loop (indefinite repetition loop).
Counter-controlled loop Sentinel-controlled loop
i=1; int i,count=0;
while(i<=10) printf(“\n Enter numbers (end with -999):”);
{ do
printf(“%d”,i); {
i=i+1; scanf(“%d”,&i);
} count++;
}while(i!=-999);
Printf(“\n count of entered numbers=%d”,count);

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.

T 2. point out the error, if any, in the while loop?


main()
I {
int i=1;
while()
O {
printf(“%d”,i++);
N if(i>10)
break;
S }
}
A. The condition in the while loop is a must.
B. There should be at least a semicolon in the while.
C. The While loop should be replaced by a for loop.
D. No error.

1)#include<stdio.h> 3)#include<stdio.h> 6)#include<stdio.h>


main() main() main()
{ { {
char j=1; int j=1; int i=1;
while(j<=255) while(j<=255) for(;i++;)
OBSERVABLE { printf(“%d\n”,++j); printf(“%d”,i);
printf(“%d\n”,j); } }
O }
j=j+1;
4)#include<stdio.h> 7)#include<stdio.h>

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;
}
}

Programs for practice


1. Write a program to check whether given number is palindromic prime or not?
2. Write a program to find roots of quadratic equation.
3. Write a program to find type of triangle based on 3 given angles.
4. A bank charges commission on the issue of Demand Draft at the following rates:
Amount commission
Upto Rs.500/- Rs.10
>500 upto 1000/- Rs. 15
>1000 upto 5000/- Rs.20
>5000 upto 10000/- Rs.25
>10000 Rs 4 for every Rs.1000
Write a program which will accept DD amount and calculate the commission payable and print it
along with DD amount.
5. Write programs to print the following numbers from 1 to 1000
a) Prime numbers b) perfect numbers c) armstrong numbers
d) strong numbers e) Fibonacci numbers f) twin prime numbers
6. Write programs to evaluate the sum of following series
a) 1-1/2+1/3-1/4+….. upto n terms
b) X+x2+x3+….+xn
c) X-x3/3!+x5/5!-x7/7!.....upto 5 palces of decimal accuracy.
7. Write a program to calculate ncr and npr.
8. Write a program to count and print sum of digits of a number.
9. Write a program to print reverse pyramid of digits.
10. Write a program that prints all perfect cubes below 1000.
11. Write a program to print all multiplication tables from 1 to 10 in a tabular format.
12. Write a program to print all prime factors of a number.
13. Write programs to print the following patterns:
a) 1 b) 0 c) *
1 2 3 010 ***
12345 01210 *****
1 234567 0123210 *******
12345 012343210 *********
1 2 3 01234543210 ***********
1 0 1234566543210 *************
14. Write a program to generate the following sequence:
If n=4, -4 -3 -2 -1 0 1 2 3 4

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.

This definition has the following parts:


 A function is named. Each function has a unique name. By using that name in another
part of the program, we can execute the statements contained in the function. This is
known as calling the function. A function can be called from within another function.
 A function is independent. A function can perform its task without interference from or
interfering with other parts of the program.
 A function performs a specific task. This is the easy part of the definition. A task is a
discrete job that a program must perform as part of its overall operation, such as sending
a line of text to a printer, sorting an array into numerical order, or calculating a cube root.
 A function can return a value to the calling program. When our program calls a
function, the statements it contains are executed. If we want them to, these statements
can pass information back to the calling program.
( OR )

A Function is a self-contained block of code that performs a coherent task.

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.

Every C program can be thought of as a collection of these functions. Any C program


contains at least one function. If a C program contains functions, then these are recognized
easily as a string (or name) followed by parentheses. E.g., main() is a function. If a program
contains only one function, it must be main( ). If a C program contains more than one
function, then one of these functions must be main( ), Typically, C program execution always
begins with main( ). There is no limit on the number of functions that might be present in a C
program.

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.

8.3. Types of functions


There are basically two kinds of functions: Pre-defined functions and user-defined functions.
Pre-defined functions are the functions that were developed by the C Language developers.
User-defined functions are the functions that will be developed by the user.

8.3.1. Pre-defined functions:


 These are the functions that were developed earlier by the C language developers.
 All related pre-defined functions are grouped together into header files, a file that has
extension “.h”. E.g., all the mathematical functions are grouped together into the header
file “math.h”. So, whenever a pre-defined function is used, the header file that contains
the pre-defined function definition should be included. # include statement helps us in this
context.
 Some of the pre-defined functions require data to be submitted as an input and these may
return the result by processing the input data. E.g., sqrt(x) function takes a double value
“x” as an input and returns square root of number as a double value. The value that is
being input to function is called as an “argument” or “parameter” and the result that the
function returns is called as “return value”.

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

In this program, we observe that:


a) main(), printf(), scanf() and pow() are functions. main() is the only one user-defined
function and others are pre-defined functions. The definitions of printf() and scanf() are
available in the header file “stdio.h” and definition of pow() is available in “math.h”. Hence
these are included with the help of pre-processor directive #include.
b) Each function has its own “function prototype” that specifies the data types of arguments,
number of arguments and type of value that is being returned. Based on this only, the
arguments will be submitted to the function and the returned value will be hold. E.g., the
prototype of pow(x,y) is “double pow(double,double);”. Based on this prototype only, we
submitted two arguments of type “double” and we used a double variable for holding the
return value.
c) As we know that the thing that is in between two parentheses is an argument, the first
printf() took one argument where as the last printf() took two arguments, scanf() took
one argument and pow() took two arguments. There is no limit in the number of
arguments taken for printf() and scanf(). But pow() should take only two arguments.
From this, we can say that some pre-defined functions may have fixed number of
arguments and some others may have variable number of arguments.
d) As the pow() returns the result, that result should be assigned to a variable for further
reference. Hence, we can say that there should be a holder (variable or pointer) for
holding the value returned by the function.
e) All the statements that are included with in pair of curly braces are collectively called as
the definition of function. There are 5 statements in between { and } after main(). These
93
statements are collectively called as “main() function definition”. For pre-defined
functions, their corresponding definitions are available in their corresponding header files.
For user-defined functions, their function definitions will be given by the user.
f) The program execution begins with main() and all other functions get executed (or called)
in the order specified with in the main(). In this program, main() is called as “calling
function” and printf(), scanf() and pow() are called as “called functions”. When a function
calls another function, the control transfers to called function’s definition. After the total
execution of definition is completed, the control comes back to the calling function along
with return value, if any.

Commonly used header files in C:


Header file name Purpose
<ctype.h> Contains functions used to classify characters by their types or to convert between
upper and lower case in a way that is independent of the used character set
<graphics.h> Contains functions used to draw different objects such as rectangle, circle …etc.
<math.h> For computing common mathematical functions.
<stdio.h> Provides the core input and output capabilities of the C language. This file includes
the venerable printf and scanf functions.
<conio.h> Provides the console input and output capabilities of the C language. However, it
is used in old MS-DOS compilers to create text user interfaces.
<stdlib.h> For performing a variety of operations, including conversion, pseudo-random
numbers, memory allocation, process control, environment, signalling, searching,
and sorting.
<time.h> For converting between various time and date formats.
<string.h> For manipulating various types of strings.

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*/

 Third, he should develop the function definition that is a collection of statements or


block of code based on the function prototype. Usually, the function definition has the
following form:

<return_type> function_name(<datatype1> <arg1>,<datatype2> <arg2>, …<datatypeN> <argN>)


{
Statement(s);
}

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*/

if ( ch >= 65 && ch <= 90 )


return ( ch ) ;
else
return ( ch + 32 ) ;

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.

8.5. Scope and extent of variables


The scope of a variable is the portion of a program in which the variable may be visible or available.
There are 3 types of scopes in which a variable can fall:
1. Block scope
2. Function scope or local scope
3. Global scope or file scope

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.

Moreover, a variable’s storage class tells us:

a) Where the variable would be stored.


b) What will be the initial value of the variable, if initial value is not specifically assigned?
(i.e. the default initial value).
c) What is the scope of the variable; i.e. in which functions the value of the variable
would be available.
d) What is the life of the variable; i.e. how long would the variable along with its values
exist.

There are four storage classes in C:

(a) Automatic storage class


(b) Register storage class
(c) Static storage class
(d) External storage class
These storage classes are identified by the keywords: auto, register, static and extern
respectively.

1) Automatic Storage Class


The features of a variable defined to have an automatic storage class are as under:

Storage Memory.

Default initial value An unpredictable value, which is often called a garbage value.

Scope Local to the block in which the variable is defined.

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.

2) Register Storage Class

The features of a variable defined to be of register storage class are as under:

Storage CPU Registers

Default initial value An unpredictable value, which is often called a garbage value.

Scope Local to the block in which the variable is defined.

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.

Not every type of variable can be stored in a CPU register.

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.

3) Static Storage Class

The features of a variable defined to have a static storage class are as under:
Storage Memory.

Default initial value Zero.

Scope Local to the block in which the variable is defined.

Life Value of the variable persists between different function calls

The following program demonstrates the details of static storage class:

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.

Default initial value Zero.

Scope Global.

Life As long as the program execution does not come to end.

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.

Look at the following program.

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.

Another small issue—what will be the output of the following program?

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.

Look at the following program.

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.

Another small issue—what will be the output of the following program?

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.

Which to Use When

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:

(a) economise the memory space consumed by the variables


(b) improve the speed of execution of the program

The rules are as under:

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.

A function is recursive if it can call itself; either directly:


void f()
{
f();
}
or indirectly:
void f()
{
g();
}

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)

The actual values will then be returned in the following order:


fact(1)=1
2*fact(1)=2*1=2
3*fact(2)=3*2=6
4*fact(3)=4*6=24
5*fact(4)=24*5=120

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.

“The greater the loyalty of a group toward the


group, the greater is the motivation among the
members to achieve the goals of the group, and
the greater the probability that the group will
achieve its goals.” -Rensis Likert

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,

An array is finite homogeneous collection of elements stored in contiguous memory locations


referred by same name.

This definition has the following parts:


 Array consists of homogenous collection of elements. That is, all the data items stored in array are
of same type.
 All elements are stored in contiguous locations. That is, all elements 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 an array.
 All elements refer to same name. That is, each element can be identified with the same name
including different index value (subscript value). Hence, an array is also called as a subscripted
variable. By using, these index values, an element in the array can be accessed directly.

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.

9.3. One-Dimensional array


9.3.1. Declaring one-dimensional array:
Just like an ordinary variable, an array should be declared before it is used.
A one-dimensional array can be declared as follows:
<storage class> <data type> <array_name>[size];
In this syntax,
<storage class> is any one of auto, static, extern or register. It specifies the storage location of an array,
the default values of all elements, scope and life time of an array.
<data type> is any basic data type such as int, float, char or double or any derived data type such as long
int, short int and so on.
<array_name> is any valid identifier.
Size is any non-negative integer constant or integer expression.
1. int a[20]; // one-dimensional array capable of holding 20 elements of type int
2. # define MAXSIZE 30
float b[MAXSIZE]; //1-D array capable of holding 30 elements of type float
3. int k=20;
int c[k]; //Error: Array size can’t be declared as a variable.

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:

a[0] a[1] a[2] a[3] a[4] a[5] a[6]


12 45 54 2 87 76 3

1000 1002 1004 1006 1008 1010 1012

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.

9.4.1. Traversing an array


Traversing is the process of visiting each element of the array. An array’s first element’s index is called
the Lower Bound (LB) and the last element’s index is called the Upper Bound (UB). Traversing is the
process of reaching Upper Bound starting from Lower Bound, incrementing Lower Bound by 1 each time.

The following program demonstrates this:


/* A program to traverse an array*/
#include<stdio.h>
main()
{
int a[10],n,LB,UB;
printf(“\n Enter the array size:”);
scanf(“%d”,&n);
LB=0;
UB=n-1;
printf(“\n Enter array elements:”);
for(i=LB;i<UB;i++)
scanf(“%d”,&a[i]);
printf(“\n The array elements are:”);
for(i=LB;i<UB;i++)
printf(“%d\t”,a[i]);
}

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.

The following program demonstrates this:


/* A program to reverse an array*?
#include<stdio.h>
main()
{
int a[10],n,i,j;
printf(“\n Enter the array size:”);
scanf(“%d”,&n);
printf(“\n Enter array elements:”);
for(i=0;i<n;i++)
scanf(“%d”,&a[i]);
for(i=0,j=n-1;i<j;i++,j--)
{
temp=a[i];
a[i]=a[j];
a[j]=temp;
}
printf(“\n The reversed array is:”);
for(i=0;i<n;i++)
printf(“%d\t”,a[i]);
}
9.4.3. Inserting an element into an array
Insertion is the process of inserting a new element into an existing array. This insertion process can best
be explained with the following example:
Let us consider an array that has the following memory map:

10 9 12 76 45

a[0] a[1] a[2] a[3] a[4] 128


To insert an element 89 into an array at 3rd position do the following:
1) First, increment the current length of array by 1. e.g., the above array holds 5 elements, then
increment 5 by 1. Then we get an array with 6 elements as given below

10 9 12 76 45

a[0] a[1] a[2] a[3] a[4] a[5]

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

a[0] a[1] a[2] a[3] a[4] a[5]


3) Finally, insert the new element at the specified 3 rd position. i.e, assign the value 89 to a[2]. In other
words, a[2]=89. Hence the new array looks like this:

10 9 89 12 76 45

a[0] a[1] a[2] a[3] a[4] a[5]


The following program demonstrates this process:
#include<stdio.h>
main()
{ int a[10],n,i,pos,ele;
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 insert:”);
scanf(“%d”,&ele);
printf(“\n Enter the position:”);
scanf(“%d”,&pos);
n=n+1; //step 1
for(i=n-1;i>=pos-1;i- -) //step 2
a[i]=a[i-1];
a[pos-1]=ele; //step3
printf(“\n New Array\n”);
for(i=0;i<n;i++)
printf(“%d\t”,a[i]);
}

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

a[0] a[1] a[2] a[3] a[4]


Suppose, we want to delete the element at 3rd position, then do the following:
1) First, pick up the element at the specified position. In other words, assign the value at a[pos-1] to
a variable. Therefore, ele=a[2];
2) Move all the elements after the element at specified position to their previous immediate locations
till the end of the array is reached.

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

a[0] a[1] a[2] a[3]


The following program demonstrates the process of deletion:
#include<stdio.h>
main()
{
int a[10],n,ele,pos,i;
printf(“\nEnter 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 position:”);
scanf(“%d”,&pos);
printf(“\n The deleted element=%d”,a[pos-1]); //step-1
for(i=pos-1;i<n;i++) //step-2
a[i]=a[i+1];
n=n-1;
printf(“\n New array:”);
for(i=0;i<n;i++)
printf(“%d\t”,a[i]);
}

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

a[0] a[1] a[2] a[3] a[4] a[5] a[6]

Let the element to be searched be 87. Then, Linear search works as follows:
87

Iteration #1: a[0] is compared with


searching element. Not suitable
12 45 54 2 87 76 3 match. Proceed further.

87

Iteration #2: a[1] is compared with


searching element. Not suitable
12 45 54 2 87 76 3 match. Proceed further.

87

Iteration #3: a[2] is compared with


searching element. Not suitable
12 45 54 2 87 76 3 match. Proceed further.

87

Iteration #4: a[3] is compared with


searching element. Not suitable
12 45 54 2 87 76 3 match. Proceed further.

131
87

Iteration #5: a[4] is compared with


searching element. suitable match.
12 45 54 2 87 76 3 Therefore, Pos=4+1=5

a[0] a[1] a[2] a[3] a[4] a[5] a[6]

The following program demonstrates Linear Search:


#include<stdio.h>
main()
{
int a[10],n,i,ele,pos,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);
flag=0;
for(i=0;i<n;i++)
{
if(a[i]= =ele)
{
flag=1;
pos=i+1;
break;
}
}
if(flag= =1)
printf(“\n The given element is found at %d position”,pos);
else
printf(“\n The given element is not found”);
}

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.

The Binary search method can be implemented either iteratively or recursively.

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);
}

9.4.6. Sorting elements of an array


Let A be list of N numbers. Sorting A refers to the operation of rearranging the elements of A so that they
are in increasing order. i.e., A[0]<A[1]<A[2]<………..<A[N-1]. There are 3 basic sorting methods:
1. Selection sort
2. Bubble sort
3. Insertion sort

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:

Let A be an array with the following memory map:

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:

Pass 1: A[0] by itself is trivially sorted.


Pass 2: A[1] is inserted either before A[0] or after A[0] so that A[0] and A[1] are sorted.
Pass 3: A[2] is inserted into its proper place in A[0] and A[1]. That is, A[2] can be inserted
before A[0] or in between A[0] and A[1] or after A[1] so that A[0],A[1] and A[2]
are in sorted order.
Pass 4: A[3] is inserted into its proper place in A[0],A[1],A[2] so that A[0],A[1],A[2],A[3]
are in sorted order.
…….
…….
Pass n: A[n-1] is inserted into proper place in A[0],A[1],A[2]…A[N-1] so that
A[0],A[1],A[2],…,A[N-1] are in sorted order.

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.

Ex: Let A be an array with the following memory map:


77 33 44 11 88 22 66 55

#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]);

printf(“\n Enter the second array size:”);


scanf(“%d”,&m);
printf(“\n Enter the second array elements in sorted order:”);
for(j=0;j<m;j++)
scanf(“%d”,&b[j]);
i=j=k=0;
while(i<n&&j<m)
{
if(a[i]<b[j])
{
c[k]=a[i];
i++; k++;
}
else if(a[i]>b[j])
{
c[k]=b[j];
j++; k++;
}
else
{
c[k]=a[i];
i++;j++;k++;
}
}
if(i<n)
{
for(l=0;l<n;l++)
{
c[k]=a[l];
k++;
}
}
if(j<m)
{
for(l=0;l<m;l++)
{
c[k]=b[l];
k++;
}
}

printf(“\n The merged list:”);


for(i=0;i<k;i++)
printf(“%d\t”,c[i]);’
140
}
9.5. Two-Dimensional arrays
A Two-Dimensional array looks like array name followed by two subscripts. It is very helpful to represent
matrices in mathematics or tables in business. The first subscript is used to denote the Number of rows
and second is used to denote the number of columns. The total number of elements a two-dimensional
array holds is the product of values of both subscript values.

9.5.1. Declaring Two-Dimensional array:


Just like an ordinary variable, an array should be declared before it is used.
A two-dimensional array can be declared as follows:
<data type> <array_name>[row][column];
In this syntax,
<data type> is any basic data type such as int, float, char or double or any derived data type such as long
int, short int and so on.
<array_name> is any valid identifier.
row and column values are any non-negative integer constants or integer expressions.
Ex: int a[5][3]; // two-dimensional array capable of holding 15 (5*3) elements of type int
# define ROW 10
# define COLUMN 5
float b[ROW][COLUMN]; //2-D array capable of holding 15 elements of type float

9.5.2. Initializing Two-Dimensional array:


Initializing Two-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 Two-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.
Ex: int a[3][4]={{12,45,54,2},{87,76,3,4},{54,64,34,23}};
Once the above array gets initialized, the values will be stored in memory. The following memory map
depicts this thing:

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.

9.5.3. Reading and printing Two-Dimensional array:


A Two-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 loop counters for
keeping track of index values for both rows and columns. The loop counters are always integer values
those begin with 0 and ends with n-1. The loop counters 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<m;i++) // m: No.of rows i: loop counter for rows
for(j=0;j<n;j++) // n: No.of columns j: loop counter for columns
scanf(“%d”,&a[i][j]);
The above statement first reads a[0][0], then a[0][1], a[0][2], a[0][3]…and so on.
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[row-1][column-1]. E.g., we want the element at 3rd row and 2nd column position, then we
should give a[2][1] to printf() statement:
printf(“Element at 3rd row and 2nd column position is %d”,a[2][1]);
We can access all the elements in the array sequentially. For this, we use printf() statement along with
two loops as follows:
printf(“\n The array elements are:”);
for(i=0;i<m;i++)
for(j=0;j<n;j++)
printf(“%d\t”,a[i][j]);
Ex: /* Program to read and print the contents of a two-dimensional array in the form of a
matrix*/
#include<stdio.h>
main()
{ int a[10][10],m,n,i,j;
printf(“\n Enter the matrix row and column values:”);
scanf(“%d%d”,&m,&n);
printf(“\n Enter the matrix elements:”);
for(i=0;i<m;i++)
for(j=0;j<n;j++)
scanf(“%d”,&a[i][j]);
printf(“\n The Given Matrix\n”);
for(i=0;i<m;i++)
{ for(j=0;j<n;j++)
printf(“%d\t”,a[i][j]);
printf(“\n”);
}
}

142
Operations on matrices:

/*Program to add two matrices*/ /*Program to multiply two matrices*/


#include<stdio.h> #include<stdio.h>
main() main()
{ {
int a[10][10],b[10][10],c[10][10],i,j; int a[10][10],b[10][10],c[10][10],i,j;
int m,n,p,q; int m,n,p,q;

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; }

printf(“\n Identity matrix\n”);


for(i=0;i<m;i++)
{
for(j=0;j<n;j++)
printf(“%d\t”,a[i][j]);
printf(“\n”);
}
}
}

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;
}

9.6.2. Passing two-dimensional array:


To pass a two-dimensional array to called function, these rules should be followed:
 The function must be called by passing only the array name.
 In the function definition, we must indicate that the array has two dimensions by including two sets
of brackets.
146
 The size of second dimension must be specified.
 The function prototypes should be similar to the function header.
The following program demonstrates passing two-dimensional array as an argument:
/*program to print lower triangle of a matrix*/
#include<stdio.h>
void lowertriangle(int [ ][5],int,int); //function prototype
main()
{
int a[10][5],m,n,i,j;
printf(“\n Enter the matrix order (row and column values):”);
scanf(“%d%d”,&m,&n);
printf(“\n Enter the matrix elements:”);
for(i=0;i<m;i++)
for(j=0;j<n;j++)
scanf(“%d”,&a[i][j]);
lowetriangle(a,m,n);
}
void lowertriangle(int a[ ][5], int m,int n)
{
int i,j;
if(m==n)
{
for(i=0;i<m;i++)
{
for(j=0;j<n;j++)
{
if(i<=j)
printf(“%d\t”,a[i][j]);
}
printf(“\n”);

}
}
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

“The greater the loyalty of a group toward the


group, the greater is the motivation among the
members to achieve the goals of the group, and
the greater the probability that the group will
achieve its goals.” -Rensis Likert

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.

A string is an array of characters terminated by a NULL character

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.

10.2. One-Dimensional array of characters


10.2.1. Declaring a string
The string that can hold an array of characters can be declared with the following syntax:

<Storage_class> char <array_name>[size];

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.

10.2.2. Initializing a string


This one-dimensional array of characters can be initialized by using assignment operator as follows:
char a[13]={‘I’,’ ‘,’L’,’o’,’v’,’e’,’ ‘,’I’,’n’,’d’,’I’,’a’};
is equivalent to
char a[13]=”I Love India”;
In both of the cases, the NULL character can be appended to the string automatically. If the length of the
string is exceeded than the specified size in square brackets, then the compiler gives the error. This error
can be rectified with the help of the following initialization statement that automatically allocates memory
based on the number of characters in that string:
char a[]={‘I’,’ ‘,’L’,’o’,’v’,’e’,’ ‘,’I’,’n’,’d’,’I’,’a’};
(or)

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”);

10.2.3. Reading and printing a string


There are 3 ways to read a string using keyboard:
 By using scanf() function
 By using gets() function
 By using getchar() repeatedly (with the help of loops)
There are 3 ways to print a string onto the monitor:
 By using printf() function
 By using puts() function
 By using putchar() repeatedly (with the help of loops)

10.2.3.1. By using the scanf() and printf() functions


The scanf() function with the conversion character %s can be used to read a string using keyboard. The
printf() function with the same conversion character can be used to print a string onto monitor. E.g.,
#include<stdio.h>
main()
{
char str[25];
printf(“\n Enter your name:”);
scanf(“%s”,str);
printf(“\n Your Name=%s”,str);

}
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:

Ex: /* A program to count the number of occurrences of a character in a string*/


#include<stdio.h>
void display(char[]); //function prototype
int getCount(char[],int);//function prototype
main()
{
char str[30],ch;
int c;
printf(“\n Enter any string:”);
gets(str);
display(str); //function call
printf(“\n Enter the character to be searched:”);
scanf(“\n%c”,&ch);
c=getCount(str,ch); //function call
if(c>0)
printf(“\n the character %c is occurred %d times”,ch,c);
else
printf(“\n The given character is not found”);

}
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);

where string1 is the one-dimensional array of characters.


This function returns an integer value that is the count of characters in the string. E.g., string1
contains pradeep is a good boy then strlen(string1) function returns the value 21.
/* A program to calculate length of string by /* A program to calculate length of string
using strlen() function*/ without using strlen() function*/
#include<stdio.h> #include<stdio.h>
#include<string.h> int MyStringLength(char [50]);
main() main()
{ {
char string1[50]; char string1[50];
int length; int length;
printf(“\n Enter any string:”); printf("\n Enter any string:\n");
gets(string1); gets(string1);
length=strlen(string1); length=MyStringLength(string1);
printf(“\n The length of string=%d”,length); printf("\n The length of string=%d",length);
} }
int MyStringLength(char str[50])
{
int len=0,i;
for(i=0;str[i]!='\0';i++)
len++;
return len;
}

2. strrev() function: This function is used to find the reversed string of a given string. Its syntax is as
follows:
strrev(string1);

where string1 is the one-dimensional array of characters.


This function stores the reversed string of string1 in that argument string1 only. E.g., string1
contains master then the same string1 contains retsam after execution of strrev() .

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);

where string1 and string2 are one-dimensional character arrays.


This function copies the content of string2 to string1. E.g., string1 contains master and string2
contains madam, then string1 holds madam after execution of the strcpy(string1,string2) function.
/* A program to copy one string to another /* A program to copy one string to another
using strcpy() function*/ without using strcpy() function*/
#include<stdio.h> #include<stdio.h>
#include<string.h> void MyStringCopy(char[],char []);
main() main()
{ { char string1[30],string2[30];
char string1[30],string2[30]; 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); MyStringCopy(string1,string2);
strcpy(string1,string2); }
printf(“\n First string=%s”,string1); void MyStringCopy(char str1[30],char str2[30])
printf(“\n Second string=%s”,string2); { int i;
} for(i=0;str2[i]!='\0';i++)
str1[i]=str2[i];
str1[i]='\0';
printf("\n First string=%s",str1);
printf("\n Second string=%s",str2);

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);

where string1 and string2 are one-dimensional character arrays.


This function joins two strings together. In other words, it adds the string2 to string1 and the
string1 contains the final concatenated string. E.g., string1 contains prog and string2 contains ram, then
string1 holds program after execution of the strcat() function.
/* A program to concatenate one string with /* A program to concatenate one string with
another using strcat() function*/ another without using strcat() function*/
#include<stdio.h> #include<stdio.h>
#include<string.h> void MyStringConcat(char[],char[]);
main() main()
{ { char string1[30],string2[15];
char string1[30],string2[15]; 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); MyStringConcat(string1,string2);
strcat(string1,string2); }
printf(“\n Concatenated string=%s”,string1); void MyStringConcat(char str1[30],char str2[15])
} { int i,j;
for(i=0;str1[i]!='\0';i++);
for(j=0;str2[j]!=0;j++)
str1[i+j]=str2[j];
str1[i+j]='\0';
printf("\n Concatenated string=%s",str1);
}

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);

where string1 and string2 are one-dimensional arrays of characters.


When this function is invoked with two strings as arguments, then:
 This function returns -1 or negative integer, if the ASCII value of the character of the first string is
less than that of second string;
 It returns 0 (zero), if both strings are equal;
 It returns 1 or a positive integer, if the ASCII value of the character of first string is greater than
that of the second string.
E.g., string1 contains master and string2 contains minds, then strcmp(string1,string2); returns a
negative value; since the ASCII value of ‘a’ is lesser than the ASCII value of ‘i’.

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);

where string1 is the one-dimensional array of characters.


e.g., string1 holds Master MINDS, then strlwr() converts all the uppercase alphabets of string1 to
lowercase. The string1 holds the lowercase string master minds.

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);

where string1 is the one-dimensional array of characters.


e.g., string1 holds Master MINDS, then strupr() converts all the lowercase alphabets of string1 to
uppercase. The string1 holds the upprecase string MASTER MINDS.

/* A program to convert a lower case string to /* A program to convert a lowercase string to


upper case string using strupr() function*/ upper case string without using strupr()
#include<stdio.h> function*/
#include<string.h> #include<stdio.h>
main() void MyStringUpper(char[]);
{ main()
char string[30]; { char string[30];
printf(“\n Enter any lower case string:”); printf("\n Enter any lower case string:");
gets(string); gets(string);
strupr(string); MyStringUpper(string);
printf(“\n upper case string=%s”,string); }
} void MyStringUpper(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 Upper case string=%s",str);
}

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.

/* A program to concatenate first n characters /*A program to concatenate first n characters


to a string by using strncat() function*/ to a string without using strncat() function*/
#include<stdio.h> #include<stdio.h>
#include<string.h> void MyStringNCat(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:");
strncat(string1,string2,n); scanf("%d",&n);
printf(“\n First string=%s”,string1); MyStringNCat(string1,string2,n);
} }
void MyStringNCat(char str1[],char str2[],int n)
{
int i,len;
len=strlen(str1);
for(i=0;i<n;i++)
{
str1[len]=str2[i];
len++;
}
str1[len]='\0';
printf("\n concatenated string=%s",str1);
}

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;
}

Other useful string handling functions


Function Purpose
strrchr(string,char) Returns the last occurrence of a specified character in the string.
strcmpi(string1,string2) Compares string2 to string1 with out considering case of text.
strncmpi(string1,string2,n) Compares at most n characters string2 to string1 ignoring case.
stpcpy(string1,string2) Same as strcpy() except it returns string2+strlen(string1).
strdup(string1) Returns the duplicate copy of string1.
strstr(string1,string2) Finds the first occurrence of substring string2 in string1.
strset(string1,char) Sets all the characters of string1 to a given character.
strnset(string1,char,n) Sets all the first n characters of string1 to a given character.

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’);
}
}

Passing multiple strings to a function


To pass multiple strings to a function, these rules should be followed:
 The function must be called by passing only the name of the character two-dimensional array,
without the subscripts.
 In the function definition, the formal parameter must be a character two-dimensional array type;
the value of the second subscript needs to be specified.
 The function prototype must show that the argument is a character two-dimensional array with
second subscript’s value.
The following programs demonstrate the concept of passing multiple strings to a function:
/*A program to sort strings in /*A program to search for a string in
alphabetical order*/ multiple strings*/
#inlcude<stdio.h> #inlcude<stdio.h>
#include<string.h> #include<string.h>
void sort(char [][],int); int search(char [][],int,char[]);
main() main()
{ char names[10][15]; { char names[10][15],ele[15];
int n,i; int n,i,pos;
printf(“\n How many strings:”); printf(“\n How many strings:”);
scanf(“%d”,&n); scanf(“%d”,&n);
for(i=0;i<n;i++) for(i=0;i<n;i++)
{ {
printf(“\n Enter %d string:”,i+1); printf(“\n Enter %d string:”,i+1);
scanf(“%s”,names[i]); scanf(“%s”,names[i]);
} }
sort(names,n); printf(“\nEnter string to search);
} scanf(“%s”,ele);
void sort(char names[][],int n) pos=search(names,n,ele);
{ int i,j; if(pos<=0)
char temp[15]; printf(“\n String is not found”);
for(i=0;i<n;i++) else
{ printf(“\nString is found at %d position”,pos);
for(j=i+1;j<n;j++) }

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

11.2. Advantages of pointers


Pointers are used frequently in C, as they offer a number of benefits to the programmers. These include:
 Pointers can be used to access and manipulate data stored in memory directly.
 Pointers allow C to support dynamic memory allocation.
 Pointers provide an efficient way to create and manipulate efficient data structures such as stacks,
queues, linked lists, trees and graphs.
 Pointers increase the execution speed and thus reduce the program’s execution time.
 Pointers are more efficient in handling arrays and data tables.
 The use of pointer arrays to strings results in saving of data storage space in memory.
 Pointers allow to change the calling function’s arguments and to return multiple values from called
function.
 Pointers permit references to functions and thereby facilitating passing of functions as arguments
to other functions.
The real power of C lies in the proper use of pointers. The misuse of pointers causes serious problems
such as system crash.

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

Valid expressions: &a //where a is the name of variable.


&c //where c is the name of an array.
&fact //where fact is the name of function.
Invalid expressions: &253 //constant can’t be used as an operand.
&(a+b) //expression can’t be used as an operand.
&r //register type can’t be used as an operand.

Consider the declaration:


int a=20;
This declaration tells the C compiler to:
a) Reserve the required space in memory to hold the integer value.
b) Associate the name a with this memory location.
c) Store the value 20 at this location.
Suppose that the variable a occupies 2 bytes on 16-bit computer. This can be represented as follows:

a Name of variable

20 Value of variable (data item)

Address of variable (byte0 address)


1000

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?

Referencing operator (&) Bitwise AND (&)


It is a unary operator. It acts on one It is a binary operator. It acts on two
operand at a time. operands at a time.
The operand is the name of variable, array, The operands are groups of bits.
pointer, function or structure.
It returns the address of byte0 of the It returns the result of bitwise AND
operand. operation on bits.

11.4. Dereferencing operator (*)


Dereferencing operator is a unary operator. It acts on one operand at a time. It returns the value stored
at the address of operand. The operand must be an address, a pointer that holds address or a pointer
expression. This operator is also called as “value at address” operator or indirection operator.
The * operator should be preceded with the operand in order to return the value at address of operand.

*Operand_1

Valid expressions: *(&num) //where num is a variable


*&*&num
**&num

Invalid expressions: *2009 //constant value can’t be used as an operand.


*num //only addresses or pointers or pointer expressions can be used.
(*&)num //parentheses should not enclose two unary operators

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?

Indirection operator (*) Arithmetic operator(*)


It is a unary operator. It acts on one It is a binary operator. It acts on two
operand at a time. operands at a time.
The operand is the address of a variable or The operands are two variables or
a pointer or a pointer expression. expressions those return numeric values.
It returns the value at the address of the It returns the product of two operands.
operand.

11.5. Working with pointers


In order to work with pointers, do the following:
1. Declare a pointer variable
2. Initialize it.
3. Access the original value through a pointer or perform any other operation on it.

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:

<storage_class> <data type> * <Pointer_name(s)>;


In this syntax,
<storage_class> is any one of the auto, static, extern or register.
<data typte> is any one of int, float, char, double or void or data types such as signed int, long int etc,
The symbol * should be preceded with the name(s) of pointer(s).
<pointer_name> is any valid identifier. If there are more pointer_names, those should be separated with
commas.
Ex: int *iptr; //pointer-to-int
float *fptr; //pointer-to-float
char *cptr; //pointer-to-char

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.

Ex: int a=40;


int *iptr1,*iptr2; //Declaring pointer variables: iptr1,iptr2
iptr1=&a; //Initializing pointer variable: iptr1
iptr2=iptr1; //Initializing pointer variable: iptr2
Whenever a pointer variable is initialized with the address of an ordinary variable or a pointer variable, we
can say that the pointer variable points to that ordinary variable or pointer variable. This can be
represented as follows:

9879 7654 3245


Points to Points to
7654 40 7654

iptr1 a iptr2

Interview question #4

What is a void pointer (generic pointer)?


A void pointer is a pointer to which any other type of pointer or address of any other type of variable,
array, function or structure can be assigned. It can be declared as follows:
Ex: void *vptr; //generic pointer: pointer-to-void
int a=10,*iptr=&a; vptr=iptr; //vptr holds pointer-to-int
float b=13.53,*fptr=&b; vptr=fptr; //vptr holds pointer-to-float

172
Point to ponder#3

Since a generic pointer has no object type, it can not be de-referenced.

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).

Accessing a pointer variable:


Once a pointer variable is initialized, it can be used to access the address as well as content of object to
which it is pointed to. The following program demonstrates this:

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

printf(“\n The address of a=%u”,&a);


printf(“\n The address of a=%u”,iptr); //accessed to print address of a

printf(“\n The value of a=%d”,a);


printf(“\n The value of a=%d”,*(&a));
printf(“\n The value of a=%d”,*iptr); //accessed to print the content of a
}
Output: The address of a=
The address of a=
The value of a=40
The value of a=40
The value of a=40

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.

11.6. Operations on pointers


11.6.1. Pointer arithmetic
The following arithmetic operations can be performed on pointers:
 Addition of a number to a pointer.
 Subtraction of a number from a pointer.
 Subtraction of a pointer from another pointer.

The following arithmetic operations can not be performed on pointers:


× Addition, multiplication, division and modulo division of two pointers.
× Multiplication, division and modulo division of a pointer by a number.
× Shifting operations.

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.

11.6.2. Pointer comparisons


Two pointers can be compared by using relational operators as well as logical operators. When these
operators encountered, these expressions may return either true or false. The following program
demonstrates this:
175
Program #4
Write a program to demonstrate pointer comparisons
#include<stdio.h>
main()
{
int a=40,b=34;
int *iptr1,*iptr2;
iptr1=&a;
iptr2=&b;
printf(“\n Equal condition of two pointers=%d”,(ip1==ip2));
printf(“\n Not Equal condition of two pointers=%d”,(ip1!=ip2));
printf(“\n Greater than condition of two pointers=%d”,(ip1>ip2));
printf(“\n Lesser than condition of two pointers=%d”,(ip1<ip2));
printf(“\n Greater than or equals condition of two pointers=%d”,(ip1>=ip2));
printf(“\n Lesser than or equals condition of two pointers=%d”,(ip1<=ip2));
printf(“\n Logical AND condition of two pointers=%d”,( ip1>=ip2&&ip1==ip2));
printf(“\n Logical OR condition of two pointers=%d”,(ip1==ip2|| ip1<ip2));
printf(“\n Logical NOT condition of two pointers=%d”,(!(ip1==ip2)));
}
Output:

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.

11.7. Pointers and functions


11.7.1. Pointer as an argument
Pointers can also be passed as arguments to a function as normal values are being passed. This method is
also known as call by reference. By using these pointers, the calling function’s arguments can be changed
from called function. Whenever we want to pass a pointer as an argument, these things should be carried
out:
 In function prototype, place an * after the type of argument to specify that we are passing a
pointer as an argument.
 In function call, place the argument- the address of operator followed by name of argument or the
pointer that is declared earlier.
 Develop the function definition based on the specified prototype.

The following program demonstrates these:

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.

The following program demonstrates these:


Program #7
Write a program that demonstrates pointer as return value
#include<stdio.h>
int * add(int,int); //function prototype—function add() returns a pointer-to-int
main()
{
int a,b;
int *c;
printf(“\n Enter the values of a and b: ”);
scanf(“%d%d”,&a,&b);
c=add(a,b);
printf(“\n The result=%d”,*c);
}
int * add(int x,int y) //function definition
{
int z;
z=x+y;
return (&z);
}

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:

<return type> (*<name_of_ptr)(arg_type_1,arg_type_2,…);

E.g., int (*addptr)(int,int);


The above declaration tells that addptr is a pointer to a function that takes two integer
arguments and returns an integer value.
2. Assign the name of the function to that pointer. The name of the function itself acts as an address
of function.
E.g., addptr=add; // add should be the name of function
3. Call the function by using pointer in the same way as we call a function.
E.g., x=(*addptr)(10,20);
The above statement is used to call that function which is already assigned to pointer-to-function.

The following program demonstrates a pointer-to-function:


Program #8
Write a program that demonstrates pointer-to-function
#include<stdio.h>
int add(int,int); //function prototype – No change, give prototype normally.
main()
{
int a,b,c;
int (*addptr)(int,int); //step-1: pointer-to-function declaration
printf(“\n Enter the values of a and b: ”);
scanf(“%d%d”,&a,&b);
addptr=add; //step-2: Assign name of function to the pointer
c=(*addptr)(a,b); //step-3 call the function using pointer
printf(“\n The result=%d”,c);
}
int add(int x,int y) //function definition- No change, give definition normally
{
int z;
z=x+y;
return z;
}

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:

<ptr1>=(<data type> *)<ptr2>;

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?

Static memory allocation Dynamic memory allocation


It is the process of allocating memory at It is the process of allocating memory
compile time. during execution of program.
Fixed number of bytes will be allocated. Memory is allocated as and when it is
needed.
The memory is allocated in memory stack. The memory is allocated from free
memory pool (heap).

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:

void *malloc(size_t size);


The function malloc() allocates a block of size bytes from the free memory pool (heap). It allows a
program to allocate an exact amount of memory explicitly, as and when needed.
Argument: The parameter passed to malloc() is of the type size_t. This type is declared in the header file
stddef.h. size_t is equivalent to the unsigned int data type. Thus, in compilers where an int is 16 bits in
size, malloc() can allocate a maximum of 64KB at a time, since the maximum value of an unsigned int is
65535.
Return value:
 On success, i.e., if free memory is available, malloc() returns a pointer to the newly allocated
memory. Usually, it is generic pointer. Hence, it should be typecast to appropriate data type before
using it to access the memory allocate.
 On failure, i.e., if enough free memory does not exist for block, malloc() returns NULL. The
constant NULL is defined in stdio.h to have a value zero. Hence, it is safe to check the return value.

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.

2) calloc() — allocates multiple blocks of memory


The function malloc() has the following prototype:

void *calloc(size_t nitems,size_t size);


calloc() provides access to the C memory heap, which is available for dynamic allocation of variable-sized
blocks of memory.
Arguments: Unlike malloc(), the function calloc() accepts two arguments: nitems and size. The parameter
nitems specifies the number of items to allocate and size specifies the size of each item.
Return value:
 On success, i.e., if free memory is available, calloc() returns a pointer to the newly allocated
memory. Usually, it is generic pointer. Hence, it should be typecast to appropriate data type before
using it to access the memory allocated.
 On failure, i.e., if enough free memory does not exist for block, calloc() returns NULL. The constant
NULL is defined in stdio.h to have a value zero. Hence, it is safe to verify the return value before
using it.
Ex: 1) calloc(3,5); allocates 15 bytes of memory and returns the address of byte0.
2) malloc(6,sizeof(float)); allocates 24 bytes of memory and returns the address of byte0.

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:

void *malloc(size_t size); void *calloc(size_t nitems,size_t size);

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:

void *realloc(void *block,size_t size);

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().

4) free() — de-allocates memory


The function free() has the following prototype:

void free(void *block);


The function free() de-allocates a memory block pointed by block.
Argument: block is the pointer that is points to allocated memory by malloc(), calloc() or realloc(). Passing
an uninitialized pointer, or a pointer to a variable not allocated by malloc(), calloc() or realloc() could be
dangerous and disastrous.
Ex: int *a;
a=(int *) malloc(30); //first 30 bytes of memory is allocated.
free(a); //de-allocates 30 bytes of memory.
Interview question #11
How does free() know how many bytes to free?
The malloc() / free() implementation remembers the size of each block allocated and returned.
So, it is not necessary to remind it of the size when freeing.
184
11.10. Pointers and One-Dimensional numeric arrays
An array is homogeneous collection of elements stored in contiguous memory locations referred by
common name. The array name itself is the base address, i.e., the address of first element in array. As we
know that the pointer is an address, the array name itself is a pointer.
11.10.1. Accessing array elements through a pointer
Usually, each element in an array is accessed through an index that starts from 0 and ends with n-1
where n is the size of array. e.g., a[0] is the first element, a[1] is second element and so on…
Similarly, by using a pointer variable, all the elements are accessed as follows:
1. First declare a pointer variable. The type of pointer variable should be same as the type of array.
2. Initialize the pointer variable with the base address of array.
3. Access each element by placing an * before incremented pointer or before the expression of the
form (ptr+i) where ptr is the pointer variable and i is the index value.
The following program demonstrates this:
Program #11
Write a program to add elements of array using a pointer.
#include<stdio.h>
void display(int *,int);
void sum(int *,int);
main()
{
int a[10],n,i,*ptr; //step-1: Declaration of a pointer variable
printf(“\n Enter the array size:”);
scanf(“%d”,&n);
printf(“\nEnter the array elements:”);
for(i=0;i<n;i++)
scanf(“%d”,&a[i]);
ptr=&a[0]; //step-2: Initalization of pointer variable
display(a,n); //the name of the array itself is the base address
sum(ptr,n);
}
void display(int a[],int n)
{
int i; Note: a[i] is equivalent to
printf(“\n The array elements are:”); i[a] or *(a+i) or *(i+a)
for(i=0;i<n;i++)
printf(“%d\t”,a[i]);
}
void sum(int *ptr,int n)
{
int i,total;
total=0;
//step-3: Accessing array elements through pointer
for(i=0;i<n;i++)
total=total+*ptr++; //or total=total+*(ptr+i);
printf(“\n The sum of array elements=%d”,total);
}
Output:
Enter the array size:5
Enter the array elements: 2 4 6 3 1 185
The array elements are: 2 4 6 3 1
The sum of array elements=16
11.10.2. Dynamically allocated 1-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 #12
Write a program to sort elements of array using pointers.
#include<stdio.h>
void display(int *,int);
void sort(int *,int);
main()
{
int *a,n,i; //step-1: Declaration of a pointer variable
printf(“\n Enter the array size:”);
scanf(“%d”,&n);
a=(int *) malloc(n*sizeof(int)); //step2: Allocate memory
printf(“\nEnter the array elements:”);
for(i=0;i<n;i++)
scanf(“%d”,a+i);
display(a,n);
sort(a,n);
free(a); //step-4: de-allocating memory
}
void display(int a[],int n)
{ Note: a[i] is equivalent to
int i; i[a] or *(a+i) or *(i+a)
printf(“\n The array elements are:”);
for(i=0;i<n;i++)
printf(“%d\t”,a[i]); //step-3: accessing elements
}
void sort(int *ptr,int n)
{
int i,j,temp;
for(i=0;i<n-1;i++)
{
for(j=i+1;j<n-i-1;j++)
{
if(*(ptr+i)>*(ptr+j)) //step-3: accessing elements
{
temp=*(ptr+i);
*(ptr+i)=*(ptr+j);
*(ptr+j)=temp;
}
}
}
printf(“\n After sorting:”);
display(ptr,n);
}

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.

11.10.3. Function returning 1-D array


By using pointers, a function can return more than one value at a time. As array contains more than one
element and array name is the base address, we can return the base address. This gives us a view that a
function can return more than one value at a time. The following program demonstrates this concept:
Program #13
Write a program to demonstrate a function that returns a sorted array.
#include<stdio.h>
int * sort(int a[],int); //function prototype
main()
{
int *p;
int a[10],n,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]);
printf("\n Before sorting:");
for(i=0;i<n;i++)
printf("%d\t",a[i]);
p=sort(a,n); //function call- p holds the base address of returned array
printf("\n After sorting:");
for(i=0;i<n;i++)
printf("%d\t",*p++);
}
int *sort(int a[],int n)
{
int i,j,temp;
for(i=0;i<n;i++)
{
for(j=i+1;j<n;j++)
{
if(a[i]>a[j])
{
temp=a[i];
a[i]=a[j];
a[j]=temp;
}
}
}
return a; //sends the base address of sorted array
}
Output:
Enter the array size: 5
Enter the array elements:35
3
46
43
1
Before sorting: 35 3 46 43 1 187
After sorting: 1 3 35 43 46
11.11. Pointers and Two-Dimensional numeric arrays
The two-dimensional array is an array with two subscripts. As same with one-dimensional numeric array,
the name of two-dimensional array is also a base address. i.e., it is the address of element that is present
in first row and first column (address of a[0][0]).
11.11.1. pointer-to-2-D array
The way we can have a pointer to an integer, or a pointer to a float, can we also have a pointer to an
array? The answer is YES. A two-dimensional array can be accessed through a pointer as follows:
1. First, declare a pointer to array. This declaration of pointer-to- 2-D array is little clumsy. It has the
following form:

<data type> (*<ptr_name>)[size];

Ex: int (*q)[4];


This declaration gives a meaning that q is a pointer-to-2-D array of 4 columns.
2. Once a pointer is declared, it should be initialized with the name of 2-D array that was declared
and initialized earlier.
e.g., ptr=a; where a is two-dimensional array.
3. Now, each element gets accessed with the help of the following expression:
*(*(ptr+i)+j) where i is the index of row and j is the index of column.

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

printf("\n Enter the first matrix order:");


scanf("%d%d",&m,&n);
printf(“\n Enter second matrix order:”);
scanf(“%d%d”,&p,&q);
if(n!=p)
printf(“\n Sorry, matrix multiplication is not possible”);
else
{
a=(int **)malloc(m*sizeof(int));
for(i=0;i<m;i++) step-2
a[i]=(int *)malloc(n*sizeof(int));
printf("\n Enter first matrix elements");
for(i=0;i<m;i++)
for(j=0;j<n;j++) step-3
scanf("%d",&a[i][j]);
printf(“\n First matrix\n”);
display(a,m,n);

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);
}

11.11.3. Array of pointers


There is an array of ints or an array of floats. Similarly, there can also be an array of pointers. Since, a
pointer is an address; an array of pointers is nothing but a collection of addresses. The addresses present
in the array of pointers can be addresses of isolated variables or addresses of array elements or any other
addresses. All rules that apply to an ordinary array apply to the array of pointers as well. The following
program demonstrates the concept of array of pointers:
Program #16
Write a program to demonstrate array of pointers.
#include<stdio.h>
main()
{
int *a[4]; //declaration of array of pointers
int i=32,j=45,k=2,l=35,m;
a[0]=&i;
a[1]=&j;
a[2]=&k;
a[3]=&l;
for(m=0;m<3;m++)
printf(“%d\t”,*(a[m])); //accessing the content in each element that is a pointer
}
Output: 32 45 2 35

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;

printf("\n Enter matrix order");


scanf("%d%d",&m,&n);

for(i=0;i<m;i++)
a[i]=(int *)malloc(n*sizeof(int));

printf("\n Enter matrix elements:");


for(i=0;i<m;i++)
for(j=0;j<n;j++)
scanf("%d",&a[i][j]);

printf("\n The original matrix\n");


for(i=0;i<m;i++)
{
for(j=0;j<n;j++)
printf("%d\t",a[j][i]);
printf("\n");
}

printf("\n The transpose of matrix\n");


for(i=0;i<n;i++)
{
for(j=0;j<m;j++)
printf("%d\t",a[j][i]);
printf("\n");
}
}
Output:
Enter matrix order: 2 3
Enter matrix elements: 1 2 3 4 5 6
The original matrix
1 2 3
4 5 6
The transpose of matrix
1 4
2 5
3 6

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”);
}
}
}

Interview question #13


Compare array of pointers to pointer-to-array?
1) A pointer to an array is a variable that contains the address of (points to) a multi-dimension variable
that could contain anything (multiple strings or multiple longs etc.).
An array of pointers is a single-dimensional variable that holds muliple addresses (pointers) each of
which could point to anything (other variables, objects etc.).

2) The number in subscript of pointer-to-array denotes the number of columns.


The number in subscript of array of pointers denotes the number of rows.

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

11.12.2. Pointer to a string


Suppose we wish to store the string “Hello friend”. We may either store it in a character array or we may
ask the C compiler to store it some where in memory and assign the address of that string in a char
pointer. This is shown below:
char message[]=”Hello friend”;
char *p=”Hello friend”;
However, there are differences between these two:
1. The size of character array will be more than the size of the character pointer.
Ex: #include<stdio.h>
main()
{
char message[]=”Hello friend”;
char *p=”Hello friend”;
printf(“\n Size of character array=%d”,sizeof(message));
printf(“\n Size of character pointer=%d”,sizeof(p));
}
194
Output (on 32-bit machine):
Size of character array=13
Size of character pointer=4
2. A char pointer can be assigned to another char pointer; but a character array can’t be assigned to
another character array.
Ex: #include<stdio.h>
main()
{
char message[]=”Hello friend”;
char mesg2[20];
char *p=”Hello friend”;
char *q;

mesg2=message; //A blunder


q=p; //works
}

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”;
}

11.12.3. Array of pointers to strings


As an array of integer pointers is used to represent a two-dimensional array of integers, array of character
pointers is used to hold multiple strings. To deal with multiple strings with the help of array of character
pointers, do the following:
1. First, declare an array of character pointers.
e.g., char *a[10];
This declaration is used to define a 10-element array of pointers. Thus, a[0] points to first
string, a[1] points to second string and so on.
2. It is not necessary to include a maximum string size within declaration. However, it is necessary to
allocate maximum string size as follows:
for(i=0;i<n;i++) // n is number of strings
a[i]=(char *) malloc(15*sizeof(char)); //15 is each string’s maximum length
3. After memory is allocated, the array of character pointers can be initialized and accessed as normal
arrays.

The following program demonstrates this concept:

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;

printf(“\n Enter how many strings:”);


scanf(“%d”,&n);

for(i=0;i<n;i++)
names[i]=(char *) malloc(15*sizeof(char));

printf(“\n Enter %d names:”,n);


for(i=0;i<n;i++)
scanf(“%s”,names[i]);

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

Interview question #14


Why can’t I get strcat() to work? I tried
char *s1=”Hello”;
char *s2=”World”;
strcat(s1,s2);
printf(“%s”,s1);
The main problem here is that the space for the concatenated result is not properly allocated. C
compilers allocate memory only for specified objects explicitly mentioned in the source code. The
programmer must arrange for sufficient space for the results of run-time operations, such as string
concatenation, typically by declaring arrays or by calling malloc().
The strcat() function performs no allocation. Since, there is no space for concatenated result in
first string (or destination string), the strcat() function returns run-time error.
196
Interview question #15
Compare arrays and pointers?
1) An array is a homogeneous collection of elements stored in contiguous memory locations referred
by a common name.

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.

2) An array can hold a collection of pointers.

A pointer can hold the base address of an array that is collection of elements.

3) An array can’t be assigned to another array (even of same type) directly.

A pointer can be assigned to another pointer (of same type only) directly.

4) A pointer can be incremented.

An array name (though it is an address of first element) can not be incremented.

5) The size of array is fixed. It can never be changed.

The memory allotted to a pointer can be reallocated.

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:

const <data type> * <ptr_name>;

E.g., const int *p;


The above statement declares p as a pointer to constant integer.
2) Once a pointer is declared, initialize it with the address of a const value or const array.
E.g., const int a=23;
p=a; //initialization of pointer with base address of array of constants
3) Access the const value or const array with the help of pointer.
It is important to note that the value that is being pointed can never be changed. But the pointer that
points to constant can be changed. In other words, it can be incremented or decremented.
E.g., The following program demonstrates this concept:
#include<stdio.h>
main()
{
const int *ptr1,*ptr2;
const int i=20;
const int a[]={10,20,40,23};
ptr1=&i;
ptr2=a;
printf(“%d”,*ptr1); //prints the value of i
i=30; //a blunder—trying to change the content of const
printf(“%d”,*ptr1);
ptr2++; //valid—a pointer to const can be changed
printf(“%d”,*ptr2); // prints the value of a[1]
}
Note: These types of pointers are very useful in char pointers, when pointers are to be passed to a
function for printing. Suppose, we are writing a function that is aimed to print a character string, it is good
practice to code that function as follows:
void printstring(const char *str)
{
printf(“%s”,str);
}
The above function accepts a pointer of type const char *(pointer to constant character). The string that
is being pointed can never be changed. This is safety measure, since it prevents the accidental
modification of the string that is being passed to called function.
Points to ponder #6
Pointer-to-constant means that the value is not changed
198 through that pointer, not which is unchanged
through any pointer.
11.13.2. Constant pointer
When we want to deal with a constant pointer, do the following:
1) Declare a constant pointer that has the following form:

<data type> * const <ptr_name>=<address>;

E.g., int a=20;


int * const p=&a;
The above statement declares p as a constant pointer that holds the address of a.
2) Access the constant pointer to print the original content of variable or array whose address is stored.
E.g., printf(“%d”,*p); //prints the value of a
It is important to note that the value that is being pointed can be changed. In the above example, the
value of a can be changed. But the value of constant pointer can never be changed. i.e., in the above
example, p++ or ++p is invalid.
Note: const int * const p=&a;
The above declaration disallows the modification of both p and a. i.e., both pointee and pointer.
Interview question #15
What is the difference between const char *p and char* const q?
1) p is a pointer-to-constant char.
P will be changed. But *p will never be changed.

2) q is a constant pointer.
q will never be changed. But *q will be changed.

11.14. Command line arguments


We can also pass arguments to the function main() as we pass arguments to other functions. The main()
function accepts two arguments: argc (argument count) and argv (argument vector). It has the following
form:
main(int argc,char *argv[])
{
}
(or)
main(int argc,char **argv)
{
}

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

Write a program to demonstrate command line arguments


#include<stdio.h>
main(int argc,char *argv[])
{
printf(“\n Number of arguments supplied=%d”,argc);
if(argc!=3)
{
printf(“\n Insufficient number of arguments”);
exit(0);
}
printf(“\n The arguments supplied are:”);
for(i=0;i<argc;i++)
printf(“\t%s”,argv[i]);
}
Output:
$cc command.c
$./a.out apple boy cat dog //suggestion: (separate each string with space)
Number of arguments supplied=5 //(including a.out)
The arguments supplied are: a.out apple boy cat dog

Program #23

Write a program to add numbers using command line arguments


#include<stdio.h>
#include<stdlib.h>
main(int argc,char *argv[])
{
int sum,i;
for(i=1,sum=0;i<argc;i++)
sum=sum+atoi(argv[i]); //atoi() function converts a string to number
printf(“\n sum=%d”,sum);

}
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])();

11.16. Problems with pointers


1) Segmentation fault (or segfault):
This generally means that a program tried to access the memory it shouldn’t have, invariably as a result
of improper pointer use. The most likely causes could be inadvertent use of null pointers or uninitialized,
misaligned, or otherwise improperly allocated pointers, corruption of malloc area and mismatched function
arguments, especially involving pointers; two possible cases are scanf(“%d”,i) (without ampersand) and
fprintf(invalid FILE* argument).
A segmentation fault occurs when an attempt is made to access memory whose address is well-
formed, but to which access can’t be granted. This might be due to either a protection fault or an invalid
page fault.
2) Un-initialized pointer:
This generally occurs when we declared a pointer, forgot to initialize it with an address and tried to access
the content through pointer. E.g.,
int *ptr, val=300;
*ptr=val; /*Error*/
3) When we want to assign a value to a pointer variable, then that assignment leads to an
error. E.g., int *p, val=24;
p=val; /*Error*/

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.

"The minute we become an integrated whole, we


look through the same eyes and we see a whole
different world together."
-- Azizah Al-Hibri

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.

12.1.2. Working with structures


In order to work with a structure, one should do these things:
 Declare its prototype.
 Create variable(s) of that structure.
 Initialize and access the members of that structure.

12.1.2.1. Declaring a structure


A structure is a user-defined data type or an ADT. As a user-defined data type, the structure groups
different types of data items into a single entity. Each type of data item is also referred to as a member of
structure. A structure can be declared as follows:

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.

Ex: struct student


{
int rno,age;
char name[15],sex;
float fees;
};

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.

12.1.2.2. Creating a structure variable


After the declaration of structure, a variable of that type of structure should be created in order to access
the members of structure. The creation of variable takes the following form:

struct <tag> <var1,var2…varN>;

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.

There are different ways to create variables:

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.

typedef <data type> <new type>;

Ex: typedef unsigned long int ULONG;


This data type ULONG provides a short and meaningful way to call the data type: unsigned long int.
Now, the new data type ULONG can be used to declare variables.
ULONG a,b,c; // variables are of type unsigned long int

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.

12.1.2.3. Initializing and accessing members of a structure


Membership operator (.): The members of a structure can be accessed with the help of membership
operator (.). The members of structure can be accessed with the help of membership operator or dot or
period as follows:
<structure_variable>.<member_name>

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;

Initializing members of structure:


Once structure is declared and a variable of that structure type is created, the members in that structure
can be initialized with the help of that structure variable. This can be done in two ways:
1. By using assignment operator.
2. By using scanf() statement
By using assignment operator
A structure can be initialized in its declaration itself with list of initializers enclosed within the curly braces.
Each initializer must be a constant and the order and type of each initializer must match with the order
and type of each member in declaration.
Ex: The above two structure variables stud1 and stud2 of structure type student can be intialized as
follows:
struct student stud1={13,18,”Balaji”,’m’,27500};
struct student stud2={5,18,”Sravani”,’f’,27500};
The above two variables can also be initialized as follows:
struct student
{
int rno,age;
char name[15],sex;
float fees;
}stud1={13,18,”Balaji”,’m’,27500},stud2={5,18,”Sravani”,’f’,27500};
The memory map for the structure variable stud1 is as follows:

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>;

Ex: struct student


{
int rno,age;
char name[15],sex;
float fees;
};
struct student stud1,stud2;

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];
}

if(stud1.marks[0]<35 || stud1.marks[1]<35 || stud1.marks[2]<35)


strcpy(stud1.grade,”failed”);
else if(stud1.total>=250)
strcpy(stud1.grade,”First class”);
else if(stud1.total<250 && stud1.total>=150)
strcpy(stud1.grade,”second class”);
else
strcpy(stud1.grade,”Third class”);
printf(“\n %s has got %s”,stud1.name,stud1.grade);
}
12.1.4.2. Array of structures
An array is a collection of elements of same data type that are stored in contiguous memory locations. A
structure is a collection of members of different data types stored in contiguous memory locations. An
array of structures is an array in which each element is a structure. This concept is very helpful in
representing multiple records of a file, where each record is a collection of dissimilar data items.

Ex: An array of structures for structure student can be declared as


struct student s[20];
In this example student[20] is a structure variable. It may contain the details of 20 students. Each record
may be accessed and processed separately like individual elements of an array.

213
Program #5 Program #6

/* program to read multiple student details /* program to read mutliple Employee


and print them*/ details and 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 stud[15]; struct address add;
int i,n; }EMPRECORD;
printf(“\n Howmany records:”);
scanf(“%d”,&n); EMPRECORD e[10];
int i,n;
for(i=0;i<n;i++) printf(“\n Howmany records:”);
{ scanf(“%d”,&n);
printf(“\n enter student %d rno , name , age ,
sex,fees”,i+1); for(i=0;i<n;i++)
scanf(“%d%s%d\n%c%f”,&stud[i].rno, {
stud[i].name, &stud[i].age, &stud[i].sex, printf(“\n enter %d employee number, name,
&stud[i].fees); designation, salary and work experience”,i+1);
printf(“\n Enter date-of-birth”); scanf(“%d%s%s%f%d”,&e[i].empno,
scanf(“%d%d%d”,&stud[i].dob.dd,&stud[i].dob. e[i].ename, e[i].designation, &e[i].salary,
mm,&stud[i].dob.yy); &e[i].experience);
}
printf(“\n======================”); printf(“\n Enter address ( street , area , city ,
printf(“\nRno\tName\tAge\tSex\tfees\tdate-of- pincode )”);
birth”); scanf(“%s%s%s%ld”,e[i].add.street,
printf(“\n======================”); e[i].add.area, e[i].add.city, &e[i].add.pincode);
for(i=0;i<n;i++) }
{ printf(“\n======================”);
printf(“\n%d\t%s\t%d\t%c\t%f\t%d/%d/%d”, printf(“\nEno\tEName\tdesignation\tsalary\t
std[i].rno,stud[i].name,stud[i].age,stud[i].sex, experience\t address”);
stud[i].fees,stud[i].dob.dd,stud[i].dob.mm, printf(“\n======================”);
stud[i].yy); for(i=0;i<n;i++){
} printf(“\n%d\t%s\t%s\t%f\t(%s, %s, %s, %ld)”
printf(“\n======================”); e[i].empno,e[i].ename,e[i].designation,e[i].salar
} y,e[i].experience,e[i].add.street,e[i].add.area,e[i]
.add.city,e.add.pincode); }
printf(“\n======================”);}

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.

/*A program to create and display the contents of linked list*/


#include<stdio.h>
#include<malloc.h>
struct Node
{ int data;
struct Node *next;
};
main()
{ struct Node *firstnode,*prevnode,*newnode;
int value;
printf(“\n Enter integers (-999 to stop):”);
scanf(“%d”,&value);
firstnode=prevnode=NULL;
while(value!=-999)
{ newnode=(struct Node*) malloc(sizeof(struct Node));
newnode->data=value;
newnode->next=NULL;

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======================================================”);
}

12.1.5.4. Array of structure pointers and dynamic memory allocation


Memory is allocated dynamically for array of structure pointers also same as to array of 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:

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]);
}
}
}

void swap(struct student *p,struct student *q)


{
struct student temp;
temp=*p;
*p=*q;
*q=temp;
}
12.1.6. Structures and Functions
12.1.6.1. Structure as an argument
A structure can be passed to a function as a single variable. When we pass an entire structure to a
function, we are passing it by call by value method. Because we are working on the copy of the structure,
any changes made to the structure members within the function are not reflected in the original structure.

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);
}

12.1.6.2. Structure as a return value


When we pass a structure variable as an argument to a function, we are passing it to the called function
by using call-by-value method. Because we are working on the copy of the structure, any changes made
to the structure members within the function are not reflected in the original structure. Hence, it is
necessary for the function to return entire structure back to the calling function. The following program
demonstrates this concept:
/* A menu-driven program to perform various operations on complex numbers*/
#include<stdio.h>
typedef struct complexnumber
{
float real;
float imag;
}COMPLEX;

COMPLEX add(COMPLEX,COMPLEX);
COMPLEX sub(COMPLEX,COMPLEX);
COMPLEX mul(COMPLEX,COMPLEX);
COMPLEX div(COMPLEX,COMPLEX);

main()
{
COMPLEX c1,c2,c3;

printf("\n enter first complex number (real,imaginary):");


scanf("%f%f",&c1.real,&c1.imag);
printf("\n enter second complex number (real,imaginary):");
scanf("%f%f",&c2.real,&c2.imag);
while(1)
{
printf(“\n1.Add\n2.Subtract\n3.Multiply\n4.Divide\n5.Exit”);
printf(“\n Enter your choice:”);
scanf(“%d”,&ch);
switch(ch)
{
219
case 1: c3=add(c1,c2);
printf("\n Result=%f+%fi",c3.real,c3.imag);
break;
case 2: c3=sub(c1,c2);
printf("\n Result=%f+%fi",c3.real,c3.imag);
break;
case 3: c3=mul(1,c2);
printf("\n Result=%f+%fi",c3.real,c3.imag);
break;
case 4: c3=div(c1,c2);
printf("\n Result=%f+%fi",c3.real,c3.imag);
break;
case 5: exit(0);
default: printf(“\n Wrong choice”);
}
}
}

COMPLEX add(COMPLEX c1,COMPLEX c2)


{
COMPLEX c;
c.real=c1.real+c2.real;
c.imag=c1.imag+c2.imag;
return c; //returning a structure
}

COMPLEX sub(COMPLEX c1,COMPLEX c2)


{
COMPLEX c;
c.real=c1.real-c2.real;
c.imag=c1.imag-c2.imag;
return c; //returning a structure
}

COMPLEX mul(COMPLEX c1,COMPLEX c2)


{
COMPLEX c;
c.real=(c1.real*c2.real)-(c1.imag*c2.imag);
c.imag=(c1.real*c2.imag)+(c1.imag*c2.real);
return c; //returning a structure
}

COMPLEX div(COMPLEX c1,COMPLEX c2)


{
COMPLEX c;
float temp;
temp=(c2.real*c2.real)+(c2.imag*c2.imag);
c.real=((c1.real*c2.real)+(c1.imag*c2.imag))/temp;
c.imag=((c2.real*c1.imag)-(c1.real*c2.imag))/temp;
return c; //returning a structure
}

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=================================================”);
}

12.1.6.4. Pointer-to-structure as an argument


When we pass a structure variable as an argument to a function, we are passing it to the called function
by using call-by-value method. Because we are working on the copy of the structure, any changes made
to the structure members within the function are not reflected in the original structure. So, to change the
called function’s arguments in called function, we can pass a pointer-to-structure as an argument. The
following program demonstrates this concept:

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 *highest(EMPRECORD [],int); //function prototype

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);

printf(“\n Enter address ( street , area , city , pincode )”);


scanf(“%s%s%s%ld”,e[i].add.street, e[i].add.area, e[i].add.city, &e[i].add.pincode);
}
temp=highest(e,n);
printf(“\n Highest salary paid employee details\n”);
printf(“\n Name=%s”,temp->ename);
printf(“\n Designation=%s”,temp->designation);
printf(“\n Salary=%.2f”,temp->salary);
}

EMPRECORD *highest(EMPRECORD e[],int n)


{
float s;
int pos;
s=e[0].salary;
for(i=1;i<n;i++)
{
if(s<e[i].salary)
pos=i;
}
return (&e[pos]); //returns pointer-to-structure
}
Programming Examples
1) /*A menu-driven program to process student records (using array of structures)*/
#include<stdio.h>
struct student
{
int rno,rank;
char name[15];
struct date_of_birth
{
int day,month,year;
}dob;
};
void display(struct student[],int);
void insert(struct student[],int);
void delete(struct student[],int);
void search(struct student[],int);
main()
{
int n,i,ch;
struct student stud[10];
printf("\n Enter how many students:");
scanf("%d",&n);
for(i=0;i<n;i++)
223
{
printf("\n Enter student %d details",i+1);
printf("\n Enter roll number:");
scanf("%d",&stud[i].rno);
printf("\n Enter name:");
scanf("%s",stud[i].name);
printf("\n Enter rank:");
scanf("%d",&stud[i].rank);
printf("\n Enter date of birth(day,month,year):");
scanf("%d%d%d",&stud[i].dob.day,&stud[i].dob.month,&stud[i].dob.year);
}
while(1)
{
printf("\n1.Print\n2.Insert\n3.Delete\n4.Search\n5.Exit");
printf("\n Enter your choice:");
scanf("%d",&ch);
switch(ch)
{
case 1: display(stud,n);
break;
case 2: insert(stud,n);
break;
case 3: delete(stud,n);
break;
case 4: search(stud,n);
break;
case 5: exit(0);
default: printf("\n Wrong choice");
}
}
}
void display(struct student s[],int n)
{
int i;
printf("\n Student details");
for(i=0;i<n;i++)
{
printf("\n%d\t%s\t%d\t%d/%d/%d",s[i].rno,s[i].name,s[i].rank,s[i].dob.day,s[i].dob.month,
s[i].dob.year);
}

}
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));

printf("\n Enter second matrix elements:");


for(i=0;i<m2.row;i++)
for(j=0;j<m2.col;j++)
scanf("%d",&m2.data[i][j]);

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));

printf("\n Resultant matrix:\n");


for(i=0;i<m3.row;i++)
{
for(j=0;j<m3.col;j++)
{
m3.data[i][j]=m1.data[i][j]+m2.data[i][j];
printf("%d\t",m3.data[i][j]);
}
printf("\n");
}
}
}

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.

12.2.1.1. Declaring a union


A union is declared same as a structure is declared except the keyword union. A union is declared as
follows:
union <tag>
{
<data type1> <member(s)>;
<data type2> <member(s)>;
:
:
<data typeN> <member(s)>;
};
In this syntax,
 union is the keyword. <tag>, an optional one, serves as a name for this union. It is used to
declare variable of the same union type. It should be a valid identifier. The first line of this
declaration is called as union header.
 All the members of the union should be enclosed in curly braces. These members may be variables,
constants, arrays, pointers and so on. 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 union
body.
It is important to note that the union declaration should be ended with a semi colon. The union name or
members of union may be omitted, but both, should not be omitted.
Ex: union student
{
int rno,age;
char name[15],sex;
float fees;
};
In this example, the union student consists of the members: rno and age as integers, name and sex as of
char type and fees as of type float.

12.2.1.2. Creating a union variable


A union variable is created same as a structure variable is created. After the declaration of union, a
variable of that type of union should be created in order to access the members of union. The creation of
variable takes the following form:

union <tag> <var1,var2…varN>;

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().

12.2.1.3. Accessing the members of a union


Just like in a structure, the membership operator or dot is used in between union variable and member of
union in order to access the member of union.
Ex: union student
{
int rno,age;
char name[15],sex;
float fees;
}s1;
In order to access the member fees of this union, we should use this statement: s1.fees

12.2.2. Properties of union

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>;

Ex: struct student Ex: union student


{ {
int rno,age; int rno,age;
char name[15],sex; char name[15],sex;
float fees; float fees;
}; };
struct student stud1,stud2; union student stud1,stud2;

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.

Interview question #12


What are the differences among these?
#define I 20
const int I=20;
enum val{I=20};
The use of an enumeration constant (enum) has many advantages over using the traditional symbolic
constant style of #define. These advantages include a lower maintenance requirement, improved
program readability, and better debugging capability.
1) The first advantage is that enumerated constants are generated automatically by the compiler.
Conversely, symbolic constants must be manually assigned values by the programmer.
2) Another advantage of using the enumeration constant method is that our programs are more
readable and thus can be understood better by others who might have to update our program later.
3) A third advantage to using enumeration constants is that some symbolic debuggers can print the
value of an enumeration constant. Conversely, most symbolic debuggers cannot print the value of a
symbolic constant. This can be an enormous help in debugging our program, because if our program is
stopped at a line that uses an enum, we can simply inspect that constant and instantly know its value.
On the other hand, because most debuggers cannot print #define values, we would most likely have to
search for that value by manually looking it up in a header file.

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.

Ex: # define MALE 0


# define FEMALE 1
# define SINGLE 0
# define MARRIED 1
# define DIVORCED 2
# define WIDOWED 3
struct employee
{
char *name;
unsigned gender:1;
int mar_status:2;
float salary;
}emp1;
main()
{
emp1.name=”Divyasree”;
emp1.gender=FEMALE;
emp1.mar_status=SINGLE;
emp1.salary=25000.00;
printf(“\n Name=%s”,emp1.name);
printf(“\n gender=%d”,emp1.gender);
printf(“\n Marital status=%d”,emp1.mar_status);
printf(“\n Salary=%f”,emp1.salary);
}

The following are the limitations of bit fields:


 Bit fields do not have addresses.
 Bit fields can not be read using scanf() function.
 Bit fields can not be accessed using pointer.
 Bit fields can not store the values beyond their limits. If larger values are assigned, the output is
undefined.
 Programs written using bit fields are not portable because of the implementation defined nature of
bit fields.
233
13
Files
0

Chapter Outline
“Pain is never permanent."
-- St. Teresa of Avila 13.1. Introduction.

13.2. Types of files.

13.3. Basic operations on files.

13.4. Random-access files.

13.5. Error-handling

13.6. Concept of binary files.


Scratch a dog and you'll find a permanent job.”
-- Franklin P. Jones
13.7. Conclusion.

“Life belongs to the living, and he who lives


must be prepared for changes.”
--Johann Wolfgang von Goethe

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

Stream-oriented Files System-oriented Files


(Standard) (Low-level)

Text Files Binary Files


(Formatted) (Unformatted)

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);

From this prototype, it is clear that:


o fputc() takes two arguments: a character that is to be written to file and pointer to
the structure FILE.
o On success, it returns an unsigned integer. Otherwise, it returns EOF.

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:

fprintf(pointer_to_FILE,<format string>,< variables>);

From this prototype, it is clear that:


o fprintf() is same as printf(), except that it accepts a file pointer as first argument.
o On success, it returns the number of bytes output. Otherwise, it returns EOF.
Ex: struct student
{ int rno,rank;
float fees;
char name[15];
}s1;

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
}

13.3.3. Reading from a file


The functions scanf(), gets() and getch() are used to read content from the keyboard. To read from a
file, the functions fscanf(), fgets() and fgetc() are used. All these functions accept a FILE pointer as
one of the parameters along with other parameters required by the standard input functions.
1) Reading a character from a file: To read a character 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 fgetc() that is used to read a character from file which has the following
prototype:

int fgetc(pointer_to_FILE);

From this prototype it is clear that:


o fgetc() takes an argument which is a pointer to the structure FILE and returns an
unsigned integer value that should be converted to a character. We should place that
file pointer which is already returned by using fopen().
o When end-of-file is reached or there is an error, the predefined character EOF is
returned.
Ex: FILE *fp;
char ch;
fp=fopen(“sample.txt”,”r”); //step-a: Open file in read mode
ch=fgetc(fp); //step-b : read a character from file
while(ch!=EOF) //read character-by-character till the end-of-file is reached
{
printf(“%c”,ch); // step-c: display that character on monitor
ch=fgetc(fp);
}
2) Reading a String from a file: To read a string from the 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 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);

From this prototype it is clear that:

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.

Ex: FILE *fp;


char *str=””; //initialize with empty string
fp=fopen(“sample.txt”,”r”); //step-a: open file in read mode.
fgets(str,10,fp); //step-b: str holds the string that is read from file
printf(“%s”,str); //prints the string to monitor.

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:

fscanf(pointer_to_FILE,<format string>,<addresses of variables>);

From this prototype it is clear that:


o fscanf() is same as scanf(), except that it accepts a file pointer as first argument.
o On success, it returns the number fields successfully scanned, converted and stored. On
failure, it returns 0, if no fields are stored.

Ex: struct student


{
int rno,rank;
float fees;
char name[15];
}s1;
FILE *fp;
fp=fopen(“student.dat”,”r”); //step-a:open file in read mode
fscanf(fp,”%d%s%d%f”,&s1.rno,s1.name,&s1.rank,&s1.fees); //step-b: read formatted content from file
printf(“\nRoll number=%d”,s1.rno);// step-c: display content on monitor
printf(“\n Name=%s”,s1.name);
printf(“\n Rank=%d”,s1.rank);
printf(“\n Fees=%.2f”,s1.fees);

13.3.4. Closing a file


During a write to a file, the data written to it is not put on the disk immediately. It is stored in a buffer (a
temporary storage area in primary memory). When the buffer is full or the program gets ended, all the
content in buffer is actually written back to the disk. The process of emptying the buffer by writing its
content back to disk is called flushing the buffer.
Closing a file flushes the buffer and releases the space taken by FILE structure which is returned by
fopen(). If we want to close a file, pass its file pointer to the function fclose() that has the following form:

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

fp=fopen(filename,”r”); //open the same file in read mode


if(fp==NULL)
{
printf(“\n unable to open”);
exit(0);
}
printf(“\n The content of file %s is:”,filename);
ch=fgetc(fp); //get a character from file
while(ch!=EOF) // check the character is not EOF
{
printf(“%c”,ch); //print that character on monitor
ch=fgetc(fp);
}
fclose(fp); //close the file
}
Output:
Enter the file name to be created: master.txt
Enter some text to file (ctrl+d to end):
Master minds are not born. They are made.
Master minds’ numbers consist of digits: 0-9
The persons who read this text are master minds
The content of file master.txt is:
Master minds are not born. They are made.
Master minds’ numbers consist of digits: 0-9
The persons who read this text are master minds
243
Interview question #4
What do you mean by FILE (all uppercase letters)?
FILE is a predefined structure whose definition is available in stdio.h. It has the following definiton:
typedef struct
{
int level; /*fill/empty level of buffer*/
unsigned flags; /*file status flags*/
char fd; /*file descriptor (file handler)*/
unsigned char hold; /*Ungetc char if no buffer*/
int bsize; /*Buffer size*/
unsigned char _FAR *buffer;/*Data transfer buffer*/
unsigned char _FAR *curp; /*current active pointer*/
unsigned istemp; /*temporary file indicator*/
short token; /*used for validity checking*/
}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);

From this prototype, it is clear that:


o feof() function takes one argument: the file pointer to which we want to search for EOF
character.
o On success, it returns non-zero if an end-of-file character is detected. If end-of-file is not
reached, then it returns 0.

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);
}

ch=fgetc(fp1); //get a character from source file


while(ch!=EOF) // check that character is not EOF
{
fputc(ch,fp2); //write that character to destination file
ch=fgetc(fp1); //Again, read a character from source file
}
fclose(fp); //close the file
}
Output:
Enter an existing filename to be opened: master.txt
Enter the file name to which the content should be copied: copy.txt
Usually, the content of first file is copied to second file. To check the correctness of program, type the
destination file name by using vi command at $ prompt. If we get the content of source file in
destination file, the program is absolutely correct.

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);

fp=fopen(“sturecords”,”r”); //open the file in read mode


if(fp==NULL)
{
printf(“\n Unable to open file”);
exit(0);
}
printf(“\n content of sturec file:”);
while(fscanf(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)!=EOF) //read a record from file
{
printf(”\n%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); //print the record onto monitor
}
fclose(fp);
}
Output:
Enter student details (rno, name ,rank ,fees and date of birth):1
Mercylin
193
27500.00
29
2
1990
Do you want to add one more record (y/n):n
Content of sturec file: 247
1 Mercylin 193 27500.00 29/2/1990
The above program has one disadvantage: if the members of structure are increased, the functions
fprintf() and fscanf() become difficult to understand. To solve this problem, fwrite() and fread()
functions are introduced.
 The function fwrite() is used to write formatted data to the file. It has the following form:

size_t fwrite(ptr,size,n,pointer_to_FILE);

From this prototype, it is clear that:


o fwrite() takes four arguments: ptr is a pointer to the data that is to be written. Size is a
value of type size_t, an unsigned integer, used to hold the size of data that is to be written.
n is a value of type size_t, an unsigned integer, used to hold number of data items to be
appended. Pointer_to_FILE is the pointer to the file in which the data is to be written.
o On success, it returns the number of items (not bytes) actually written. on failure, it returns
a short count (possibly zero).
Ex: struct student s1;
fwrite(&s1,sizeof(s1),1,fp);

 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);

fp=fopen(“sturecords”,”r”); //open the file in read mode


if(fp==NULL)
{
printf(“\n Unable to open file”);
exit(0);
}
printf(“\n content of sturec file:”);
while(!feof(fp)) //read a record from file
{
fread(&s2,sizeof(s2),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); //print the record onto monitor
}
fclose(fp);
}
Output:
Enter student details (rno, name ,rank ,fees and date of birth):25
Naveen
193
27500.00
29
2
1990
Do you want to add one more record (y/n):n
Content of sturec file:
25 Naveen 193 27500.00 249
29/2/1990
13.4. Random-access files
Random-access files are the stream-oriented files in which the accessing of data is done at any position.
That is the data should be written to or read from any position in the specified file. A position pointer is
always associated with a file while reading or writing. Read and write operations are done at the position
pointed by this pointer. In order to perform random-access while reading a file, the functions fseek(),
ftell() and rewind() functions are very helpful:
1. fseek()- places the position pointer at the specified position.
2. rewind()- places the position pointer to the beginning of the file.
3. ftell()- tells the current position of the position pointer in the file.
fseek() function: The fseek() function is used to place the position pointer at the specified location in the
file. It has the following prototype:

int fseek(pointer_to_FILE,offset,location);

From this prototype, it is clear that:


o fseek() function takes three arguments: the first argument is the file pointer that points to the file
in which the position pointer should be placed. The second argument, a long integer value, is the
position at which the pointer should be placed. If it is positive value, the file position pointer will
be moved forward. If it is negative number, the file position pointer will be moved back. The third
argument takes one of the following three:
Constant value File location
SEEK_SET 0 Seeks from beginning of file.
SEEK_CUR 1 Seeks from current position.
SEEK_END 2 Seeks from end of file.
o On success, it returns 0. On failure, it returns a non-zero value. fseek() returns an error code only
when an unopened file or when a non-existing device is accessed.
rewind() function: The function rewind() is used to place the position pointer to the beginning of the
file. It has the following prototype:

void rewind(pointer_to_FILE);

From this prototype, it is clear that:


o rewind() function takes one argument: a pointer to the FILE in which we want to place the position
pointer at the beginning of the file.
The same operation can also be done using the function call:
fseek(pointer_to_FILE,0,0);

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

Write a program to demonstrate fseek(), ftell() and rewind() functions


#include<stdio.h>
main()
{
FILE *fp;
char ch;
fp=fopen("stud.txt","w+");
if(fp==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,fp);
ch=getchar();
}
ch=fgetc(fp);
while(ch!=EOF)
{
printf("%c",ch);
ch=fgetc(fp);
}
fseek(fp,5,SEEK_SET); //place the cursor at the position 5
printf("\n The cursor is at %d position",ftell(fp)); //tells the cursor position as 5
printf("\n Enter the character to insert:");
scanf("\n%c",&ch);
fputc(ch,fp); //inserts the character at specified position
ch=fgetc(fp);
while(ch!=EOF) //prints all the characters from specified position
{
printf("%c",ch);
ch=fgetc(fp); The content of stud.txt
} pradKep is a good boy.
rewind(fp); //places the cursor to the beginning of file
printf("\n The cursor is at %d position",ftell(fp));
fclose(fp);

}
Output:
Enter the text into file (end with ctrl+d):
pradeep is a good boy.

The cursor is at 5 position


Enter the character to insert:K
ep is a good boy.

The cursor is at 0 position

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

Enter the record number to read (0 to stop): 2


2 maya 13 23500.00 11/9/2004
Enter the record number to read (0 to stop): 1
1 master 1 27500.00 12/ 3/1990
Enter the record number to read (0 to stop): 0

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;

printf("\n Enter file name:");


scanf("%s",filename);
fp=fopen(filename,"w");
printf("\n Enter the text (end with ctrl+d):");
ch=getchar();
while(ch!=EOF)
{
fputc(ch,fp);
ch=getchar();
}
fclose(fp);
printf("\n Enter the word to be searched:");
scanf("%s",word);
fp=fopen(filename,"r");
//fscanf(fp,"%s",temp);
while(!feof(fp))
{
fscanf(fp,"%s",temp);
if(strcmp(temp,word)==0)
count++;
}
fclose(fp);
printf("\n The word %s is occured %d times",word,count);
}
Output:
Enter the file name: sample.txt
Enter the text into file (end with ctrl+d):
Mater minds are not made.
Master minds are born.
Enter the word to be searched: minds
The word minds is occurred 2 times.

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 error-handling functions in C are:


perror() function: The perror() function is used to print the nature of the error. It has the following
prototype:

void perror(char *msg);

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];

printf("Enter filename: ");


gets(filename);

if (( fp = fopen(filename, "r")) == NULL)


{
perror("You made a mistake");
exit(1);
}
else
{
puts("File opened for reading.");
fclose(fp);
}
}
Output:
Enter file name: master.xxx
You made a mistake: No such file or directory.

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:

int ferror(pointe r_to_FILE);

From this prototype, it is clear that:


o ferror() function takes one argument: the file pointer .
o On success, it returns non-zero if an error is detected on the named file pointer.

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.

13.6. Concept of binary files


Apart from text files, every computer uses another kind of files that are known as binary files. All machine
language files such as files with extension .com, .exe, .obj, .dll, etc are actually binary files. For opening a
binary file, file mode has to be mentioned as “rb” or “wb” in fopen(). Otherwise, all files are opened in
default mode, which is text mode. These binary files should be handled in a different way as compared to
text files. The binary files differ from text files in three ways:
1) The storage of new line characters: In text files, \n is stored as a single new line character by
user, but it takes 2 bytes of storage inside the memory. Actually, new line character is collection of
two characters- first carriage return (\r ASCII code 13) and second line feed (ASCII code 10).
When a text file stores \n, it is stored using 2 bytes, but is considered as a single character. So

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

You might also like