C Programming - Rajiv Chopra, PHD
C Programming - Rajiv Chopra, PHD
Programming
LICENSE, DISCLAIMER OF LIABILITY, AND LIMITED WARRANTY
By purchasing or using this book (the “Work”), you agree that this license
grants permission to use the contents contained herein, but does not give you
the right of ownership to any of the textual content in the book or ownership
to any of the information or products contained in it. This license does not
permit uploading of the Work onto the Internet or on a network (of any kind)
without the written consent of the Publisher. Duplication or dissemination
of any text, code, simulations, images, etc. contained herein is limited to and
subject to licensing terms for the respective products, and permission must
be obtained from the Publisher or the owner of the content, etc., in order to
reproduce or network any portion of the textual material (in any media) that is
contained in the Work.
The author, developers, and the publisher of any accompanying content, and
anyone involved in the composition, production, and manufacturing of this
work will not be liable for damages of any kind arising out of the use of (or the
inability to use) the algorithms, source code, computer programs, or textual
material contained in this publication. This includes, but is not limited to, loss
of revenue or profit, or other incidental, physical, or consequential damages
arising out of the use of this Work.
The sole remedy in the event of a claim of any kind is expressly limited to
replacement of the book and only at the discretion of the Publisher. The use
of “implied warranty” and certain “exclusions” vary from state to state, and
might not apply to the purchaser of this product.
C
Programming
A Self-Teaching Introduction
By
RAJIV CHOPRA, PhD
This publication, portions of it, or any accompanying software may not be reproduced in
any way, stored in a retrieval system of any type, or transmitted by any means, media,
electronic display or mechanical display, including, but not limited to, photocopy, record-
ing, Internet postings, or scanning, without prior permission in writing from the publisher.
The publisher recognizes and respects all marks used by companies, manufacturers, and
developers as a means to distinguish their products. All brand names and product names
mentioned in this book are trademarks or service marks of their respective companies. Any
omission or misuse (of any kind) of service marks or trademarks, etc. is not an attempt to
infringe on the property of others.
Our titles are available for adoption, license, or bulk purchase by institutions, corporations,
etc. For additional information, please contact the Customer Service Dept. at 800-232-
0223(toll free).
All of our titles are available in digital format at authorcloudware.com and other digital
vendors. The sole obligation of Mercury Learning and Information to the purchaser is to
replace the book, based on defective materials or faulty workmanship, but not based on the
operation or functionality of the product.
Contents
Preface viii
Acknowledgments x
Chapter 1: C Overview 1
1.0 Introduction 1
1.1 The Concept of Algorithms and Pseudocodes 2
1.2 Flowcharts 8
1.3 Compiler Overview 15
1.4 Assembler, Linker, and Loader 19
1.5 Structure of a Simple “Hello World” Program in C 22
1.6 Overview of the Compilation and Execution
Process in an Integrated Development Environment
(preferably CodeBlock) 30
Summary 32
Exercises 32
Appendices 341
B: Keywords in C 343
References 347
Index 349
Preface
The right temperament required for research originates from the right expo-
sure and environment that a student receives during study. And good books
help in this direction.
Programming is an art. You have to learn this art, as only then will you learn
how to write good programs.
This book is an outcome of lecture notes prepared during my long years of
teaching Introduction to Programming (C), augmented by consulting a large
number of books available on the subject. I thank my students, colleagues, and
teachers, as well as all the authors who have helped in shaping my approach to
this knowledge.
Acknowledgments
A dream is visualized by a pair of eyes; however, many pairs of hands join to-
gether and work hard toward its realization. This book has been a similar en-
terprise.
I next thank my college staff, director, and HOD for their contributions to
this book on the C programming language.
I would also like to thank the entire staff of Mercury Learning for bringing
the book to a new market.
Finally, I would like to thank my wife, Mrs. Shakti, my twin kids, Arjessh
and Arshitha Chopra, as well as my parents who cooperated with me in all terms
in order to write this book.
Dr. Rajiv Chopra
CHAPTER
1
C Overview
1.0 INTRODUCTION
T
he C programming language was developed by Dennis Ritchie at AT&T
Bell Laboratories in the early 1970s. Soon after, Bell Laboratories devel-
oped a new operating system, called UNIX. About 90% of the code for
the Unix operating system (OS) was exclusively in C. As C gained popularity,
more and more vendors joined the race and developed their own compilers.
This was necessary because until the late 1970s, only Bell Laboratories had a C
compiler.
In the early 1980s, realizing the need to standardize the C language, the
American Standards Institute (ANSI), an organization that handles such mat-
ters, began the task. In 1990, the first official ANSI standard definition of C was
published. Soon C became omnipresent and thus there was a need of further
standardization. The International Standards Organization (ISO) adopted a
standard called ISO/IEC 9899:1990. After 1990, many additional changes were
made in the C language. In 1993, an ANSI C committee (known as X3J11), was
formed to standardize C. The most recent standard was adopted in 1999. It is
known as ANSI C99 or ISO/IEC 9899:1999. Since then, ANSI C has been im-
plemented on a wide variety of computers, including IBM-compatible personal
computers (PCs), mainframes, minicomputers, and workstations.
C is a higher-level language that nevertheless allows the programmer to deal
with hardware at a much lower level. Please note that although C is a general-
purpose programming language, it was designed with systems program-
ming applications in mind. So it provides a lot of power and flexibility.
2 • C Programming
This chapter discusses some basic terminology related to C and also ex-
plains the process of compiling a program written in the C language.
if (a > b)
Step 3: do if (a > c)
Step 4: then Print ‘a’ and go to step-12.
Step 5: else
Step 6: Print ‘c’ and go to step-12.
Step 7: else
Step 8: do if (b > c)
Step 9: then Print ‘b’ and go to step-12.
Step 10: else
Step 11: Print ‘c’ and go to step-12.
Step 12: Stop
In all of the preceding dry runs, the expected output equals the
NOTE observed output.
Step 5: else
Step 6: do if (x = y && y! =z) || (x = z && z!=y) || (y=z &&x!=z)
Step 7: then do if (x = sqrt( z2 /2) || (x = sqrt(y2 /2) || (y = sqrt(x2 /2))
Step 8: Print: ‘Right Angled Isosceles Triangle’ and go to step 17.
Step 9: else
Step 10: Print: ‘Isosceles Triangle’ and go to step 17.
Step 11: else
Step 12: do if (x = sqrt(z2 + y2 )) || (y = sqrt(z2 + x2 )) || (x = sqrt(x2 + y2 ))
Step 13: then Print: ‘Right Angled Scalene Triangle’ and go to step 17.
Step 14: else Print: ‘Scalene Triangle’ and go to step 17.
Step 15: else
Step 16: Print: ‘Not a triangle’ and go to step 17.
Step 17: Stop.
Process:
Is (x + y > z) && (y + z > x) && (x + z > y)?
True
Is x = y && y = z?
False
Is (x =y && y!=z) || (x=z && z!=y) ||(y=z && z!=x)?
True
Is (32 + 42 = 52) → True
Observed Output: Right Angled Scalene Triangle
Dry Run 3:
Input: x = 6
y = 6
z = 6
Expected output: Equilateral Triangle
Process:
Is (6 + 6 > 6) ? → True
Is (6 = 6 = 6) → True
Observed Output: Equilateral Triangle
In all of the preceding dry runs, it is seen that the expected output
NOTE equals the observed output.
1.2 FLOWCHARTS
Amount due
Start
Read
quantity,
price
Multiply quantity
by price
Write
amount bill
Stop
1. Each algorithm should have only one entry point and one exit point.
2. A null statement is shown by a flow line; there is no symbol for null.
Variable ← Expression
Start/Stop
Decisions
C Connector
Flow of control
Module call
start
Input
a,b,c
Y
Is a>b? Is a>c? Print a
N N
Y
Is b>c ? Print c
Print c Print b
Stop
C Overview • 13
Start
Input
a, b, c
Print 'Not
a
Is a=0?
quadratic
equation'
D = b2 – 4ac
Is D>0
OR roots=(-b+ sqrt(D))/2a
D<0?
ROOTS=-b /2a
Print
ROOTS
STOP
Example 6: It is desired to add n numbers. Write the following for this
problem:
Hint: (a) Plain English: First, read n numbers to be added. Initialize a re-
sultant value to 0. Then add these numbers to this resultant value one by one.
When all the numbers have been added, display the result.
(b) Structured English:
Step 1: Start
Step 2: Initialize sum and number of elements to add to 0.
Step 3: Read the number of elements to add—that is, read n.
Step 4: Read a number to be added and let it be a.
Step 5: s=s+a and i=i+1
Step 6: If i<n, go to step 4, else go to step 7.
Step 7: Display (output) the value of sum.
Step 8: Stop.
(c) Pseudocode:
Algo_ add(a, n)
{
s:= 0.0;
for i:=1 to n do
s:= s + a [i]; S + a [i];
return s;
}
(d) C Code:
int add(int a[ ] , int n)
{
int i, s=0;
for(i=0; i <n ; i++)
s=s + a[i];
return s;
}
C Overview • 15
Start
Source
program
Edit
(file.c)
Compile
and
assemble
yes Object
Errors program
? (file.o)
no
Link
Libraries
and other Execute Executable
object object
program (a.out)
Results
no OK?
yes
Finish
Figure 1.3 Basic Steps for Entering, Compiling, and Executing C Programs
Explanation: The program that is to be compiled is first typed and saved into
a file. C programs are saved with a .c extension. Thus, program1.c might be a
valid filename for a C program. A C program is typed, saved, and edited in a
text editor. For example, vi is a popular text editor used on Unix systems. The
program that is entered into the file is known as the source program
because it represents the original form of the program expressed in the
C language. After the source program is entered into a file, you can then pro-
ceed to have it compiled. The compilation process is initiated by typing a special
command on the system. When this command is entered, the name of the file
that contains the source program must also be specified. For example, on Unix
systems, the command to initiate program compilation is called cc.
But please remember that if you are using the popular GNU C compiler,
the command you use is gcc. So typing the line
gcc program1.c
has the effect of initiating the compilation process with the source program
contained in program1.c.
C Overview • 17
In the first step of the compilation process, the compiler examines each
of the program statements contained in the source program and checks to en-
sure that each conforms to the syntax and semantics (meaning) of the language.
Practically speaking, the C compiler normally makes a prepass of the program
looking for special statements. This is also known as a preprocessing phase. If
any mistakes are discovered by the compiler during this phase, they are report-
ed to the user and the compilation process ends right there. Then the errors
have to be corrected in the source program using an editor and the compilation
process must be restarted. Typical errors reported during this phase of compi-
lation might be due to an expression that has unbalanced parentheses (syntax
error) or due to the use of a variable that is not defined (i.e., semantic error).
When all the syntactic and semantic errors have been removed from the
program, the compiler then proceeds to take each statement of the program
and translate it into lower form. This means that each statement is trans-
lated by the compiler into the equivalent statement or statements in
assembly language needed to perform the task.
After the program has been translated into an equivalent assembly language
program, the next step in the compilation process is to translate the assembly
language statements into actual machine instructions. This step might or might
not involve the execution of a separate program known as an assembler. On
most systems, the assembler is executed automatically as part of the compila-
tion process. The assembler takes each assembly language statement and con-
verts it into a binary format known as object code which is then written into
another file on the system. This file typically has the same name as the source
file under Unix, with the last letter as “o” (for object) instead of a “c”. In Win-
dows, the suffix letters “obj” typically replace the “c” in the filename.
After the program has been translated into object code, it is ready to be
linked. This process is once again performed automatically whenever the cc
or gcc command is issued under Unix. Also understand that the purpose
of the linking phase is to get the program into a final form for execu-
tion on the computer. If the program uses other programs that were previ-
ously processed by the compiler, then during this phase the programs are linked
together. Programs that are used from the system’s program library are also
searched and linked together with the object program during this phase. The
process of compiling and linking a program is known as building. The
final linked file, which is in an executable object code format, is stored in
another file on the system, ready to be run or executed.
Under Unix, this file is called a.out (by default).
18 • C Programming
Under Windows, the executable file usually has the same name as the
source file, with the c extension replaced by an exe extension.
The command a.out is used to execute the program. This command will
load the program called a.out into the computer’s memory and initiate its ex-
ecution. When the program is executed, each of the statements of the program
is sequentially executed in turn. If the program requests any data from the
user (called input), the program temporarily suspends its execution so that the
input can be entered. Or the program might simply wait for an event, such
as a mouse being clicked, to occur. Results that are displayed by the program
(called outputs) appear in a window (also called console). Or the output might
be directly written to a file on the system.
If the program works correctly, there is no problem, but this does not of-
ten happen on the first attempt. If the program does not produce the desired
results, it is necessary to go back and reanalyze the program’s logic. This is
known as the debugging phase, during which an attempt is made to remove
all known problems or bugs from the program. Doing this requires making
changes to the original source program. Please note that in such a case, the
entire process of compiling, linking, and executing the program must
be repeated until the desired results are obtained. Also note that in
general, gcc follows the following processing steps:
Step 1: Preprocessing (invokes cpp)
Step 2: Compilation
Step 3: Assembly (invoke as)
Step 4: Linking (invokes ld).
This can also be shown graphically, as in Figures 1.4 and 1.5.
gcc
Myprog.c Myprog.s
8086 m/c code
Assembler as
Myprog.s Myprog.o
(x86 m/c code)
gcc
Myprog.c Myprog.o
8086 m/c code
Linker ld
Myprog.o Myprog
(x86 m/c code)
Each computer has its own machine language that is made of streams of
0s and 1s. This is so because computers are made up of switches, transistors,
and other electronic devices that can be either in 1 (logic high) or 0 (logic low)
states. These are also named as 0 (off state) and 1 (on state).
into machine language. The program that translates symbolic code into
machine language is known as an assembler.
Then in the 1960s came the introduction of high-level languages that re-
lieved the programmer of the tedious task of writing programs in assembly
language. Both symbolic and higher-level languages share one thing in com-
mon—both must be converted into machine language. And this process of
converting them is known as compilation.
For example, the first high-level language was FORTRAN (FORmula
TRANslation). It was created by John Backus and an IBM team in 1957. C is
also a high-level language used for developing system software and new appli-
cations.
Often a program is so large that it is convenient to break it down into small-
er units. Each of these units is stored in a separate file. After these separate
program files are compiled, they must somehow be linked together to form a
single program. This linking is usually accomplished by a program called
a linkage editor, which is often run automatically when a program is
compiled. This linker assembles all of the functions (both user-defined
as well as system functions) into a final executable program.
Once a program has been linked, it is ready for execution. To execute a
program, we use an operating system command like the run command. This
command will load the program into primary memory and execute it. And get-
ting the program into memory is the function of an operating system
program known as the loader. It locates the executable program and
reads it into memory. When everything is loaded, the program takes
control and it begins execution.
We are in a position to solve some examples now.
Example 1: Compare a compiler and an interpreter.
Solution 1: The following chart compares a compiler and an interpreter:
Compiler Interpreter
1. Converts the whole program into 1. Converts the program into ma-
machine code and then executes chine code one step at a time and
the entire program. then runs only
that step.
2. Lists all errors after compilation. 2. Immediately displays any error in
any line of the program after the
translation of that line.
C Overview • 21
Preprocessor Directives
Global declarations
Main function
This program has only one preprocessor directive. There are no global
declarations and no local definitions. It simply displays “Hello World!” on the
screen. Then there are two statements, one to print the message and the other
to stop the program.
Let us learn about these parts now.
Working of Preprocessor
When you issue the command to compile a C program, the program is run au-
tomatically through the preprocessor. The preprocessor is a program that modi-
fies the C source program according to the directives supplied in the program.
An original source program is usually stored in a file. The preprocessor does not
modify this program file but creates a new file that contains the processed ver-
sion of the program. This new file is then submitted to the compiler.
When we compile this program, the compiler shows the number of lines
compiled to be greater than 6. This is because during the preprocessing stage,
the include preprocessor directive (line 1) searches the file stdio.h in the pre-
scribed list of directories and if the header file is found, the include directive
is replaced by the entire content of the header file. If the included header file
contains another include directive, it will also be processed. This processing
is carried out recursively till either no include directive remains or till
the maximum translation limit is achieved (ISO specifies a maximum of
15 nested levels of include files). Thus, one line of source code gets replaced
by multiple lines of the header file. During the compilation stage, these added
lines will also be compiled. Thus, the compiler shows the number of lines to be
greater than 6.
13. Header files also provide consistency among several program files.
Often a program is large and thus it is possible to break it into smaller
units, each of which is stored in a separate file. After these separate
program files are compiled, they must somehow be linked together to
form a single program. This linking is usually done by a program called
the linkage editor (which is run automatically when a program is
compiled).
14. A header file can contain other #include directives. Please note that
it cannot include itself because this would result in an infinite
recursion. Also note that it cannot include another file that
includes the first file as this would also result in an infinite
recursion.
15. Header files can contain any text at all. They may also contain C code
to define structure templates, global variables, or function definitions.
However, header files usually do not contain function definitions, as it is
more efficient to store these in the function libraries set up by the user.
But global variables are sometimes included.
16. If stdio.h is included in the program, the macro versions (to be discussed
later) are used. On the other hand, if the programmer wishes to use the
function versions they can be undefined after the #include<stdio.h>
directive.
17. A preprocessor directive is terminated by the end of the line it oc-
cupies but if necessary it can be continued onto one or more lines by
ending all but the last line with backslashes.
After identifying the main( ) to the system, we must now specify what this
routine must do. And this is done by enclosing all program statements of the
routine within a pair of curly braces (line 3). Also note that all program
statements included between the braces are taken as part of the main
routine by the system. In the Hello World! program, we have only two such
statements. The first statement tells that a routine named printf is to be
invoked or called. The string of characters “hello world! \n” is the pa-
rameter or argument to be passed to the printf routine.
Just remember that the printf routine is a function in the C library. It simply
prints or displays its arguments on your screen in between double quotation
marks. Also note that a blank space in a string counts as a character.
Also seen in line 4 are two special characters—the backslash (\) and the
letter n—that are together known as the newline character. This newline
character tells the system to do precisely what its name implies—that
is, go to a new line (next line).
This exit status can be tested by other programs like the UNIX
NOTE shell to see whether the program ran successfully.
The end of the program is marked off by a closing brace. Remember the
following programming tips:
1. The number of opening braces and closing braces must be the same.
2. These braces line up with the letter ‘m’ of the main( ).
28 • C Programming
All of the tools like text editor, preprocessor, compiler, and linker that are
required for developing programs are integrated into one package known as an
IDE.
Codeblocks is an open source, cross-platform IDE. A global variable or a
function defined in one source file can be used in another source file in a mul-
tifile program. Let us see how.
Consider a program that consists of two source files, t1.c and t2.c. The
source file t2.c contains the definition of a variable var1 and a function fun1.
These definitions are used in another source file t1.c of the program. Because
the global variables and the function have external linkage, this usage is al-
lowed. And this can be done with CodeBlock as follows:
Say, file t1.c has the following code:
#include<stdio.h>
main( )
{
C Overview • 31
[Hint: Preprocessor directives are the lines to be executed before the ac-
tual compilation of the code starts. And wherever in the program code the
macros are called, the code of that macro is inserted. On the other hand,
in a function call, the body of the function is executed at runtime. And
wherever in a code the functions are called, the execution of the program
jumps to the body of the function. Code is not copied as in the case of
preprocessor directives.]
Q7. Name some popular C language IDEs.
[Hint: There are various IDEs on the market today targeted toward differ-
ent operating systems. For example, Turbo C and Turbo C++ are popular
compilers that work under MS-DOS, Visual Studio and Visual Studio Ex-
press Edition are compilers that work under Windows, whereas the gcc
compiler works under Linux. Please note here that the Turbo C, Turbo
C++, and gcc compilers can also be installed on machines running Win-
dows. Both the Visual Studio Express Edition and gcc compilers are free
of cost and can be downloaded easily.]
Summary
In this chapter, we have studied what an algorithm is. We have defined terms
like flowcharts, pseudocode, and structured English. Also we have seen how a
C program is compiled and run. The roles of assemblers, linkers, and loaders
have also been examined. We have specifically focused on the gcc compiler.
The chapter also shows the basic structure of any C program. It also discusses
the IDEs that are used to compile and run C programs like CodeBlocks.
Exercises
Q1. What is a C preprocessor? Explain each of them.
Q2. How do you debug a C program? Discuss the purpose of preprocessor
directive statements and macros as used in the C language?
Q3. What is an interactive debugger?
Q4. Distinguish between the following with examples:
(a) Syntactic errors and semantic errors
(b) Runtime errors and logical errors
(c) Debugging and testing
Q5. What is the scope of a preprocessor directive within a program file?
C Overview • 33
(c) How would you modify the above commands to link a library called
process2 stored in the home directory?
(d) Some header files need to be read and have been found in a header
subdirectory of your home directory and also in the current work-
ing directory. How would you modify the compiler commands to ac-
count for this?
Q21. Suppose you have a C program composed of several separate files and
they include one another as shown in the following chart:
File Name Include Files
main.c stdio.h, process1.h
input.c stdio.h, list.h
output.c stdio.h
process1.c stdio.h, process1.h
process2.c stdio.h, list.h
2
Programming Using C
2.0 INTRODUCTION
C
is a general purpose, block-structured, procedural, case-
sensitive, freeflow, portable, powerful high-level programming
language. This language is so powerful that an operating system like
UNIX is itself coded in C. It is said that programming languages are born,
age, and eventually die but the C programming language has only matured
from the time it was born. It has the same relevance today as it had when it
was developed by Dennis Ritchie at Bell Telephone Laboratories in 1972. The
importance of the language can be easily fathomed from the fact that C is a
prerequisite in any software industry today.
modifies the C source program according to the directives supplied in the pro-
gram. An original source program is usually stored in a file. The preprocessor
does not modify this program file but creates a new file that contains the pro-
cessed version of the program. This new file is then submitted to the compiler.
When we compile this program, the compiler shows the number of lines
compiled to be greater than 6. This is because during the preprocessing stage,
the include preprocessor directive searches the file iostream.h in the pre-
scribed list of directories and if the header file is found, the include directive
is replaced by the entire content of the header file. If the included header file
contains another include directive, it will also be processed. This processing
is carried out recursively till either no include directive remains or till
the maximum translation limit is achieved (ISO specifies a maximum of
15 nested levels of include files). Thus, one line of source code gets replaced
by multiple lines of the header file. During the compilation stage, these added
lines will also be compiled. Thus, the compiler shows the number of lines to be
greater than 6.
8. It tells the preprocessor that you want the library file in angular
brackets (< >) to be included in your program. The name of this
header file is iostream.h. It stands for “Standard input/output header
stream file.”
9. The angular brackets tell the preprocessor to search for the file in
one or more standard directories. These directories contain header files
that are provided by the system and those commonly used by several
programmers (if the computer is a multiple-user machine).
10. Sometimes the brackets are replaced with double quotation marks as in
the following:
#include “iostream.h”
In this case the preprocessor will first look in the program-
mer’s own directory or the same one that contains the program
file. If it is NOT found there, then the standard directories are
searched.
Definition Section
In this section, we define a variable with some value in it. This is also known as a
special constant section. Here, a define statement is used. The general syntax
of a symbolic preprocessor or symbolic compiler directive can be defined using
the following #define statement:
#define name value
For example,
#define PI 3.1417
This initializes a variable PI with a value of 3.1417. But please remember
the following points regarding a #define preprocessor directive:
For example,
#define PI 3.1417 (is valid).
But #define PI = 3.1417 (is invalid).
Similarly, #define NAME “Rajiv” (is valid).
#define R ‘r’ (is valid).
But #Define PI 3.1417 (is invalid, as ‘D’ must be in lowercase).
# define PI 3.1417 (is invalid, as no space is allowed between #
and define).
#define PI, R 3.14, 5 (is invalid, as multiple initializations are
not allowed).
void main( )
{
char c;
printf(“\nEnter the text:”);
c= getchar( );
printf(“The output text is: “);
while (c!= ‘\n’)
{
if (c = = “ || c= = ‘\t’)
{
c = ‘ ‘;
putchar( c );
}
while(c = = ‘ ‘ | | c = = ‘\t’)
{
c = getchar( );
}
putchar(c );
c = getchar( );
}
printf(“\n”);
}
OUTPUTS (after running)
Enter the text: DR. RAJIV CHOPRA
The output text is: DR. RAJIV CHOPRA
Certain functions are used for data input and data output. These functions are
called standard input-output functions. In C, these functions are put under
two categories:
Next let us discuss the printf( ) function. The printf( ) function is used to
accept output data from a computer to a standard device in a fixed format. It is
a formatted output function. Its syntax is as follows:
Syntax
printf(“format string”, arguments);
For example,
printf(“My name is Dr. Rajiv”); /* double quotes are
used */
For another example,
printf (“%d”, a);
Also note that here the value of ‘a’ is inserted at the ‘%d’ position
and thus the value of ‘a’ gets printed.
Functions like getchar( ), putchar( ), printf( ), and scanf( ) are defined in the
stdio.h file. Functions like strlen( ), strcpy( ), strcat( ), strcmp( ), and strrev( ) are
defined in a string.h header file. A function like exit(0) is defined in a process.h
file. Similarly, functions like sin( ), cos( ), tan( ), and so on are included in a
math.h header file. Please note that all these functions that are included
in one or the other header files are built into the C library. This means
that the C compiler will automatically execute their code and give the
desired result. Also note that we cannot modify these inbuilt functions.
If we want to modify any of these functions, we have to write our own functions,
known as user-defined functions.
With every C compiler a large set of useful string handling library
functions is provided. These functions are predefined in the compiler of the
language and stored in a special library file.
C has a concept of data types that are used to define a variable before its use.
The definition of a variable will assign storage for the variable and define the
type of data that will be held in the location. The value of a variable can be
changed any time. In C, the following data types are given:
Programming Using C • 45
(a) int
(b) float
(c) double
(d) char
Please note that there is not a Boolean data type. C does not have the
traditional view of logical comparison. Actually, data types in C are listed under
three main categories:
number is insufficient, we can use the double to define the number. The
double is the same as a float but with a greater precision. To extend
precision further we can use a long double, which consumes 80 bits
of memory space.
For example, float a;
Void is used to specify the type of a function.
The size and range of each data type is shown in Table 2.1.
Table 2.1: Data Types, Sizes, and Ranges
Note that short, long, signed, and unsigned are modifiers. These
modifiers define the amount of storage allocated to the variable. Also remem-
ber that as per ANSI rules:
short int <= int <= long int
float <= double <= long double
This means that a ‘short int’ should assign less than or the same
amount of storage as an ‘int’ and the ‘int’ should require the same or
fewer bytes than a ‘long int’.
It is possible to find out how much storage is allocated to a data type by us-
ing the sizeof operator. These ranges are defined in the limits.h header file.
Variables
A variable is a named area of storage that can hold a single value (nu-
meric or character). Every variable used in the program should be de-
Programming Using C • 47
2.6 ENUMERATION
There are two types of user-defined type declarations in C. In the first, a user
can define an identifier that represents an existing data type. The user-defined
data type can later be used to declare variables. Its syntax is:
48 • C Programming
Modifiers
Please note that one can alter the data storage of any data type by pre-
ceding it with certain modifiers. These are called data type modifiers.
Programming Using C • 49
They include short, long, unsigned, and signed. Not all combinations of types
and modifiers are allowed in C. Also note that long and short are modifiers
that make it possible for a data type to use either more or less memory.
Type Qualifiers
A type qualifier is used to refine the declaration of a variable, a func-
tion, and parameters by specifying whether the value of a variable can be
changed or the value of a variable must always be read from memory rather
than from a register. In C they are of two types:
1. const
2. volatile
Let us discuss them one by one.
I. const Qualifier
A const qualifier tells the C compiler that the value of a variable cannot
be changed after its initialization. For example,
const float pi = 3.1417;
That is, now pi cannot be changed throughout the program.
Another way of doing this is using the #define preprocessor directive as
follows:
#define PI 3.1417
But please remember that const and #define are different. #define
constants are declared at the beginning of the program, even before
main( ). On the other hand, const variables can be placed anywhere
within the program. So const has finer control than #define. #define cannot
be placed anywhere in the program. This gives an error.
again x is initialized to 20. Now, x is a local variable. And the rule is that
whenever there is a conflict between a local and a global variable, it is
the local variable that gets first priority. Also note that since the global
variable is available to the entire program, it need not be passed as a
parameter.
There are two ways by which data can be made available to other parts
NOTE of the program. Either declare them as global variables or pass them
as parameters or arguments.
Global variables are declared at the top of the program file. They are initial-
ized automatically by the system when you define them.
2.7 OPERATORS
Arithmetic Operators
C provides two unary and five binary arithmetic operators (see Table 2.2).
Table 2.2: Showing Arithmetic Operators in C
Symbol Meaning
+ Unary plus
– Unary minus
* Multiplication
/ Division
% Modulus (remainder operator)
+ Binary Addition
– Binary Subtraction
Increment/Decrement Operators
In C, we have ++ (increment) and decrement (– –) operators that increment or
decrement the variable’s value by 1. This can be done in two ways:
Assignment Operators
We have already studied how the assignment operator assigns the value of the
expression which is on its right to the left-side variable. Each assignment state-
ment itself returns a value.
For example,
counter1=counter2 =1;
In this statement, the effect is to assign the value of 1 to both of the variables—
counter1 and counter2. Please note here that the assignment operator has
right-to-left associativity; that is, here counter2 is assigned a value of 1 first
and then it is assigned to the variable counter1.
Symbol Meaning
+= Addition Assignment
–= Subtraction Assignment
*= Multiplication Assignment
/= Division Assignment
%= Modulus Assignment
Relational Operators
Relational operators are used to compare two expressions. When two expres-
sions are compared they return either a true or false value. C supports the rela-
tional operators shown in Table 2.4.
54 • C Programming
Symbol Meaning
> Greater than
< Less than
== Equal to
!= Not equal to
<= Less than or equal to
>= Greater than or equal to
Logical Operators
In C, three types of logical operators are available (see Table 2.5).
Table 2.5: Showing Logical Operators
Symbol Meaning
&& Logical AND
|| Logical OR
!= Logical NOT
Bitwise Operator
Bitwise operators perform operations on the bit level. Please remember that
you can use these operators with integer expressions only but not on
floats or doubles. Also remember that with the help of these operators
you can access and manipulate individual bits also. The bitwise operators
are shown in Table 2.6.
Programming Using C • 55
Let us now see how the bitwise AND Operator (&) works.
For example, say one number is 12 and the other is 24. We know that an
integer takes 2 bytes or 16 bits in memory, but for simplicity’s sake, we will just
take 8 bits and do the bitwise ANDing of these two numbers as follows:
That is, numb1 = 12 = 00001100
numb2 = 24 = 00011000
Now the expression numb1 & numb2 is interpreted as
00001100
& 00011000
00001000
56 • C Programming
Note here that the result is in binary form only. Its equivalent decimal num-
ber is 8. Thus, the expression, numb1 & numb2 will return a decimal value of
8. Please note here that the operation is being performed on individual
bits and this operator of ANDing bits is completely independent of each
other. Also note that this bitwise AND operator is used in general to
check whether a particular bit of an operand is ON or OFF. For example,
say the bit pattern is 10010100 and you want to check whether a particular bit
of an operand is ON or OFF (i.e., 0 or 1). To do so we will create a mask (i.e.,
we will keep the fourth bit of this mask as 1 and all others 0s) and then bitwise
AND the two as follows:
10010100 (the given number)
00010000 (the 8-bit mask)
00010000 (result)
This means the result is 0001000 after ANDing and that is 16 in decimal.
This further implies that the fourth bit is ON.
Inside your system the bit pattern is numbered from 0 to 7 but from
NOTE right to left rather than from left to right.
A B A|B
0 0 0
0 1 1
1 0 1
1 1 1
Please note here that the OR operation returns 1 when any of the
two bits or both bits are 1. For example, for the above two numbers (12 and
24) numb1 | numb2 yields:
10010100 (the given first number)
00011000 (the second number)
00011100 (result)
Programming Using C • 57
This means the result is 0001110 after ORing, which is 28 in decimal. Thus,
the expression numb1 | numb2 returns a decimal value of 28.
Also note that the bitwise OR operator is generally used to set a
particular bit in a number ON. Thus, if you want to set the fifth bit
of a number ON then you will OR this number with the bit pattern
00100000.
Bitwise exclusive OR (XOR) Operator (^)
The Bitwise XOR operator is used to perform an exclusive OR operation
between two bit patterns. Please note that the XOR operator returns 1
only if one of the two bits is 1. Table 2.9 shows its truth table.
Table 2.9 Bitwise XOR Operator.
A B A^B
0 0 0
0 1 1
1 0 1
1 1 0
Also note that the XOR operator is used to toggle a bit ON or OFF.
For example,
If numb1 = 12
and numb2 = 24
then (numb1 ^ numb2) yields
00001100
`00011000
00001000 (result)
This yields 20 (decimal).
A ~A
0 1
1 0
Comma Operator
The comma operator (, ) allows two different expressions to appear in one state-
ment. Each comma-separated expression is evaluated and the value returned
from the group is the value of the rightmost expression.
For example,
#include<stdio.h>
void main( )
{
int x, y, z;
x=y=20;
Programming Using C • 59
Ternary Operator
C also provides a ternary operator that takes three operands (hence its name).
Its syntax is:
expression1 ? expression2 : expression3;
That is, if expression1 is true, then expression2 is evaluated; else, expression3 is
evaluated. The ternary operators are also called conditional operators.
For example,
#include<stdio.h>
void main( )
{
int u, v, w;
u = 20;
v= 30;
w = (u > v ? u : v);
printf(“\n Greatest out of the two is %d”, w);
}
OUTPUT (after running):
Greater out of the two is 30
Precedence and Associativity
The priority in which operations are performed in an expression is
called precedence and the order of evaluation, when they have equal pri-
ority, is called associativity. Table 2.11 shows precedence and associativity in C.
Table 2.11: Precedence and Associativity in C
|| Left to right
?: Left to right
= *= /= %= += –= <= &= Right to left
|= ^=
, Lowest Left to right
From the table, it is crystal clear that the comma operator has the lowest
priority and the function expression operator has the highest priority. Please
note that the operations that have equal precedence are evaluated ac-
cording to the associativity given in Table 2.11.
For example, consider the following statement:
total = x * y/z;
The evaluation computes the value of x * y and then divides z into that
value and assigns the resultant value to the variable ‘total’. Also note that
to override this associativity, put parentheses around the expression
as follows:
total = x * (y/z);
This expression now computes (y/z) first, multiplies x by that value, and
assigns the resultant value to ‘total’ (the variable). Sometimes we do not
need the default precedence to produce the desired result. For ex-
ample,
total = x + y * z;
Here, since the multiplication operator has a higher precedence over ad-
dition, the expression calculates y*z first and then adds this value to x. On the
other hand, if you wish to compute x+y first and then multiply that result by z,
use parentheses as follows:
total = (x + y) * z;
The rule can be stated as follows: “Parentheses are required
whenever you want to override associativity as the default prece-
dence. But within a pair of parentheses, the same hierarchy (as in
Table 2.11) is operative. Also, if you have a nested set of parentheses,
the operation within the innermost parentheses will be performed
first, followed by the operation within the next innermost pair of pa-
rentheses, and so on.”
62 • C Programming
C supports different data types like int, float, long, double, and so on. Each
of these has a different range of values because of their size and their signed/
unsigned properties. In practice, an expression can have an operation between
two different data types (one can be an integer and another can be a float or
vice versa). To handle such situations, C provides certain rules of type conver-
sion in these cases. Please understand that when a compiler encounters
different types of operands in the same expression, the smaller type
variable is promoted to a larger type variable. The order of inbuilt data
types is shown in Table 2.12.
Table 2.12: Inbuilt Data Types
Yes
Is
it raining?
Take your
No umbrella
Even though an if statement usually spans more than one line, it is really
one long statement. For example, the following if statements are identical ex-
cept for the style in which they are written:
if (salary > 100000)
printf(“\n It is a good salary”);
if (salary > 1000000) printf(“\n It is a good salary”);
Also note that in both of these examples, the compiler considers the
if statement and the conditionally executed statement as one unit, with
a semicolon properly placed at the end. Indentions and spacing are for hu-
man readers of a program, not the compiler.
Rules for Using if Statements
Rule 1: The conditionally executed statement should appear on the
line after the if statement.
Rule 2: The conditionally executed statement should be indented
one level from the if statement.
Recall that in most editors, when you press the tab key, you are indenting by
one level. By indenting the conditionally executed statement, you are causing it
to stand out visually. This is so you can tell at a glance what part of the program
the if statement executes. This is the standard way of writing if statements.
NOTE
1. Don’t put semicolons after the if(testcondition) portion, because
the if statement is incomplete without its conditional part. But if you
place a semicolon here, the compiler assumes that you have terminat-
ed the statement. No error will be displayed but the compiler will as-
sume that you are placing a null statement there. Also note that the
null statement (an empty statement that does nothing) will become the
conditionally executed statement. The statement that you intended to
be conditionally executed will be disconnected from the if statement
and will always execute. For example,
int u=5, v=10;
if ( u>v);
System.out.println(“u is greater than v” + u);
Programming Using C • 65
is associated with the respective if. To avoid this confusion, it is better to use
braces appropriately for the association of each else part with its if. By using
the braces, any else part may be associated with a particular if construct.
Let us now see the if-else-if control construct.
The else-if control construct follows the if control construct to allow
multiple decision making.
Syntax
if (boolExpr1)
{
Stml1;
}
else
if (boolExpr2)
{
Stml2;
}
else
if (boolExpr3)
{
Stml3;
}
………….
else if (boolExprN-1)
{
StmlN-1;
}
else {
StmlN;
}
Herein, if any boolExpr returns a true value, the Stmt associated with
that if is executed and then the next statement to the whole else-if construct is
executed. If no expression returns a true value, the last else part is executed. If
there is no instruction needed for the last else part, then it can be omitted or it
can be used for displaying the error messages due to invalid conditions.
We are in a position to write simple programs now.
Example 1: Write a C program to read a number from the keyboard
and to check whether it is a positive number.
Programming Using C • 67
plex code into a separate method and simply call that method from the
case statement.
The following points may be made regarding switch statements:
12. The expression is evaluated first and its value is then matched against
the case labels that must be constant values. When a match is found,
the statement following that case will be executed. If there is no match
with any of the case labels, the statement following the default (if
present) will be executed.
13. Different case statements in a switch-case statement may be arranged
in any order.
14. The CaseExpressions of each case statement must be unique.
scanf(“%c”, ch);
switch (ch)
{
case ‘a’:
printf(“You entered a.”);
break;
case ‘e’:
printf(“You entered e.”);
break;
case ‘i’:
printf(“You entered i.”);
break;
case ‘o’:
printf(“You entered o.”);
break;
case ‘u’:
printf(“You entered u.”);
break;
default:
printf(“You have not entered any vowel.”);
}
}
OUTPUT (after running):
Enter any vowel: i
You entered i.
Enter any vowel: u
You entered u.
Enter any vowel: r
You have not entered any vowel.
//vowel program using switch with character constants and integer (in case),
both.
#include<stdio.h>
void main( )
{
char ch;
printf(“\n Enter any vowel:”);
scanf(“%c”, ch);
switch (ch)
72 • C Programming
{
case ‘a’:
printf(“You entered a.”);
break;
case ‘101’:
printf(“You entered e.”);
break;
case ‘i’:
printf(“You entered i.”);
break;
case ‘111’:
printf(“You entered o.”);
break;
case ‘u’:
printf(“You entered u.”);
break;
default:
printf(“You have not entered any vowel.”);
}
}
OUTPUT (after running):
Enter any vowel: i
You entered i.
Enter any vowel: u
You entered u.
Enter any vowel: r
You have not entered any vowel.
The output is therefore the same in both cases. Switches allow executing
a set of statements for more than one case label. We have seen that whenever
a switch statement finds a match, it executes all of the subsequent lines in the
switch unless it encounters a break statement. Also note here that if you don’t
use a default case and the switch statement does not find a match, then
nothing gets executed within the switch statement and control is trans-
ferred to the next statement, if any, following the control structure.
a false value. The boolExpr is an expression that yields a Boolean literal. The
syntax of a while loop is shown next, followed by its working (in Figure 2.2).
Syntax
while (boolExpr)
{
Stmt;
}
Working of the while Loop
Entry
false
boolExpr
true
Stml
Exit
This is an infinite loop. Here, the Boolean literal true is used in place of a
boolExpr. It may also be written as follows to form an infinite loop:
while (! false) {
Stmt;
}
Thus, if a loop does not have a way of stopping, it is called an infinite loop.
An infinite loop continues to repeat until the program is interrupted.
For example,
int numb =1;
while (numb <=5)
{
printf(“Hello”);
}
This is an infinite loop because it does not contain a statement that changes
the value of the numb variable. Each time the Boolean expression is tested,
numb will contain the value 1.
Now, say, by mistake the programmer has put a semicolon at the end of the
while loop as follows:
while(numb <=5);
Please note here that the semicolon at the end of the first line is as-
sumed to be a null statement and disconnects the while statement from
the block that comes after it. This while loop will forever execute the null
statement, which does nothing.
Now, say, you forget to put the braces after the while header as follows:
int numb =1;
while(numb <=5)
printf(“Hello”);
numb++;
Here, the numb++ statement is not in the body of the loop. Because the
braces are missing, the while statement only executes the statement that im-
mediately follows it. This loop will also execute infinitely because there is
no code in its body that changes the numb variable.
The rules that you must follow can be stated as follows:
Rule 1: If there is only one statement repeated by the loop, it should
appear on the line after the while statement and be indented one ad-
ditional level.
76 • C Programming
Rule 2: If the loop repeats a block, each line inside the braces should
be indented.
There is no semicolon at the end of the loop header. Also note that this
while loop works just like an if statement that executes over and over again as
long as the expression in the parentheses is true. Each repetition of a loop is
known as an iteration. But the important feature of this loop is that it
will never iterate if the Boolean expression is false to start with.
subtract n from m.
end
final n is the GCD.
Method 3:
Yet another algorithm may be followed:
1. Read 2 numbers a, b.
2. Repeat through step 5 while a is not equal to 0.
3. Set gcd =a
4. a = b % a
5. b = gcd
6. Print gcd
7. Exit
[Hint: Method 1:
void main( )
{
int n1, n2;
printf(“\n\t Enter two numbers:”);
scanf(“%d %d”, n1, n2);
int greaterNumber = n2;
int gcd =1;
/* assign the greater value to the greaterNumber
variable */
if (n1 > n2)
greaterNumber = n1;
/* start finding GCD from the minimum gcd: 2 */
int index =2;
/* keep checking unless the index is larger than
the greater value and */
/*greater value is larger than 2 */
while (index <= greaterNumber && greaterNumber
> 2)
{
if ((n1 % index ==0) && (n2 % index ==0)) {
gcd = index;
Programming Using C • 79
}
/* check the next value */
index++
}
/*print the GCD */
printf(“\nGreatest Common Divisor (GCD) is %d”,
gcd);
}
}
OUTPUT (after running):
Enter two numbers
6
9
Greatest common divisor (GCD) = 3
Method 2
int gcd(int m1, int n1) {
int m = m1;
int n = n1;
int temp;
while (m >0) {
if(n > m) {temp =n; n=m; m=temp; }
m = m – n }
return n; }
void main( ) {
cout<< gcd(24,18); }
}
OUTPUT: 6
Method 3
void main( )
{
int a ,b, gcd;
a =b=gcd=0;
printf(“\n\t Enter two numbers:”);
scanf(“%d %d, &a, &b);
while(a!=0)
{
gcd =a;
a= b% a;
80 • C Programming
b=gcd;
}
printf(“GCD = %d”,gcd);
}
} ].
Q5. Enter a number from the keyboard and find out the Fibonacci series using
a while loop.
[Hint: void main( )
{
int a=0, b=1, c=0, size;
printf(“\n\t Enter a range”);
size = s;
printf(“\n”);
printf(“Enter a and b:”);
while(c <= size)
{
c = a +b;
if(c<=size)
printf(“%d\n”, c);
a=b;
b=c;
}
}
}
OUTPUT (after running):
Enter a range
50
0
1
2
3
5
8
13
21
34 ].
Programming Using C • 81
Q6. Write a C program to read a number from the keyboard and find its factorial.
[Hint: void main( )
{
int fact=1, b, c;
printf(“Enter a number:”);
scanf(“%d”, &b);
c = b;
while(c >0)
{
fact = fact * c;
c--;
}
printf(“\n Factorial of b
is:”,fact);
}
}
OUTPUT (after running):
Enter a number: 3
The Factorial of 3 is 6.
Q7. Write a C program to check whether a given number is a palindrome.
[Hint: The algorithm is given first:
1. Initialize s=0
2. Read number, num
3. Set b=num
4. Repeat through step 7 until (num > 0)
5. r=num % 10
6. s=(s*10) + r
7. num = num/10
8. If b is equal to s, then print “b is a palindrome” else print “b is not a
palindrome”
9. Exit
/* palindrome program */
82 • C Programming
void main( )
{
int num, b, s=0, r;
printf (“\n\t Enter a number:”);
scanf (“%d”, &num);
b=num;
while (num > 0)
{
r = num % 10;
s= (s * 10) + r;
num = num/10;
}
if (b = =s)
printf(“b is a palindrome”);
else
printf(“b is not a palindrome”);
}
}
OUTPUT (after running):
Enter a number
121
121 is a palindrome.
Run2:
Enter a number
123
123 is not a palindrome
Q8. Write an algorithm and the resulting C program to check whether a given
number is an Armstrong number.
[Hint: The algorithm is as follows:
1. Initialize s=0
2. Read number, num
3. Set b = num
4. Repeat through step 7 while num is greater than 0
5. r=num%10
Programming Using C • 83
6. s=s+(r*r*r)
7. num=num/10
8. If b is equal to s, then print “it is an Armstrong number” else print “it is
not an Armstrong number”
9. Exit
The resulting program is as follows:
void main( )
{
int num, b, s=0, r;
printf( “Enter a number:”);
cin >> num;
b = num;
while (num > 0)
{
r = num % 10;
s=s+ (r *r*r);
num = num/10;
}
if ( b = =s)
printf(“b is an Armstrong number”);
else
printf(“b is not an Armstrong number”);
}
}
OUTPUT (after running):
Enter a number: 153
153 is an Armstrong number
Run2:
Enter a number: 15
15 is not an Armstrong number
Q9. Write a C program to check whether a given number is binary.
[Hint:
void main( )
{
int r=0,c=0, num, b;
84 • C Programming
printf(“Enter a number:”);
scanf(“%d”, &num);
b = num;
while(num > 0)
{
if((num % 10 ==0) ||
(num%10==1))
c++;
r++;
num=num/10;
}
if(c= =r)
printf( “b is a binary num-
ber.”;
else
cout << b <<”is not a binary
number.”);
}
}
OUTPUT (after running):
Enter a number:
12345
12345 is not a binary number.
Enter a number:
11001011
11001011 is a binary number.
The do-while Loop
The general syntax of a do-while loop is as follows:
do
{
statement(s);
} while (test-condition);
The do-while statement evaluates the test condition at the end of the loop.
This loop guarantees that the loop will be executed at least once. Whereas a
loop is called a pretest loop or entry-controlled loop, a do-while loop is
known as a posttest loop or exit-controlled loop. A loop that uses another
loop is called a nested loop. Any type of loop may be used inside another
loop. The rules for nested loops are as follows:
Programming Using C • 85
Rule 1: An inner loop goes through all of its iterations for each it-
eration of an outer loop.
Rule 2: Inner loops complete their iterations before outer loops do.
Rule 3: To get the total number of iterations of a nested loop, mul-
tiply the number of iterations of all the loops.
Working of the do-while Loop
The do-while loop is similar to the while loop only but here the condition is
evaluated after the statement is executed once. Its flowchart is as follows:
Entry
Stml
true
boolExpr
false
Exit
1. Initialize a=1.
2. Initialize b=1.
3. Print a*b.
4. Increment b by 1 (i.e., b = b+1).
5. Repeat steps 3 to 5 until (b <=3).
6. Increment a by 1 (i.e., a=a+1).
7. Repeat steps 2 to 7 until (a<=3).
8. Exit.
The C program is as follows:
void main ( )
{
int a, b;
a=1;
do
{
b=1;
do
{
printf(“\n Value of a and b is %d”,
(a *b));
b++;
} (while(b<=3);
a++;
}while(a<=3);
}
}
Programming Using C • 87
statement(s);
}
Working of the for Loop
The working of the for loop is as follows:
statement(s);
}
That is, first, expr1 is evaluated. Then the condition is checked. If it is true,
then the loop enters into the body (after the { brace) and executes the state-
ments within it. After one iteration is over, control goes back to expr2 and then
again the boolExpr condition is checked. This is the process by which a for
loop works. Also note here that any one, two, or all of the three expres-
sions can be omitted in a for loop but the two semicolons (;) must be
placed separating the expressions. Also, expr1 and expr2 can be lists of
expressions separated by a comma. Thus, expr1 or expr2 may become
compound statements also.
Remember the following points regarding for loops:
expr1;
while (boolExpr) {
statements;
expr2
}
Similarly, a for loop may be implemented by using a do-while loop also:
expr1;
do {
statements;
expr2
}
while (boolExpr);
2. Any valid value can be initialized to expr1 that will act as the counter.
3. The minimum number of times a for loop is executed is zero.
4. It is also possible to declare the counter variable in a for loop itself—for
example,
for ( int count=1; count< 10; count++) {…}
5. We can also nest any of the three loops discussed so far into one another.
Such loops are called nested loops. Note that loops should not
overlap each other. Also note that one type of loop construct
can be nested in another type of loop construct. For instance, a
for loop may be nested within a while loop or do-while loop and
vice versa. This depends on the program statement that you are
solving.
6. We can also control the operation of a loop with break and continue
statements, with and without labels. The break statement
immediately terminates the loop code block whereas the
continue statement skips any remaining code in the block and
continues with the next loop iteration.
7. A variable/iterator/counter variable that is declared in a for
statement can be referred to only inside the loop.
8. The following is the bare minimum for a loop (with missing parts):
for (;;){ }
10. The first line of the for loop is also known as a loop header.
11. Note that there is no semicolon after expr3.
12. A for loop is also a pretest loop as it checks for the condition
before it performs an iteration.
13. It is also possible to execute more than one statement in the initialization
expression and the expr3 (increment/decrement). Just remember
that when you use multiple statements in any of the parts of the
for loop header, simply separate the statements with commas.
For instance,
for ( int i=1, j=2; i<10; i--) {…}
15. A new feature of the for loop is that it is also able to iterate through col-
lections without the explicit use of iterators. Iterators are the pro-
gramming patterns used to provide simple sequential access to
a collection of objects without knowing a priori the type and the
size of the specific collection accessed (to be discussed later).
Rules Followed While Writing Triangle-Like Programs:
I. Normal Photo
That is, when the triangle looks like the following:
Programming Using C • 91
Rule: “In these cases, when photo will be normal, then both the loops, i
and j, will run straight/normal, starting from 1 or otherwise both loops,
i and j, will run in reverse. This is the rule.
f3 = f1 + f2;
f1 = f2;
f2 = f3;
printf(“\t%d”, f3);
}
}
}
}
OUTPUTS (after running):
0 1 1 2 3 5 8 13 21 3
4 55 89 144
Dry run:
c = i / 100;
n = a * a * a + b * b * b + c*c*c;
if (i= =n)
printf(“%d”, i);
}
}
}
OUTPUT (after running):
153 370 371 407
Q3. Write a C++ program to compute the factorial of an integer.
[Hint:
void main( ) {
int n;
printf(“Enter your number:”);
scanf(“%d”, &n);
long f =1;
for (int i =1; i<=n; i++)
f *= i;
cout <<“Factorial is” << f);
}
}
OUTPUT (after running):
Enter your number:
4
Factorial is 24
Q4. An important series in mathematics is the sine series. Write a C program
to find the value of sin(x) from the following series:
Sin(x) = x –x3 / 3! + x5 / 5! –x7 / 7! + …
[Hint:
void main( ) {
int deg, n;
printf(“Enter the number of terms: “);
scanf(“%d”, &n);
printf(“Enter the angle in degrees:”);
scanf(“%d”, °);
float x, s = 0.0f, t;
Programming Using C • 95
}
if (count = =n)
break;
}
}
}
OUTPUTS (after running):
Enter your n:
4
6 28 496 8128
Q6. If a loop has a counter-variable, would it be normally written as a while
statement or a for statement? In a for loop, which of the initialization, test,
and update parts are optional? Which of the initialization, test, and update
parts allow the use of commas? Give examples(s) to explain this.
Q7. Write a C program to draw the following triangle:
*
* *
* * *
* * * *
* * * * *
* * * * * *
[Hint: Rule: For any triangle problem, loop j will run either j <= i
or j >= i.
Let us write its algorithm first:
7. j=j+1
8. Move to new line.
9. i=i+1
10. Stop and exit.
The program is as follows:
void main( )
{
int row, i, j;
printf(“Enter the number of rows:”);
scanf(“%d”, &row);
printf(“\n”);
for (i=0; i<row; i++)
{
for (j=0; j<=i; j++)
{
printf(“ * “);
}
printf( “\n”);
}
}
}
OUTPUT (after running):
Enter the number of rows:
6
*
* *
* * *
* * * *
* * * * *
* * * * * *
Q8. Write a C program to draw the following triangle:
1
01
98 • C Programming
101
0101
10101
010101
1010101
[Hint: Let us write its algorithm first:
}
printf(“\n”);
}
}
}
OUTPUT (after running):
Enter the number of rows
7
* * * * * * *
* * * * * *
* * * * *
* * * *
* * *
* *
* ].
Q10. Write a C program to print the following triangle:
1
12
123
1234
12345
123456
1234567
[Hint:
Let us develop its algorithm first:
}
printf(“\n”);
}
}
}
OUTPUT (after running):
Enter the number of rows
7
7777777
666666
55555
4444
333
22
1
Q12. Write an algorithm and a C program to print the following pattern:
*
***
*****
*******
*********
***********
[Hint: Let us develop its algorithm first:
7. j=j+1
8. Initialize j=1.
9. Repeat through step 11 until j is less than or equal to i.
10. Print “*”.
11. j=j+1
12. Initialize j=1.
13. Repeat through step 15 until j is less than i.
14. Print “*”.
15. j=j+1
16. Move to new line.
17. i=i+1
18. Stop and exit.
The program is as follows:
void main( )
{
int row, i, j;
printf(“Enter the number of rows:”);
scanf(“%d”, &row);
for(i=0; i<=row; i++)
{
for(j=1; j<=row-i; j++)
printf(“ “);
for(j=1; j<=i; j++)
printf(“*”);
for(j=1; j<=i; j++)
printf(“*”);
printf(“\n”);
}
}
}
OUTPUT (after running):
Enter the number of rows
6
Programming Using C • 105
*
***
*****
*******
*********
***********
Q13. Write a C program to draw a Pascal Triangle as follows:
1
1 1
1 2 1
1 3 3 1
1 4 6 4 1
[Hint: Let us develop its algorithm first:
15. q=q+1
16. Stop and exit.
The program is as follows:
void main( )
{
int a=1,p,q=0,row, b;
printf(“Enter the number of rows:”);
scanf(“%d”, &row);
printf(“\n Pascal Triangle\n”);
while (q<row)
{
for (p=30-3*q; p>0;p--)
printf(“ “);
for (b=0;b<=q;b++)
{
if (b==0 || q==0)
a=1;
else
a=(a*(q-b+1)/b;
printf (“ “ ,a);
}
printf(“\n”);
q++;
}
}
}
OUTPUT (after running):
Enter the number of rows
5
1
1 1
1 2 1
1 3 3 1
1 4 6 4 1 ].
Q14. Write a C program to display the Floyd triangle.
[Hint: Let us write its algorithm first:
Programming Using C • 107
1. Initialize a=1.
2. Read the number of rows, row.
3. Initialize i=0.
4. Repeat through step 12 until i is less than row.
5. Initialize j=0.
6. Repeat through step 10 until j is less than or equal to i.
7. Print a.
8. If a is less than 10, print “ ” else print “ ”.
9. a=a+1
10. j=j+1
11. Move to the next line.
12. i=i+1
13. Stop and exit.
The program is as follows:
void main( )
{
int a=1,i, j, row;
printf(“Enter the number of rows:”);
scanf(“%d”, & row);
printf(“\n”);
for(i=0;i<row;i++)
{
for(j=0;j<=i;j++)
{
if(a<10)
printf(“%d\t”, a);
else
printf(“%d\t”, a);
a++;
}
printf(“\n”);
}
}
}
108 • C Programming
Other Statements of C
The break Statement
When a break statement is executed inside a loop, it skips the remaining state-
ments of that loop and control is immediately transferred outside the loop.
Syntax
break;
For example,
void main( )
{
int i, j;
for(i=1; i<=3;i++)
{
for(j=1;j<=3;j++)
{
if(i= =j)
break;
else
printf(“%d\t %d”, i, j);
}
}
}
}
OUTPUT (after running):
2 1
3 1
3 2
Please note that when a break statement appears inside a loop or in
a switch statement, it terminates execution at that point and transfers
execution control to the statement immediately following the loop or
switch statement. Thus, it does an early exit from any loop or switch state-
ment. Also note that when multiple statements are nested within each
other, a break transfers control to the immediate outer level.
However, break statements should be avoided in loops (whenever
possible) because they bypass the loop’s logic and make the code dif-
ficult to understand and debug.
110 • C Programming
1. The while loop: As we have seen, a while loop is a pretest loop. This
loop is ideal when you do not want the loop to iterate if the con-
dition is false from the beginning. It is also ideal if you want to use
a sentinel value to terminate the loop. A sentinel value is a special
value that cannot be mistaken as a member of the list and signals
that there are no more values to be entered. When the user en-
ters the sentinel value, the loop terminates.
2. The do-while loop: As we have seen, a do-while loop is a sort of posttest
loop. This loop is ideal for situations where you always want the
loop to iterate at least once.
3. The for loop: As we have seen, the for loop is a pretest loop that has inbuilt
expressions for initializing, testing, and updating. These expressions make
it very convenient to use a loop control variable as a counter. The for loop
is ideal in situations where the exact number of iterations is known.
For methods having a void return type, this statement can be omit-
NOTE ted and will be implicitly added by the compiler.
Block Statements
A group of statements enclosed within curly braces comprises a block.
Thus, a block contains a statement list—a sequence of statements. A state-
ment in a block is called an embedded statement and it can be a label,
a declaration, or a simple statement. Please note that a block is also
called a compound statement. It is valid to have no statements or an empty
statement in a block. A block is syntactically similar to a single statement. Also
note that no semicolon is placed after the closing brace that ends a
block. When there is no statement in a block, it is called an empty block. A
block having an empty statement is not an empty block since it contains
a valid statement. That is,
{ } //is empty block
{ ; } //non-empty block
Empty statement: A statement that does nothing is known as an
empty statement. It is written as a single semicolon as follows:
; //empty statement
Remember that an empty statement is also known as a null state-
ment. This statement helps a programmer introduce some delays in program
execution. Actually, they do nothing and just bypass certain machine cycles,
thereby producing delays. For example,
for( int i=0; i<100; i++)
{
; // null statement
}
Similarly, we can use it in while and do-while loops as well.
We are in a position to solve some examples now.
Q1. Define sentinel value and explain why it is used?
Q2. Write a C program to read numbers 1 to 10 through the keyboard and
display their squares in a tabular format.
[Hint: void main( ) {
{
int number, maxValue; // number is loop
control variable
Programming Using C • 113
4 plus 4 equals 8
5 plus 5 equals 10 ].
Q4. Give an example to show the use of a sentinel value.
[Hint:
while (result != -1)
{
result = result + 20;
}
Here, the value –1 was chosen for the sentinel because it is not possible to
have a negative result. Thus, this makes it possible for the loop to terminate im-
mediately if the user gets –1 as the result].
Q5. Write a C program that reads the number of students and the number of
test scores per student and then displays the average score for a student.
[Hint:
void main( )
{
int n, /* number of students */
numTests, /* number of tests per
student*/
score, /* test score */
total; /* test scores in total
*/
double average; /*average test score */
printf(“TEST AVERAGING PROGRAM”);
/* read number of students */
printf(“Enter number of students:”);
scanf(“%d”, &n);
/* get number of test scores per student */
printf(“How many test scores per stu-
dent?”);
scanf(“%d”, &numTests);
/* Calculate for each student */
int student =1; student <=numStudents;
student++)
{
total = 0; /*set total to 0 */
Programming Using C • 115
printf(“Enter a number:”);
scanf(“%d”, &x);
}
(b) Convert for loop to a while loop in the code below:
for( int i = 10 ; i > 0; i--)
{
printf( “%d seconds to go”, i);
}
(c) Write an input validation loop that asks a user to enter a num-
ber in the range of 1 through 100.
(d) Write a C++ program that displays a table of centigrade tem-
peratures 0 to 50 and their Fahrenheit equivalents. The for-
mula used is:
C = 5/9 (F–32)
where C and F have their usual meanings. Try to
use a loop to display your table.
Q9. Develop a program to find the roots of a given quadratic equation. Use
switch statements and loops to display your roots.
[Hint: Refer to page 267].
Q10. The distance a body travels in free fall is given by the formula:
S= –gt2
where s is the distance traveled in feet,
T is the time in seconds to travel the distance s,
G is a constant and is equal to 32.2 feet per second2.
Write a C program for this equation.
Q11. Write a C program to read a number from the keyboard and to add each
of its digits.
[Hint:
void main( )
{
int r, sum=0, num;
printf(“Enter a number:”);
scanf(“%d”, &num);
while(num > 0)
Programming Using C • 117
{
r = num % 10;
sum = sum + r;
num = num /10;
}
printf(“The sum of digits is= %d”, sum);
}
}
OUTPUT (after running):
Enter a number
123
The sum of digits is = 6 ].
Q12. Give and discuss the output of the following code:
int price;
for (int width =11; width <=20; width++) {
for(int length =5; length <=25; length +=5) {
price = width * length * 19;
printf(“ \t%d “, price);
}
//finished one row; now move on to the next row
printf(“ “);
}
[Hint: The outer for statement is set to range from the first row (width=11)
to the last row (width=20). For each repetition of the outer for, the inner
for statement is executed, which ranges from the first column (length=5)
to the fifth column (length=25). The loop body of the inner for computes
the price of a single item and prints out this price. So, the complete ex-
ecution of the inner for loop, which causes its loop body to be executed 5
times, completes the output of one row. The following shows the sequence
of values for the 2 control variables:
width length
11
5
10
15
20
118 • C Programming
Variables in C have a data type. But they also have a storage class that provides
information about their location and visibility. The storage class divides the por-
tion of the program within which the variables are recognized. The following
are the storage classes:
I. Auto
The auto storage class is a local variable known only to the function in
which it is declared.
Auto is the default storage class. The auto keyword places the specified
variable into the stack area of memory. This is usually implicit in most variable
declarations like int i;
The default storage class for all local variables is auto.
For example,
int counter;
auto int i;
Both the variables are here defined with the same storage class; auto can
only be used within functions (i.e., local variables).
II. Static
The static storage class is a local variable which exists and retains its
value even after control is transferred to the calling function.
A static variable is the one that does not get initialized again and again.
The static keyword is useful for extending the lifetime of a particular variable.
Please note that if you declare a static variable inside a function, the
variable remains even after the function call is long gone (the variable is
placed in the alterable area of memory). Also note that the static keyword
is overloaded. It is also used to declare variables to be private to a certain file
only when declared with global variables. Static variables can also be used with
functions, making those functions visible only to the file itself. Static is the
default storage class for global variables.
For example,
static int count;
120 • C Programming
Static variables can be seen within all functions in this source file. At link
time, the static variables defined here will not be seen by the object modules
that are brought in. Note that static can also be defined within a function. If
this is done the variable is initialized at runtime but is not reinitialized when the
function is called. This inside a function static variable retains its value during
various calls.
For example,
void func(void)
static count=10; /* global variable- static is the
default */
main( )
{
while (count - - )
{
func( );
}
}
void func(void)
{
static i = 5;
i++;
printf(“i is %d and count is %d\n”, i, count);
}
OUTPUT (after running):
i is 6 and count is 9
i is 7 and count is 8
i is 8 and count is 7
i is 9 and count is 6
i is 10 and count is 5
i is 11 and count is 4
i is 12 and count is 3
i is 13 and count is 2
i is 14 and count is 1
i is 15 and count is 0
Programming Using C • 121
Here, the keyword void means function does not return anything and
NOTE it does not take any parameter. Static variables are initialized to 0
automatically.
III. Extern
We know that global variables are known to all functions in the file. The extern
keyword makes the specified variable access the variable of the same name
from some other file. This is very useful for sharing variables in modular pro-
grams; extern is used to give a reference of a global variable that is visible to
all program files. When you use extern the variable cannot be initialized as all
it does is point the variable name at a storage location that has been previously
defined. Please note that when you have multiple files and you define a
global variable or function, which will be used in other files also, then
extern will be used in another file to give reference of the defined vari-
able or function. Also note that extern is used to declare a global vari-
able or function in another file.
For example,
File 1: main.c
int count = 10;
main( )
{
write_extern( );
}
File 2: write.c
void write_extern(void)
extern int count;
void write_extern(void)
{
printf(“count is %i\n”, count);
}
Here, the extern keyword is being used to declare a count in another file.
Now compile these two files as follows:
gcc main.c write.c –o write
This creates a write file that can be used to produce a result by executing it.
The count in main.c will have a value of 15. If main.c changes the value of the
count, write.c will see the new value.
122 • C Programming
IV. Register
The keyword register refers to the social variables that are stored in the regis-
ter. It suggests that the compiler place the particular variable in the fast register
memory located directly on the CPU. Most compilers these days (like gcc) are
so smart that suggesting registers could actually make your programs slower.
Please note that register is used to define local variables that should
be stored in a register instead of RAM. Also note that this means that
the variable has a maximum size equal to the register size (usually one
word) and can’t have the unary ‘&’ operator as it does not have a mem-
ory location.
For example,
register int u;
The register keyword should only be used for variables that require quick
access such as counters. Also understand that defining register does not
mean that the variable will be stored in a register; rather, it means that
it might be stored in a register—depending on hardware and imple-
mentation restrictions.
Before we close this chapter, let us write some programs now.
Q1. Write a C program to convert a binary number to a decimal number.
Ans. 1: The program is as follows:
#include<stdio.h>
main( )
{
int binary, bin, digit, decimal=0, base=0;
printf(“\n\t Enter any binary number:”);
scanf(“%d”, &binary);
bin = binary;
while (binary !=0)
{
digit = binary % 10;
digit = digit << base;
decimal = decimal + digit;
base++;
binary = binary / 10;
}
printf(“\n Decimal equivalent of binary number %d = %d”,
bin, decimal);
}
Programming Using C • 123
False False
Statement
Here, if test condition-1 results in True then the if-else statement, which is
embedded in the if block, is executed and the other if-else statement, which is
embedded in the else block, is skipped. On the other hand, if test condition-1
128 • C Programming
results in False then the if-else statement, which is embedded in the if block, is
skipped and the other if-else statement, which is embedded in the else block,
is executed.
Q12. Write a C program to find the power of x raised to y (xy).
Ans. 12: The program is as follows:
#include<stdio.h>
main( )
{
int x, y, i, power =1;
printf(“\n Enter the value of a and y =”);
scanf(“%d %d”, &x, &y);
if (y = =0)
printf(“\n Power of %d to %d is = %d”, x, y, power);
else
{
while (y > = 1)
{
power = power * x;
y - - ;
}
printf(“\n Power of %d to %d is = %d”, x, y, pow-
er);
}
}
OUTPUT (after running):
Enter the value of x and y = 2 3
Power of 2 to 3 is = 8
Q13. Write a C program to generate the Fibonacci series that continues till n.
Ans. 13: The program is as follows:
#include<stdio.h>
main( )
{
int i, n, f1, f2, f3;
printf(“\n \t Enter the value of n: “);
scanf(“%d”, &n);
if (n <= 1)
printf(“%d”, n);
Programming Using C • 129
else
{
f1 = 0;
f2 = 1;
f3 = f1 + f2;
printf(“%d\t”, f3);
for (i=2; i<=n; i++)
{
f3 = f1 + f2;
f1 = f2;
f2 = f3;
printf(“%d\t”, f3);
}
}
}
Please note here that in a for statement, you can have more than
one expression in the initialization part of the statement and more than
one expression in the update part. To separate multiple initializations
and updating, we use commas to separate them. Also note that the C
language strictly allows only one test condition and no more than that
in a for statement.
Q14. Write the output of the following C code:
#include<stdio.h>
main( )
{
int x = 4;
x *= x + 4;
printf(“%d”, x);
}
Ans. 14: The output is as follows: 32
This is so because we have x = x * (x + 4) = 4 * ( 8 ) = 32.
Q15. What is a variable declaration and what is a variable definition?
Ans. 15: extern int a is a declaration whereas int a=100 is a definition.
Q16. What are different types of linkages?
Ans. 16: There are three different types of linkages: external, internal,
and none.
130 • C Programming
In shifting, bits are lost, whereas in rotation, bits are not lost (i.e.,
NOTE LSBs become MSBs and vice versa).
3 4<10 4
4 5<10 5
5 6<10 6
6 7<10 7
7 8<10 8
8 9<10 9 times.
9 10<10 (is false).
Q24. Give the output of the following program:
main( )
{
int m, n;
m = 14;
n = 15;
printf(“m & n = %d”, m & n);
}
Ans. 24: Now, m= 14 d = (1110)2
n = 15d = (1111)2
So, 1110
& 1111
1110
And 1110 = 0 * 20 + 1 * 21 + 1 * 22 + 1 * 23 = 0 + 2 + 4 + 8 = 1410
Q25. Give the output of the following program:
#include<stdio.h>
#include<conio.h>
main( )
{
int i = 7;
int res;
clrscr( );
res = i++ * i++;
cout << “Result is: “ << res;
getch( );
}
Ans. 25: 49
Programming Using C • 133
gets( ) puts( )
This function reads a string from a standard This function prints a string on the standard
input device. output device.
This function is used as an input function for This function is used as an output function for
a string. a string.
No message can be printed with this function. With this function any message can also be
printed.
Summary
In this chapter, we have examined how a C program reads and writes inputs
and outputs from a standard input device like a keyboard. We have seen that C
provides a facility for decision making by using different types of control state-
ments like the if, if-else, and switch statements. We have explored how if-else
can be nested and the switch statement as a multi-way selection statement. We
have also seen how loops are used and the functioning of different loops like the
while loop, do-while loop, and for loop. We have looked at break and continue
statements and have studied modifiers and qualifiers in C.
Exercises
Q1. What are the major data types available in C? Using a suitable example,
discuss enumerated data types.
Q2. Write short notes on bitwise operators in C.
136 • C Programming
Q3. Can we replace a for loop with a while loop? If yes, explain with an example.
Q4. Write a loop that will generate every third integer beginning with i=2 and
continuing for all integers that are less than 100. Calculate the sum of
those integers that are evenly divisible by 5.
Q5. Explain briefly all storage classes used in C.
Q6. What does the storage class of a variable mean and how would you define
the scope of a variable within a program. Also explain how an automatic
variable is defined and initialized? What happens if an automatic variable
is not explicitly initialized within a function?
Q7. Write a C program to sum the following exponential series:
ex = 1 + x + x2/2! + x3/ 3! + …..xn/n!
[Hint:
1. Read x and n.
2. Initialize t=1 and sum =1.
3. for i 1 to n do
4. prod = i.
5. t = t * x/prod.
6. sum = sum + t
7. Print sum. ].
Q8. Write a C program to find the factorial of a number using for loops.
[Hint:
fact =1.
for(i=1; i<=n; i++)
fact = fact * i.
printf fact. ].
Q9. Write a C program to compute the 100th triangular number. A triangular
number is obtained by adding the integers from 1 up to 100.
[Hint:
main( )
{
int n, triangular_number;
triangular_number = 0;
Programming Using C • 137
1. read a number.
2. right_digit = number % 10.
3. print right_digit.
4. number = number /10 ].
Q13. Write a C program to generate and display a table of n and n2 and n3
for integers ranging from 1 to n.
Q14. Write a C program to generate and print the table of the first 10 factorials.
Q15. Write a C program to show what happens when a minus is placed in
front of a field width specification.
[Hint: The field is displayed left-justified].
Q16. Write a C program to calculate the average of a set of grades and to
count the number of failing test grades.
[Hint:
main( )
{
138 • C Programming
1. Read a character c.
2. If c >= ‘a’ and c <= ‘z’ or c >= ‘A’ and c <= ‘Z’ then print ‘It is a character’.
3. Else if c >= ‘0’ and c <= ‘9’ then print ‘It is a digit’.
4. Else print ‘ It is a special character’. ].
Q20. What are the largest positive and negative numbers that can be stored?
How are they determined?
[Hint: The largest positive number that can be stored into n bits is 2n-1 – 1.
So, in 8-bits, we can store up to 27 – 1 or 127. Similarly, the smallest nega-
Programming Using C • 139
tive number that can be stored in n bits is –2n-1, which in an 8-bit comes
to –128. Please note that these two values are not the same. This is
applicable to characters, as they take 1 byte or 8 bits.
On the other hand, integers take 2 bytes or 16 bits in computer memory,
so the largest possible value that can be stored into such an integer is 215–1 or
32,767, whereas the smallest negative number that can be stored is –32,768.].
Q21. Why do unsigned integers take values from 0 to 65,535?
[Hint: We know that an unsigned modifier can be used to increase the
accuracy of a variable. This is because the leftmost bit is no longer needed
to store the sign of the number, since we are only dealing with positive in-
tegers. This extra bit is used to increase the magnitude of the value stored
in that variable by a factor of 2. Please note that n bits can now be used to
store values up to 2n–1. Also note that on a machine that stores integers
in 16 bits, this means that unsigned integers can range in value from 0
through 65,535.].
CHAPTER
3
Arrays and Pointers
3.0 INTRODUCTION
S
ay we wish to store the marks of 3000 students at our college; if I use
variables, more than 3000 variables are required. This is very tedious and
cumbersome. So to solve this type of problem, we use an array that has a
common name with a subscript representing the index of each element. Thus,
an array is an ordered sequence of finite data items of the same data
type that share a common name. The common name is the array name
and each individual data item is known as an element of the array.
An array is defined as a set of a similar type of elements that are
stored contiguously in memory. This means that the elements of an ar-
ray are stored in the subsequent memory locations starting from the
first memory location of the block of memory created for the array.
Each element of an array can be referred to by an array name and a subscript
or an index. Please note that all elements of an array should be of simi-
lar type. Arrays can have one of more dimensions—one-dimensional (1D),
two-dimensional (2D), or multidimensional. A one-dimensional array uses a
single index and a two-dimensional array uses two indexes, and so on. A
1D array can be used to represent a list of data items and is also known
as a vector or a list. Similarly, a 2D array can be used to represent a
table of data items consisting of rows and columns. It is also known as a
matrix. A 3D array can be used to represent a collection of tables. The
concept can go beyond three dimensions also.
142 • C Programming
The dimension of the array is known as its rank. For instance, a 1D array
has rank 1, a 2D array has a rank of 2, and so on. The number of subscripts
is determined by the rank of an array. The size or length of each di-
mension is represented by an integral value greater than or equal to
0. The total number of elements in an array is the product of the sizes
of each dimension in an array. If any one or more of the dimensions of
an array have size 0, the array is known as an empty array. An array may
be regular or ragged. A ragged/jagged array is a 1D array which contains
arrays as elements. A regular array is a multidimensional array where each
dimension contains the same number of elements, which is not generally true
for jagged arrays.
Note that the size of an array is not part of the array data type.
The overall classification of arrays in C is shown in Figure 3.1.
Arrays
1D arrays Multidimensional
arrays
An array must be created before using its elements in a program. There are two
steps:
Arrays and Pointers • 143
1. The square brackets follow the data type and not the array name.
2. It is also possible to have the square brackets follow the array name.
3. The above syntax declares references to the arrays of a specific data type.
4. These references are initialized with default null values.
5. Thus, memory is not allocated for an array by the declaration alone.
6. The data type of elements and the rank of the array are identified from
the declaration.
7. The size of an array representing the length of dimension is not part of
the array’s type. That is why the size of the array is not mentioned it its
declaration.
144 • C Programming
8. The declaration also does not enclose any integer value between the
opening and closing square brackets.
9. Note here that in C array indexing starts from 0 and uses integer
expressions.
10. An array having a size equal to 0 is known as an empty array.
11. Once an array is created, its size cannot be changed.
12. The subscript of the last element in an array is one less than the
total number of elements in the array.
13. In C, array initialization suffers from two drawbacks:
(a) There is no simple way to initialize only the selected elements.
(b) There is no shortcut method to initialize a large number of
elements.
Correct Method
We observed from the preceding example that we cannot copy an array by
merely assigning one array reference variable to another. Please remember
that to copy an array you need to copy the individual elements of one
array to another as follows:
int [ ] firstArray = { 1, 2, 3, 4, 5, 6, 7, 8, 9};
int [ ] secondArray [9];
for( int i=0; i < n; i++)
secondArray[i] = firstArray[i];
The loop in this code copies each element of firstArray to the correspond-
ing element of secondArray.
Before we discuss multidimensional arrays, let us summarize arrays
as follows:
4. You must differentiate between an array index and the values stored in
an array at a particular index.
5. An array may hold at most the number of elements specified by its size.
It may hold no data if the size is 0.
6. An array name followed by a subscript enclosed within the square
brackets refers to the individual elements in it.
7. The subscript can be byte, short, char, or int. it cannot be long type.
8. The elements are stored in consecutive/successive memory
locations.
9. Subscripted array variables are treated as ordinary variables.
10. Subscripted array variables use the subscript enclosed within
square brackets whereas ordinary variables do not have any
subscript.
11. By incrementing the value of the subscript by 1, the data stored in the
subsequent memory location is obtained. Please note here that this
is not true of ordinary variables.
12. Accessing an array element is similarly easy irrespective of the size
of the array. The value of the subscript gives the position of the
element in the array.
13. Arrays may be one-dimensional or multidimensional.
14. Arrays may be regular or ragged.
15. In 2D regular arrays, all rows have the same number of columns.
16. A 1D ragged array may have rows with equal or different column sizes.
17. An array instance created is always an array type.
18. When an instance of an array is created, the rank and size of each
dimension are specified and remain constant throughout the
lifetime of the instance. It is not possible to change the rank and
size of the dimensions of an existing array.
19. Sizes must be constant values.
20. An array is a reference data type.
148 • C Programming
21. The data type of elements, the shape of an array, and the number of
dimensions are part of the type of array. Thus, an array contains only
these details in its declaration.
22. Array size is not part of the array’s type. Thus, the declaration of an
array does not contain its size.
23. An array declaration does not reserve any memory.
24. An instance of the array is created dynamically using new operator.
25. It is only in array creation using new operator that the values
within square brackets mention the size. In other places, they refer to
the indices or subscripts only. The subscript must be an integral
constant.
26. The size of the array must be an integer greater than or equal
to 0. After creation of arrays, the values of the subscripted variables
assume default values if there are no initializers.
27. The array subscripts must always start at zero.
28. The last array variable’s subscript is always [size -1] (i.e., one less
than the size of the array).
29. You cannot index an array backward (like a[-1], a[-2], etc.). Also note
that it is illegal to refer to elements that are out of array bounds.
For example, for an array of size 8, the array bound is from a [0] to a
[7] only.The C compiler checks on the array bounds and report
errors, if any, at compile time.
30. While executing a program, a value of an array type can be null or a
reference to an instance of that array type.
31. Initialization of an array may be combined with instantiation by using
initializers.
32. Array elements are initialized to their default values, if they are
not explicitly initialized by using initializers, when an instance is cre-
ated.
We are in a position to solve some questions based on 1D arrays now.
Q1. Write a C program that reads 10 integer elements and displays them.
Solution 1: The program is as follows:
Arrays and Pointers • 149
#include<stdio.h>
main( )
{
int val[10];
int i;
printf(“\n\tEnter the array elements:”);
for (i =0; i<10; i++)
scanf(“%d”, &val[i]);
printf(“\n\tArray elements are: “);
for (i = 0; i <10; i++)
printf(“\n%d”, val[i]);
}
OUTPUT (after running):
Enter the array elements: 1 2 3 4 5
Array elements are:
1
2
3
4
5
Q2. Write a C program that finds the sum and average of 10 real numbers and
displays them.
Solution 2: The program is as follows:
#include<stdio.h>
main( )
{
int num [10], i, large;
float average, sum;
int i;
printf(“\n\tEnter the array elements:”);
for(i=0; i<10; i++)
scanf(“%f”, &num[i]);
sum = 0;
for(i=0;i<10;i++)
sum = sum + num[i];
average = sum / 10.0;
printf(“\n\tSum of 10 real number is=%f”, sum);
150 • C Programming
Q4. Write a C program that reads 10 integer elements, reverses them, and then
displays them.
Solution 4: The program is as follows:
#include<stdio.h>
void main( )
{
int a[10], i;
clrscr( );
printf(“\n\tEnter your 10 array elements:”);
for(i=0; i<10; i++)
scanf(“%d”, &a[i]);
printf(“\nThe list in reverse order is:”);
for(i=9; i>=0; i- -)
printf(“%d”, a[i]);
getch( );
}
OUTPUT (after running):
Enter the 10 array elements: 1 2 3 4 5 6 7 8 9 10
The list in reverse order is: 10 9 8 7 6 5 4 3 2 1
Q5. Write a C program that reads an array, finds the greatest element, and
prints this number and its position in that array.
Solution 5: The program is as follows:
#include<stdio.h>
#include<conio.h>
void main( )
{
int a[90], big, pos, i, n;
clrscr( );
printf(“\nEnter the size of the array:”);
scanf(“%d”, &n);
printf(“\nEnter the array elements:”);
for (i =0; i<n; i++)
scanf(“%d”, &a[i]);
big = a[0]; /*assume 1st element is the largest one */
pos = 0; /*set the position of big as 0 */
for (i=1; i<n; i++)
{
if (a[i] > big)
152 • C Programming
{
big = a[i];
pos = i;
}
}
pos++; /*increment pos by 1 as array is counted
from 0 */
printf(“\nLargest number =%d is stored at position
= %d”, big, pos);
getch( );
}
OUTPUT (after running):
Enter the size of the array: 5
Enter the array elements: 1 2 3 4 5
The largest number = 5 is stored at position = 5
Q6. Write a C program using an array of, say, 10 elements, to interchange its
even-position elements with odd-position elements.
Solution 6: The program is as follows:
#include<stdio.h>
#include<conio.h>
void main( )
{
int a[10], i, t;
clrscr( );
printf(“\n\tEnter a list of 5 elements:”);
for(i=0; i<5; i++)
scanf(“%d”, &a[i]);
/*Interchange eve elements with odd elements position
wise */
for(i=0; i< 5; i+=2)
{
t = a[i];
a[i] = a[i+1];
a[i+1] = t;
}
printf(“\nThe final list is:”);
for(i=0; i<5; i++)
printf(“%d\t”, a[i]);
getch( );
}
Arrays and Pointers • 153
Q8. Write a C program to search a given number from a list of n numbers and
to print its location also.
Solution 8: The program is as follows:
154 • C Programming
#include<stdio.h>
#include<conio.h>
void main( )
{
int a[80], i, s, n, loc;
clrscr( );
printf(“\nEnter number of elements in the array: “);
scanf(“%d”, &n);
printf(“\nEnter the array elements:”);
for(i=0; i<n; i++)
scanf(“%d”, & a[i]);
printf(“\nEnter the element you want to search:”);
scanf(“%d”, &s);
for(i =0; i <n; i++)
{
if (s = = a[i])
{
loc = i + 1;
printf(“\nElement %d is present at %d location”, s,
loc);
break;
}
}
if (i = =n)
printf(“\nElement %d is not present in the list”, s);
getch( );
}
OUTPUT (after running):
Enter number of elements in the array: 10
Enter the array elements: 10 20 30 40 50 60 70 80 90 100
Enter the element you want to search: 90
Element 90 is present at 9 location
Q9. Write a C program to read n values from the keyboard and compute their
mean standard deviation (SD) and variance (VAR).
[Hint: The formulas to be used are as follows:
AM = 1/n Σxi where i → 1 to n
VAR = 1/n [Σ (xi – AM)2 ]
and SD = sqrt(VAR) ].
Arrays and Pointers • 155
Multidimensional Arrays
A multidimensional array is an array having more than one dimension (2d, 3d,
etc.)
Two-Dimensional Arrays
A two-dimensional array is basically a collection of similar types of elements
which are organized in two dimensions. They are used to represent a table with
rows and columns. Real-life examples of 2d arrays include chess boards, tic-tac-
toe boards, and so on.
#include<stdio.h>
main( )
{
int a[10][10], b[10][10], c[10][10];
int i, j, row1, row2, col1, col2;
printf(“\n\tEnter the number of rows and columns of
first matrix:”);
scanf(“%d%d”, &row1, &col1);
printf(“\n\tEnter the number of rows and columns of
second matrix:”);
scanf(“%d%d”, &row2, &col2);
if ((row1 = = row2) && (col1 = = col2))
{
printf(“\nEnter the elements of first matrix (*d *
%d)”, row1, col1);
for(i=0; i<row1; i++)
{
for(j=0; j<col1; j++)
scanf(“%d”, &a[i][j]);
}
printf(“\nEnter the elements of second matrix (*d * %d)”,
row2, col2);
for(i=0; i<row2; i++)
{
for(j=0; j<col2; j++)
scanf(“%d”, &b[i][j]);
}
for(i=0; i<row1; i++)
{
for(j=0; j<col1; j++)
c[i][j] = a[i][j] + b[i][j];
}
printf(“\nAddition of two matrices is:”);
for(i=0; i<row1; i++)
{
printf(“\n”);
for(i=0; i<col1; i++)
{
printf(“%d”, c[i][j]);
}
}
}
158 • C Programming
else
{
printf(“\nDimensions of both matrices do not
match”);
printf(“Please enter same dimensions of both ma-
trices”);
}
}
OUTPUT-1 (after running):
Enter the number of rows and columns of first matrix: 3 4
Enter the number of rows and columns of second matrix: 4 4
Dimensions of both matrices do not match.
Please enter same dimensions of both matrices.
}
printf(“\nMultiplication of two matrices is: “);
for(i=0; i<row1; i++)
{
printf(\n”);
for(j=0; j<col2; j++)
{
printf(“%d\t”, c[i][j]);
}
}
}
else
{
printf(“\nColumns of first matrix and rows of second
ma trix do not match”);
printf(\nPlease re-enter correct dimensions of both
the matrices”);
}
}
OUTPUT (after running):
Enter the number of rows and columns of first matrix: 2 4
Enter the number of rows and columns of second matrix: 4 3
Enter the elements of first matrix (2 * 4):
2 4 5 6
1 6 3 8
Enter the elements of second matrix (4 * 3):
5 3 8
9 0 1
3 5 7
4 6 1
Multiplication of two matrices is:
85 67 61
100 66 43
Arrays and Pointers • 161
{
big = a[i][j];
locbi = i +1;
locbj = j + 1;
}
if (a[i][j] < small)
{
small = a[i][j];
locsi = i +1;
locsj = j + 1;
}
}
}
printf(“\nLargest element is %d”, big);
printf(“\nLargest element is stored at %d row %d
column”, locbi, locbj);
printf(“\nSmallest element is %d”, small);
printf(“\nSmallest element is stored at %d row %d
column”, losci, locsj);
getch( );
}
OUTPUT (after running):
Enter the row and column of a matrix: 3 3
Echoing …
123
456
789
Largest element is 9
Largest element is stored at 3 row and 3 column
Smallest element is 1
Smallest element is stored at 1 row and 1 column
Example 5: Write a C program to print Pascal’s triangle—that is,
1
1 1
1 2 1
164 • C Programming
1
3 3 1
1
4 6 4 1 ?
Solution 5: The program is as follows:
#include<stdio.h>
#include<conio.h>
void main( )
{
int a[10][10], i, j, n;
clrscr( );
printf(“\nHow many rows you want?”);
scanf(“%d”, &n);
for (i =1; i< = n; i++)
{
for (j=1; j <=i j++)
{
if (j = = 1 | | j = = i)
a[i][j] = 1;
else
a[i][j] = a[i-1][j] + a[i-1][j-1];
printf(“%d\t”, a[i][j]);
}
printf(“\n”);
}
getch( );
}
OUTPUTS (after running):
How many rows you want? 5
1
1 1
1 2 1
1 3 3 1
1
4
6 4 1
char array_name[size];
Here, array_name is the name of the array storing character-type data and
size is the total number of characters in array_name.
For example,
char name[80];
Here, name is an array that can hold upto 80 characters. Again, array in-
dexes start from 0. So the fifth element of name[ ] array is referred to as:
name[4];
Similarly, entire array elements can be accessed using loops.
printf(“\nEchoing…..”);
for(i=0; i<10; i++)
printf(“%c”, name[i]);
}
OUTPUT (after running):
Please enter your name: Dr. RAJIV
Echoing … Dr. RAJIV
How to Initialize a Character Array
Like an array of ints or floats or doubles, we can also initialize an
array of chars during its declaration as follows:
char name[10] = {‘D’, ‘r’, ‘.’, ‘R’, ‘A’, ‘J’, ‘I’, ‘V’ };
We can also write the following:
char name[ ] = {‘D’, ‘r’, ‘.’, ‘R’, ‘A’, ‘J’, ‘I’, ‘V’ };
Please note that during array declaration, if the subscript (array
size) is omitted, it is assumed to be the size of the data with which the
array is initialized. This means that the size declaration is optional in
array declaration. Also note that it is the duty of the user to remember
the number of characters stored in the array.
But please note here that the %s format specifier has some limitations:
1. The first limitation of using the format specifier ‘%s’ is that the program-
mer has to remember the size of the character array.
2. The second limitation is that it cannot receive multiwords strings from
the keyboard.
3. That is, in the above program, if we enter the input name string as DR.
RAJIV then it would only display Dr. When it encounters a space bar, it
will automatically terminate the string.
int len;
printf(“\nEnter any string:”);
gets(name);
len = strlen(name);
printf(“The length of a given string is %d”, len);
}
OUTPUT (after running):
Enter any string: Dr. Rajiv Chopra
The length of a given string is 16
Syntax
strcmp(str1, str2);
Here str1 and str2 are the string constants or string variables. The function
returns 0 if they are equal, returns a negative if str1 is less than str2, and re-
turns a positive if str1 is greater than str2. Remember that this comparison
is case sensitive.
For example,
#include<stdio.h>
#include<string.h>
main( )
{
char name1[80], name2[80];
printf(“\nEnter your first string:”);
gets (name1);
printf(“\nEnter your second string:”);
gets (name2);
if (strcmp(name1, name2) = = 0)
printf(“Both strings are equal”);
else
printf(“Both strings are not equal”);
}
OUTPUT (after running):
Enter your first string: DR. RAJIV
Enter your second string: DR. RAJIV
Both strings are equal
Syntax
strcat (str, str);
Here the contents of string str2 are appended to string str1.
For example,
#include<stdio.h>
#include<string.h>
main( )
{
char str1[20], str2[20], str3[20];
printf(“\nEnter your first string:”);
gets(str1);
printf(“\nEnter your second string:”);
gets(str2);
strcpy(str3, str1);
strcat(str3, str2);
printf(“Concatenated string is %s”, str3);
}
OUTPUT (after running):
Enter your string: DR. RAJIV
Enter your second string: CHOPRA
Concatenated string is: DR. RAJIV CHOPRA
#include<stdio.h>
#include<string.h>
main( )
{
char name1[80], name2[80];
printf(“\nEnter your string:”);
gets (name1);
strcpy(name2, name1);
strrev(name1);
if (strcmp(name1, name2) = = 0)
printf(“Given string is a palindrome”);
else
printf(“Given string is not a palindrome”);
}
OUTPUT (after running):
Enter your string: DR. RAJIV
Given string is not a palindrome.
Enter your string: TOOT
Given string is a palindrome
strlwr(name1);
strupr(name2);
printf(“Equivalent lowercase string is %s”, name1”);
printf(“Equivalent uppercase string is %s”, name2”);
}
OUTPUT (after running):
Enter your string: Dr. Rajiv
Equivalent lowercase string is dr. rajiv
Equivalent uppercase string is DR. RAJIV
int choice;
printf(“\nEnter any week day number:”);
scanf(“%d”, &choice);
if ((choice >=1) && (choice <=7))
printf(“\nYou have entered %s”, days[choice – 1]);
else
printf(“\nYou have entered wrong number”);
}
OUTPUT (after running):
Enter any week day number: 4
You have entered THURSDAY.
We are in a position to write some programs now.
Example 1: Write a C program to show the concept of pass by value
in C. Then rewrite that same program using the concept of call by ref-
erence.
Solution 1: Like any other arguments (data), array elements can also be
passed by value and by reference. In the pass by value method, the array ele-
ments are passed while in pass by reference addresses of the array elements are
passed. Let us write these two programs now.
/* using pass by value or call by value in C */
#include<stdio.h>
#include<conio.h>
void main( )
{
int m [ ] = {10, 20, 30, 40 50}, i;
clrscr( );
for(i =0; i< 5; i++)
show(a[i]);
getch( );
}
show (int marks)
{
printf(“\t%d”, marks);
}
OUTPUTS (after running):
10 20 30 40 50
On the other hand, in call by reference or pass by reference:
178 • C Programming
OUTPUT:
101
201
301
401
501
601
Arrays and Pointers • 181
701
801
901
1001
…
Example 5: Write a C program to evaluate a polynomial using an array.
Solution 5: The program is as follows:
#include<stdio.h>
void main( )
{
int a[40];
int x, n, i, res;
printf(“\nEnter the maximum power of x: \n\t”);
scanf(“%d”, &n); /* maximum size of array is read */
printf(“\nEnter the coefficients of the polynomial:\n”);
for(i=0; i<=n; i++)
{
printf(“\nEnter the coefficient of X^ %d = \t”, i);
scanf(“%d”, &a[i]);
}
printf(“\nEnter the value of X= \t”);
scanf(“%d”, &x);
/*calculating polynomials value */
res = a[n];
for(i = n-1; i >=0; i- - )
res = res * x + a[i];
printf(“\nValue of polynomial = %d\n”, res);
}
OUTPUTS (after running):
Enter the maximum power of x: 2
Enter the coefficients of the polynomial:
Enter coefficient of X ^ 0 = 1
Enter coefficient of X ^ 1 = 2
Enter coefficient of X ^ 2 = 3
182 • C Programming
high = mid – 1;
}
printf(“\nUnsuccessful Search”);
}
OUTPUTS (after running):
Enter the number of elements: 10
Enter 10 elements in ascending order:
1
2
3
4
5
6
7
8
9
10
Enter the key element to search: 5
Search successful.
Example 8: Write a C program to compare two strings without using
the strcmp( ) function.
Solution 8: The program is as follows:
#include<stdio.h>
#include<string.h>
void main( )
{
char a[100], b[100];
int result;
printf(“\nEnter the first string:”);
gets(a);
printf(“\nEnter the second string:”);
gets(b);
result = compare(a, b);
186 • C Programming
if (result = = 0)
printf(“\nEntered strings are equal.\n”);
else
printf(“\nEntered strings are not equal.\n”);
}
int compare(char a[ ] , char b[ ] )
{
int c = 0;
while (a[c] = = b[c])
{
if (a[c] = = ‘\0’ || b[c] = = ‘\0’)
break;
c++;
}
if (a[c] = = ‘\0’ && b[c] = = ‘\0’)
return 0;
else
return -1;
}
OUTPUTS (after running):
Enter the first string: DR. RAJIV
Entered the second string: DR. RAJIV
Entered strings are equal.
#include<stdio.h>
main( )
{
int i, j, k, n, num, flag=0;
float a[80];
printf(“Enter the size of vector: “);
scanf(“%d”, &n);
printf(“%d”, n);
num = n;
printf(“\nEnter the vector elements:\n”);
for (i=0; i<n;i++)
scanf(“%f”, &a[i]);
for(i=0; i<n;i++)
printf(“%f”, a[i]);
printf(“\n);
/* removing duplicates */
for (i=0; i<n-1; i++)
for (j=i+1; j<n; j++)
{
if (a[i] = = a[j])
{
n= n – 1;
for (k =j; k<n; k++)
a[k] = a[k+1];
flag = 1;
j = j-1;
}
}
if ( flag = = 0)
printf (“\n No duplicates found in the vector”);
else
{
printf (“\nVector has %d duplicates \n\n”, num –
n);
printf (“Vector after deleting duplicates”);
for (i=0; i<n; i++)
printf (“%f”, a[i]);
printf (“\n”);
}
}
190 • C Programming
NOTE Attempt to write a program now to select an element from the vector.
Example 13: Write a C program to find the row sum and column sum of
a matrix.
Solution 13: The program is as follows:
#include<stdio.h>
main( )
{
int a[10][10], i, j, m, n;
printf(“\n Enter the number of rows and column:”);
scanf(“%d%d”, &n, &m);
printf(“Enter matrix elements:”);
for (i=1; i< n + 1; ++)
for(j=1; j < m+1; ++j)
scanf(“%d”, &a[i][j]);
/* find row sum */
for (i =1; i < n+1; ++i)
{
a[i][m+1] = 0;
for (j=1; j < m+1; ++j)
{
a[i][m+1] = a[i][m+1] + a[i][j];
}
}
* find col sum */
192 • C Programming
Example 14: Write a C program to sum the elements above and below
the main diagonal of a matrix.
Solution 14: The program is as follows:
#include<stdio.h>
Arrays and Pointers • 193
main( )
{
int a[50][50], i, j, n, csum, dsum;
printf(“Enter the size of your array:”);
scanf(“%d”, &n);
printf(“%d”, n);
printf(“Enter matrix elements:”);
for (i=1; i< n + 1; ++)
for(j=1; j < n+1; ++j)
scanf(“%d”, &a[i][j]);
printf(“Echoing given matrix:”);
for (i=1; i< n + 1; ++)
{
for(j=1; j < n+1; ++j)
{
printf(“%d”, a[i][j]);
}
printf(“\n”);
}
/* add elements above the main diagonal of a matrix */
csum = 0;
for (i=1; i< n+1; ++i)
{
for (j=1; j< n+1; ++j)
{
if (i < j)
csum = csum + a[i][j];
}
}
printf (“Sum of elements above the main diagonal: %d\n”,
csum);
/* add elements below the main diagonal of a matrix */
dsum = 0;
for (i=1; i< n+1; ++i)
{
for (j=1; j< n+1; ++j)
{
if (i > j)
dsum = dsum + a[i][j];
}
}
printf (“Sum of elements below the main diagonal: %d\n”,
194 • C Programming
dsum);
}
OUTPUT (after running):
Enter the size of your array: 3
Enter the matrix elements:
123
456
789
Sum of elements above the main diagonal: 11
Sum of elements below the main diagonal: 19
Example 15: Illustrate the process (using dry runs) of searching for
an element 6 in a given array A, with elements as 1, 2, 3, 4, 5, 6, 7, 8, 9,
10, using a binary search.
Solution 15: The following is the dry run:
Step 1: Given:
A 1 2 3 4 5 6 7 8 9 10
0 1 2 3 4 5 6 7 8 9
LB UB
Thus, mid = LB + UB / 2 = 0 +9 /2 = 4
Therefore, A[mid] is not equal to item as 5!=6
Step 2: As A[mid] < item, so
LB = mid + 1 = 4 + 1 = 5
Thus, the array part to search now is from A[5]:
A 6 7 8 9 10
5 6 7 8 9
LB UB
Arrays and Pointers • 195
A 6 7
5 6 7 8 9
LB UB
A[mid] = item
A[6] = 6
i.e., 6=6
The item is found.
Example 16: Write a C program to do the following operations:
(a) Find the length of a string without using the inbuilt string length
function of C.
(b) Copy one string to another without using the inbuilt string copy function
of C.
(c) Concatenate two strings without using the string concat function of C.
(d) Check whether two strings are the same without using the string
comparison function of C.
(e) Reverse a string without using the string reversal function of C.
196 • C Programming
(a) The length of a string without using strlen( ) can be found as follows:
#include<stdio.h>
#include<conio.h>
#include<string.h>
void main( )
{
char s1[20];
int i=0, length = 0;
clrscr( );
printf (“Enter your string:”);
scanf (“%s”, s1);
while (s1[i] != ‘\0’)
{
length ++;
i++;
}
printf(“The length of the string is %d”, length);
getch( );
}
(b) Copying a string without using strcpy( ) can be done as follows:
#include<stdio.h>
#include<conio.h>
#include<string.h>
void main( )
{
char s1[20], s2[20];
int i=0;
clrscr( );
printf (“Enter your string:”);
scanf (“%s”, s1);
while (s1[i] != ‘\0’)
{
s2[i] = s1[i];
i++;
}
s2[i] = ‘\0’;
printf(“The copy of the string is %s”, s2);
getch( );
}
Arrays and Pointers • 197
{
if (s1[i] = = s2[i])
{
flag = 0;
i++;
}
else
{
flag = 1;
break;
}
}
if (flag = = 0)
{
printf (“ Strings are same.”);
}
else
{
printf (“Strings are not same”);
}
getch( );
}
(e) Reversing a string without using strrev( ) can be done as follows:
#include<stdio.h>
#include<conio.h>
#include<string.h>
void main( )
{
char s1[20], s2[20];
int i=0, j;
clrscr( );
printf (“Enter your string:”);
scanf (“%s”, s1);
j = strlen(s1) – 1;
while (j >= 0)
{
s2[i] = s1[j])
i++;
j- -;
}
s2[i] = ‘\0’;
Arrays and Pointers • 199
123
456
789
The required traversal is: 1 2 3 6 9 8 7 4 5
Practice Programs
Q1. Write a C program to sort a matrix row-wise.
Q2. Write a C program to sort a given matrix column-wise.
Q3. Write a C program to check whether a given matrix is a magic square. A
magic square is one in which
Column sum = row sum = diagonal sum
and all elements in the matrix are distinct.
For example, the matrix given below is a magic square matrix:
4 3 8
9 5 1
2 7 6
On the other hand, the following matrix is not a magic square matrix:
3 3
3 3.
Q4. Write a C program to modify a matrix.
Example 18: Write a C program to print the upper and lower triangle
of a matrix.
Solution 18: The program is as follows:
#include<stdio.h>
main( )
{
int a[10][10], i, j, m, n;
printf (“\n\t Please enter the number of rows and col-
umns of a matrix:”);
scanf (“%d %d”, &n, &m);
printf (“%d%d”, n, m);
printf(“\n\t Enter the matrix elements:”);
Arrays and Pointers • 201
{
if (a[j][q] > a[p][q])
flag = 0;
}
if (flag)
{
printf(“Saddle point a[%d][%d] = %d\n”, p+1, q+1,
a[p][q]);
else
printf(“No saddle point in row %d\n”, i+1);
flag = 1;
}
}
OUTPUT (after running):
Please enter the number of rows and columns of a matrix: 3 3
Enter the matrix elements:
755
10 5 8
633
Saddle point a[1][2] = 5
Saddle point a[2][2] = 5
No saddle point in row 3
Example 20: Write a C program to check whether a given matrix is or-
thogonal.
Solution 20: The program is as follows:
#include<stdio.h>
main( )
{
int a[5][5], b[5][5], c[5][5];
int i, j, m, k, flag=0;
printf (“\n\t Enter the order of matrix:”);
scanf (“%d”, &m);
printf (“%d * %d”, m, m);
printf(“\n\t Enter the matrix elements:”);
for (i=0; i<m; i++)
for (j=0; j<m; j++)
204 • C Programming
scanf(“%d”, &a[i][j]);
/* Echoing array…. */
for (i=0; i<m; i++)
{
for (j=0; j<m; j++)
printf(“%f”, a[i][j]);
printf(“\n”);
}
/*transpose the given matrix */
for (i=0; i<m; i++)
for (j=0; j<m; j++)
b[i][j] = a[j][i];
printf(“Transpose is:”);
for (i=0; i<m; i++) {
for (j=0; j<m; j++)
printf(“%f”, b[i][j]);
printf(“\n”);
}
/* if matrix A * transpose of A = identity matrix */
for (i=0; i<m; i++) {
for (j=0; j<m; j++) {
c[i][j] = 0;
for(k=0; k<=m; k++) {
c[i][j] + = a[i][k] * b[k][j];
}
}
}
for (i=0; i<m; i++)
{
for (j=0; j<m; j++)
{
if ((int) c[i][i] = = 1 && (int) c[i][j] = = 0)
flag = 1;
}
printf(“Matrix A * transpose of A”);
for (i=0; i<m; i++) {
for (j=0; j<m; j++)
printf(“%f”, c[i][j]);
printf(“\n”);
}
if (flag = = 1)
printf (“Matrix A * Transpose of A = Identity Ma-
Arrays and Pointers • 205
trix”);
printf (“The given matrix is orthogonal\n”);
else
printf (“Matrix A * Transpose of A < > Identity Ma-
trix”);
printf (“The matrix is not orthogonal”);
}
OUTPUT (after running):
Enter the order of the matrix: 3* 3
Enter the matrix elements:
0.0 0.0
1.0 0.0
0.0 1.0
Transpose is
0.0 0.0
1.0 0.0
0.0 1.0
Matrix A * Transpose of A = Identity Matrix
The given matrix is orthogonal
Practice Programs:
Q1. Write a C program to find whether a given matrix is singular. It is said that
if the determinant is 0, the matrix is singular.
Q2. Write a C program to find whether a given matrix is symmetric.
[Hint:
#include<stdio.h>
main( )
{
int a[5][5], b[5][5], c[5][5];
int i, j, m, k, flag=0;
printf (“\n\t Enter the order of matrix:”);
scanf (“%d”, &m);
printf (“%d * %d”, m, m);
printf(“\n\t Enter the matrix elements:”);
206 • C Programming
break;
case 6:
printf(“six”);
break;
case 7:
printf(“seven”);
break;
case 8:
printf(“eight”);
break;
case 9:
printf(“nine”);
break;
case 10:
printf(“ten”);
break;
default:
break;
}
}
printf(“\n”);
}
OUTPUT (after running):
Enter your number: 567321
The number in words is: five six seven three two one
Example 22: Write a C program to count the number of vow-
els, consonants, words, white spaces, and other charac-
ters in a line of text.
Solution 22: The program is as follows:
#include<stdio.h>
main( )
{
char line[80], c;
int i, vow, cons, dig, word, whites, other;
i =vow = cons = dig = word = whites = other = 0;
printf (“\n\t Enter a line of text”);
scanf(“%[^\n]”, line);
printf(“%s”, line);
while ((c = tolower(line[i++])) != ‘\0’)
{
if (c = = ‘a’ || c = = ‘e’ || c = = ‘i’ || c = = ‘o’
|| c = =’u’)
++vow;
else if (c >= ‘a’ && c<= ‘z’)
Arrays and Pointers • 209
++cons;
else if (c >= ‘0’ && c <=’9’)
++dig;
else if (c = = ‘ ‘) {
++word;
++ whites;
while ((line[i] = = ‘ ‘ || line[i] = = ‘\t’))
{
i++;
whites++;
}
}
else
++other;
}
++word;
printf(“\n\n---------------------“);
printf(“\n\nTotal number of: “);
printf(“\n\n---------------------“);
printf(“Vowels = %d\n”, vow);
printf(“Consonants = %d\n”, cons);
printf(“Digits = %d\n”, dig);
printf(“Other characters = %d\n”, other);
printf(“Words = %d\n”, word);
printf(“White spaces = %d\n”, whites);
}
OUTPUT (after running):
Enter a line of text: Dr. Rajiv Chopra has written 23 books!
---------------------
Total number of:
---------------------
Vowels = 9
Consonants = 21
Digits = 2
Other characters = 1
Words = 7
White spaces = 6
210 • C Programming
NOTE Observed that in the scanf statement in this program we have used the ^
character also. Its meaning can be clarified with an example. If we write:
%[A – Z]
in scanf, it will catch all uppercase inputs. On the other hand, if we
write:
%[^a – c]
in scanf, it will catch all ASCII except ‘a’, ‘b’, and ‘c’.
Example 23: Write a C program to search for a substring within a string
and to display its position.
Solution 23: The program is as follows:
#include<stdio.h>
main( )
{
char mainstr[50], patstr[50];
int i, j, k, len1, len2, diff, flag;
/*strings taken till newline character */
printf(“Enter the main string\n”);
scanf(“%[^\n]”, mainstr);
printf(“%s”, mainstr);
for(len1=0; mainstr[len1] != ‘\0’; len1++)
printf(“\n Length of main string is %d\n”, len1);
printf(“\n Enter pattern string \n”);
scanf(“%s”,patstr);
printf(“%s”, patstr);
for(len2=0; mainstr[len2] != ‘\0’; len2++)
printf(“\n Length of pattern string is %d\n”, len2);
/*index */
flag = 0; /*set flag */
j=0;
for (i=0; i<len1, j <len2; i++)
if (mainstr[i] != patstr[j])
flag = 1;
else {
flag = 0; /* reset flag */
j ++;
}
Arrays and Pointers • 211
if (flag = = 0)
printf(“\n Pattern found at position %d\n”, i-len2+1);
else
printf(“\n Pattern not found”);
}
OUTPUT (after running):
Enter the main string:
Dr. Rajiv Chopra has a Ph.D.
Length of main string is 25
Enter pattern string
Chop
Length of pattern string is 4
Pattern found at position 24
Practice Programs:
Q1. Write a C program to insert a substring into a string.
Q2. Write a C program to replace a portion of a string.
Example 24: Write a C program to sort a string of names.
Solution 24: The program is as follows:
#include<stdio.h>
main( )
{
char names[20][10], temp[10], c;
int i, j, k, n;
n=0;
printf(“\n Enter names one [er line \n”);
printf(“Terminate with string END\n”);
scanf(“%s”, names[n]);
while (strcmp(names[n], “END”) > 0) {
n++;
scanf(“%s”, names[n]);
}
printf(“\n”);
for (i=0; i<n; i++)
printf(“%10s”, names[i]);
printf(“\n”);
212 • C Programming
printf(“\n”);
printf(“Total names = %d\n”, n);
/*selection sorting is used */
for (i=0; i<n – 1; i++)
for (j = i +1; j<n; j++) {
if (strcmp(names[i], names[j]) > 0) {
strcpy(temp, names[i]);
strcpy(names[i], names[j]);
strcpy(names[j], temp);
}
}
printf(“\n Sorted Names: \n”);
for(i=0; i<n; i++)
printf(“%10s”, names[i]);
printf(“\n”);
getch( );
}
OUTPUT (after running):
Enter names one per line
Terminate with string END
Krish Rajiv Ajay Mayur Diksha
Total names = 5
Sorted Names:
Ajay Diksha Krish Mayur Rajiv
When a problem to be solved is very complex, we first need to divide that com-
plex problem into smaller, simpler problems. Then we try to find the subsolu-
tions to these subproblems. Finally, we integrate (combine) all these subso-
lutions to get a complete solution. This approach is called the modular
approach and such programming is called modular programming. An
advantage here is that parallel coding can be done for these modules. A library
of modules may be created and these may be reused when needed by another
program and called by the user. They behave like inbuilt modules. Debugging
and maintenance of modules is simpler than ever, as module sizes are usu-
Arrays and Pointers • 213
Characteristics of a Module
1. A module contains a series of program instructions in some program-
ming language.
2. A module is terminated by some special markers required by the syntax
of the language.
3. A module as a whole has a unique name.
4. A module has only one entry point to which control is transferred from
the outside and only one exit point from which control is returned to the
calling module.
5. Structured programming involves modularization of a program structure.
Top-down analysis is a method of problem solving and problem
analysis. It involves two main tasks:
3.3 FUNCTIONS
Syntax
<type> name (arguments)
{
……..
……..
<statements>
……
}
‘type’ is the value returned by the function. If no value is returned back
from the function, then the keyword void is used.
‘name’ is the user-defined name of the function. A function can be called
from anywhere with this name only.
‘arguments’ is a list of parameters. If there are no parameters, then just
two parentheses ( ) are placed.
The program segment enclosed within the opening and closing
brace is called a function body.
For example, in C every program starts with a main( ). The program of
every program within C also starts with main( ) only. All functions that
you define must be called from main( ), or else they will not work.
Example
name( )
{
printf(“\n My name is Dr. Rajiv Chopra”);
}
void main( )
{
clrscr( );
printf(“\nGood Morning”);
name( ); /* function call */
getch( );
}
Here, too, program execution starts from main( ). It displays the message
“Good Morning” and then calls the function name( ). Control goes to the func-
tion name( ). It displays “My name is Dr. Rajiv Chopra”. And then control goes
back to the main program.
Arrays and Pointers • 215
That is, when the program control reaches the function call f1( ) then it
transfers control to the function f1( ) (on the right-hand side), where on en-
countering a return statement, control returns back to the main( ) function.
Types of Functions
Functions can be of two types:
Defining a Function
1. int gcd(int u, int v)
2. {
3. int temp;
4. temp = u % v;
5. u = v;
6. v = temp;
7. return (v);
8. }
In this function, observe that:
2. The arguments that are passed from main( ) are known as actual
arguments. The actual arguments may be constants, variables, or
more complex expressions.
3. Each actual argument must be of the same type as its
corresponding formal argument.
4. It is the value of each actual argument that is transferred into the
function and assigned to the corresponding formal argument.
5. If the return type of the function is not specified, then by default it is
assumed to be of type int.
6. Formal arguments cannot be constants or expressions.
7. Rules for naming a function are the same as for variable names.
8. The return type in the main or in the function must be of the same type.
9. The function is known as a called function while the main( ) function
that calls it is known as a calling function.
Just as variables are declared, similarly functions needs to be declared
as follows:
<type> <name> (arguments);
This is essentially a function prototype. If you are working in C on a
UNIX platform, it may not be necessary to write the prototype first, but if you
are running your program with a C++ compiler, it is necessary. Every C pro-
gram can be run on a C++ compiler, too, as C is subset of C++.
For example,
fact(int n);
Here, ‘n’ is an actual argument and there is no return value in this function
call. It ends with a semicolon. On the other hand, consider
result = fact(int n);
This function call will return some value in the ‘result’ variable.
We can even write the following:
fact( );
This means that the function has nothing to return now and has no
arguments.
218 • C Programming
User-Called Functions
There are five types of functions that can be created by the user and then
called.
int a, b, c;
printf(“\nEnter two numbers for difference:”);
scanf(“%d %d”, &a, &b);
c = a - b;
return ( c) ;
}
int mul( )
{
int a, b, c;
printf(“\nEnter two numbers for multiplication:”);
scanf(%d %d”, &a, &b);
c = a * b;
return ( c) ;
}
OUTPUT (after running):
Enter two numbers for addition: 20 40
The addition of two numbers: 60
Enter two numbers for difference: 80 40
The difference of two numbers: 40
Enter two numbers for multiplication: 50 90
The product of two numbers: 4500
Explanation: In this program, we have called three functions—add( ),
sub( ), and mul( )—from the main( ) function. Note that since we are not
passing any values to these three functions and just receiving value, in
their prototypes declaration it is therefore necessary to include void in
parenthesis and int as their return types. If a function prototype specifies
its return type as void then it is terminated by the closing brace of its defini-
tion. If you want to return some value from a function, you must use the return
statement with a value within its body. The return statement returns only one
value at a time. A void returning function can use the return statement with no
value as:
void example( )
{
printf(”\n Thanks to God”);
return;
}
222 • C Programming
Also note that the return statement can appear anywhere in the
function body. It means that the programmer is free to use it before the
closing brace of the function body.
For example,
#include<iostream.h>
void main( )
{
void test( );
test( );
}
void test( )
{
int u;
printf(“Enter your number: “);
scanf(%d”, &u);
if ( u < 0)
{
printf(“\n It is a negative number”);
return;
}
else
{
printf(”\n It is a positive number”);
return;
}
}
OUTPUT (after running):
Enter your number: -80
It is a negative number
V. Recursions
Recursion is defined as a process in which a function calls itself again
and again. It is a technique of defining a problem in terms of one or more
smaller versions of the same problem. The solution to the problem is built on
the results from the smaller versions. A recursive function is one which calls
itself directly or indirectly to solve a smaller version of its task until a final call
which does not require a self-call.
For example,
Add( )
{
Add ( );
}
This means that the function add( ) calls itself.
Advantages of Recursion
1. Recursion makes the program compact.
2. For complex problems, recursions can lead to solutions that are much
clearer and easier to write.
3. It is very simple and quite apt for data structures like stacks, queues,
trees, and so on.
4. During recursion, the system takes care of the internal stack.
5. It is useful for problems in which there is some repetition.
Disadvantages of Recursion
1. It is slower as far as speed and execution time.
2. It takes more memory space as variables are created again and again
during every function call.
3. It needs extra runtime overhead.
4. For most problems recursion is difficult to implement.
5. Too many recursive calls will result in stack overflow.
There are two conditions for recursion:
Recursion Iteration
(1) It is slower as compared to iteration. (1) Iteration is faster than recursion.
(2) It takes more memory, as variables (2) It takes less memory, as variables are
are created again and again during declared only once.
every function call.
(3) These algorithms may require extra (3) No overhead is involved in these
overhead for multiple function calling. algorithms.
(4) In some scenarios, recursion is (4) For some scenarios, iteration is dif-
simple to use (like tree traversal); ficult to implement; sometimes it is
otherwise, it is difficult. easy to implement.
(5) The system takes care of the internal (5) The user must take care of the inter-
stack. nal stack.
Let us now write a program to find the factorial of a number using each of
these methods (i.e., recursion and iteration).
Iterative Method:
An iterative loop to find the factorial of a number is as follows:
:
:
:
fact = 1;
for (i =1; i <=n; i++)
fact = fact * i;
printf(“\n The factorial of %d = %d”, n, fact);
Recursive Method:
As we know
n! = n * (n – 1) !
= n * (n – 1) * (n – 2)!
We continue this process till the end (i.e., 0! = 1). We can generalize now:
Arrays and Pointers • 225
fact ( n ) = 1 if n = 0
n * fact ( n – 1) if n > 0
Thus, we write:
fact (int n)
{
if ( n = = 0)
return ( 1);
else
return ( n * fact (n – 1));
}
The function fact is being called by itself but with parameter n replaced by
n-1. This ability of a function to call itself again and again is known as
recursion.
This process is repeated for any factorial that you want to find. But please
remember that this program will work up until, say, 8! or 9! or 10!
Higher numbers may result in stack overflows. Therefore, we need to
modify the preceding program by changing integer-type variables to
either long int or even doubles. This is because the register sizes now
needed are larger than for the smaller values of n (whose factorial you
want).
Also keep the following points in mind while using recursions:
1. Determine the specific variable which will be responsible for the termi-
nation of the algorithm (i.e., key variable).
2. Determine the value of the key variable that will terminate the algorithm
(i.e., base value).
3. Ensure that the key variable always approaches the base value.
4. When the key variable equals the base value, the algorithm must terminate.
We are in a position to write some programs on recursions now.
Example 1: Write a C program to generate a Fibonacci series to n using
recursion.
Solution 1: The program is as follows:
#include<stdio.h>
#include<conio.h>
void main( )
{
int n, i, t;
clrscr( );
printf(“\n Enter the number of terms to be generated”);
scanf(“%d”, &n);
printf(“\n\t The Fibonacci series is:”);
for (i =1; i <=n; i++)
{
t = fib (i);
printf(“\t %d”, t);
}
getch( );
}
fib (int n)
{
Arrays and Pointers • 227
if (n = = 1)
return 0;
else
if ( n = = 2)
return ( 1);
else
return (fib (n – 1) + fib (n -2));
}
OUTPUT (after running):
Enter the number of terms to be generated: 5
The Fibonacci series is:
0 1 1 2 3
Example 2: Write a C program to find the GCD of two numbers using
recursion.
Solution 2: The program is as follows:
#include<stdio.h>
#include<conio.h>
void main( )
{
int a, b, res;
clrscr( );
printf(“\n Enter the two numbers to find their
gcd:”);
scanf(“%d %d”, &a, &b);
if ( a > b)
res = gcd(a, b);
else
res = gcd (b, a);
printf(“\n The GCD of %d and %d = %d”, a, b, res);
getch( );
}
gcd( int x, int y)
{
int r;
r = x % y;
if ( r = = 0)
return (y);
else
return (y, r);
}
228 • C Programming
There are two ways in which data can be made available to a program. One way
is to declare global data. This type of data will be available throughout the pro-
gram. The other method is by passing data through and across functions. This
method is better than the first one as in the first method (global variables) the
privacy of the data is lost.
The ultimate aim of the program is that data should be available to other
functions. This can be done two ways—one is to declare data (variables) as
global variables and the other way is to pass the data to the functions.
Arguments can generally be passed to functions in one of two ways:
I. Pass by Value
We know that the function header is always formal and thus its argu-
ments are called formal arguments. Whenever a portion of the program
is calling a function with a formal argument, control will be transferred from
the main to the calling function and the value of the actual argument is copied
into the function. Within the function, the actual value copied from the calling
portion of the program may be altered or changed. Please note that when
control is transferred back from the function to the calling portion of
the program, the altered values are not transferred back. This way of
passing formal arguments to a function is called call by value. The only
limitation of call by value is that the value of the actual argument remains un-
changed. This situation is useful where we do not want to change the values of
the arguments. In other situations call by value is not as appropriate.
Arrays and Pointers • 229
For example,
#include<iostream.h>
#include<conio.h>
void main( )
{
clrscr( );
int a = 10;
int b = 20;
swapv (a, b);
printf(”\na is:”, a);
printf(“\nb is:”,b);
getch( );
}
swapv (int x, int y)
{
int t;
t = x;
x = y;
y = t;
printf(”x is:”,x); //values are exchanged here but no
impact on the main( ) above.
printf(”y is:”, y);
}
OUTPUT (after running):
x = 20
y = 10
a = 10
b = 20
Explanation: In this first method, the ‘value’ of each actual argument in
the calling function is copied into the corresponding formal arguments of the
called function. With this method, changes made to the formal arguments in
the called function have no effect on the values of the actual arguments in the
calling function. Also note that the values of ‘a’ and ‘b’ remain unchanged
even after exchanging the values of ‘x’ and ‘y’. We are passing 10 and 20
from the main ( ) into the swapv function. In the swapv function, the values are
exchanged (i.e., x and y become 20 and 10 after exchange but this change is
NOT reflected back in the main program).
230 • C Programming
int a =10;
int *ptr = &a;
That is, ‘ptr’ is an integer pointer that holds the memory address of another
integer variable, ‘a’. We must declare a pointer variable also. Many pointer vari-
ables can be declared on a single line, such as
int *ptr1, *ptr2, *ptr3;
We can even have an array of pointers and so on but we shall study this a bit
later. Remember the following rule: “Always store the address of a data
type into a pointer of the same data type. We cannot store the address
of a variable of one type into a pointer variable of another type. This
means that the integer pointer can hold the address of an integer vari-
able, the float pointer can hold the address of a float variable, and so
on.” In the call by address technique, we pass addresses of actual arguments to
the called function. These addresses are stored in formal arguments, which are
nothing but pointer variables. Now whatever changes are made in the formal
arguments are reflected directly to the actual arguments.
to a reference, then that change is actually applied to the variable to which the
reference refers. As a result, all references to either name have the same effect.
For example,
v+ = 1;
will add 1 to ‘u’, the variable referred to by ‘b’. Also note that each defini-
tion of a reference must be preceded by the address-of operator—that
is, & (ampersand).
For example,
#include<iostream.h>
void main( )
{
int a = 100;
int &b = a;
printf(”\n a= %d b= %d“ , a, b);
b = 200;
printf(”\n a= %d b= %d“ , a, b);
a = 300
printf(”\n a= %d b= %d“ , a, b);
}
OUTPUT (after running):
a= 100 b = 100
a= 200 b = 200
a= 300 b = 300
Please note here that ‘b’ is called as a reference to ‘a’ and note that
the ‘a’ variable and its reference are so closely interlinked that if one
changes, the other will automatically change. Also remember that even
the address of ‘a’ and ‘b’ are the same. From the output it is also observed
that a reference is neither a copy nor a pointer to the object to which it refers.
Instead it is just another name.
However, there is a difference between a normal reference and a const ref-
erence. A const reference can be initialized to a variable of a different
data type. There is a conversion from one type to another, as well as to
some constants.
Arrays and Pointers • 233
For example,
float u = 99.90;
const int &a = u;
Note that these initializations are completely invalid for non-const
references and thus they result in compile-time errors. When it is initial-
ized to a variable type then the compiler must generate a temporary object that
the reference actually addresses. But, unfortunately, the user has no access to it.
So the previous two statements are internally transformed as follows:
float u = 99.90;
int temp = u;
const int &a = temp;
We have already written swap functions for the call by value and call by ad-
dress methods. Now let us write one for the call by reference method.
#include<iostream.h>
void main( )
{
int u, v;
printf(”\n Enter your two numbers:”);
scanf(“%d %d”, &u, &v);
printf(”Before calling swapref( ) function.”);
printf(”\n u=%d \t v= %d”, u, v);
swapref(u, v);
printf(”After calling swapref( ) function.”);
printf(”\n u=%d \t v= %d”, u, v);
}
void swapref (int &aa, int &bb)
{
int temp;
temp = aa;
aa = bb;
bb = temp;
}
OUTPUT (after running):
Enter your two numbers: 11 55
Before calling swapref( ) function.
234 • C Programming
u = 11 v = 55
After calling swapref( ) function.
u = 55 v = 11
3.5 POINTERS
Programming languages like C and C++ make use of pointers whereas the
JAVA2 language is free of pointers. A pointer is a variable that holds the memo-
ry address of another variable. It allows us to do an indirect manipulation of that
variable because it holds the address of that variable where it has been stored
in memory. Pointers have many applications and if used with care they can im-
prove the efficiency of our programs. Let us explore this and other concepts in
this section.
u 80 20A0
Here the address of 20A0 is assigned to the variable ‘u’ with a value of 80 in
it. Note here that the address itself is an integer (in HEX form).
Now when we say ‘u’, the reference is to the value at ‘u’ whereas if we say
‘&u’, the reference is to its address, which is 20A0 in memory. This is done
by the operating system itself. And if now I say ‘*(&u);’ it means the value or
contents of the location referred to by ‘u’ (i.e., 80). It means that first the
parentheses are evaluated—that is, the address (&) of ‘u’ and then its
Arrays and Pointers • 235
Pointer Variables
We can store the addresses of variables in a special type of variable known as
a pointer variable. We can define a pointer variable as a variable that
holds the address of a variable or a function.
Syntax
data-type *pointer-name;
Here, ‘pointer-name’ is the name of the pointer variable and ‘data-type’
is any valid C++ data type. The asterisk operator or star operator (*) means
“pointer to”. In C, we can write:
int *ptr;
But in C++ we can also write:
int* ptr;
Note here that both will work, as spaces are optional. Also note here that
the result of the pointer operator (*) does the reverse of the operator
&. The pointer operator (*) returns the value of the variable stored at
the address following it. So to access the value stored at an address, we will
use the pointer operator. Also note that, like integer pointers, we can also
have char pointers or float pointers.
236 • C Programming
For example,
char *ptr1;
float *ptr2;
This means that *ptr1 and *ptr2 are pointing to float value and char value,
respectively. It does not mean that *ptr1 contains a char value or *ptr2 contains
a float value. Actually, pointer variables are of uniform size regardless of what
they point to.
Just like ordinary variables, we can also write multiple pointer declarations
in one line as follows:
int *ptr1, *ptr2, *ptr3;
But please remember that we store the address of a data type into
a pointer of the same data type. This means that an integer pointer can
hold the address of an integer variable, a float pointer can hold the ad-
dress of a float variable, and so on.
For example,
#include<iosteam.h>
void main( )
{
int i = 100;
float *ptr;
ptr = &i;
printf(“value of ptr is %d”, *ptr);
}
After compilation, we get the following error:
‘cannot convert “int” to “float”’
Why? This is so because ‘ptr’ is a float pointer and we have stored the ad-
dress of an integer variable to a float pointer. Therefore, the pointer variable
must always point to the correct data type. But there is an exception to this rule
in C++ as C++ provides a void pointer to overrule this limitation.
void Pointers
A void pointer is a pointer that can point to any type of variable. It is
declared as follows:
void *vptr;
Arrays and Pointers • 237
Here ‘vptr’ is called a pointer to void type that can point to any type of vari-
able, say, an int, a float, and so on. Thus, we can also define a void pointer
as a general-purpose pointer that can point to any data type.
Applications of Void Pointers
Void pointers are used as parameters to functions that can operate on any
type of memory. It is also possible to return void pointers to assign to any of
several different types of pointers. Remember that you cannot use a void
pointer to dereference a variable unless you provide a type cast. It
means that if ‘vptr’ contains an address of an integer variable, then you
cannot display its value as:
printf(“void pointer is”, *vptr);
A void pointer can point to any data type but the reverse is not
true—that is, the following program statement would result in an error:
ptr1 = vptr; //error
To remove this error, you would have to type cast it explicitly as follows:
ptr = (int *) vptr;
Also remember that if you have to perform arithmetic on a void
pointer, it is not possible without a type cast.
If ‘ptr’ holds 2000 (address), then after the execution of the second state-
ment, ‘ptr’ gets 2002. Subtraction works similarly.
A character pointer also works like this, except its size is different now.
When we increment or decrement a character pointer variable, its value is in-
cremented/decremented by 1. This is because a character occupies 1 byte in
memory. Along similar lines, a float pointer variable’s value, when incremented/
decremented, increases/decreases by 4. In other words, in pointer arith-
metic, all pointers increase and decrease by the length of the data type
they point to. And remember that regardless of the pointer type, the
pointer holds the address of the very first byte of the memory location.
And this address of the very first byte is known as the base address.
Every time a pointer is incremented, it points to the immediate next
location of its type.
So we can use them as follows:
int i = 75;
int *ptr;
ptr = &i;
Also we can say that:
int *ptr = 0;
int *ptr1 = &i;
And we can even write:
ptr = ptr1; // is OK
But the following is invalid:
ptr = i;
This implies that one should always set a pointer to a definite and appropri-
ate address before applying the dereference operator (*) to it.
In a nutshell, we can say:
8. When we say a[i], the C++ compiler internally converts it to *(a +i).
The same thing happens with 2D arrays.
9. In memory, whether it is a 1D array or a 2D array, the elements are
stored in one continuous chain.
10. Just as num[i] is the same as *(num + i), similarly, *(num[2] +1) is the
same as *(*(num +2) +1).
11. So a[i], *(a +i), *(i + a), and i[a] all refer to the same element—the ith
element from the base address.
12. The expression *(a + i) = a[i] + i[a] is nothing but a[i] = a[i] + a[i];
Internally all arrays (of any dimension) make use of pointers for their implemen-
tation. In C/C++, the array name is treated as the address of its first element.
For example,
int a[20];
Here, ‘a’ is the name of the array that holds 80 integer numbers and the
value of ‘a’ is the address of num[0] (i.e., the address of the first element of the
array); then, (a + 1) contains the address of the 2nd element, (a +2) contains an
address of the 3rd element, and so on. This is because the C++ compiler inter-
nally reserves 40 words for a 20-array element. However, you can also access the
address of array elements as &a[0], &a[1], &a[2], and so on. Just remember
240 • C Programming
1. The bracket [ ] tells the compiler that we are dealing with an array.
2. An array is a collection of similar elements.
3. The first element in an array is numbered 0 and hence the last element is
1 less than the size of the array.
4. However big an array may be, its elements are always stored in contiguous
memory locations.
5. If array elements are not initialized, then they are said to contain garbage
values.
For example,
#include<iostream.h>
#include<conio.h>
void main( )
{
clrscr( );
int a = 10;
int b = 20;
swapr (&a, &b);
printf(”\n a is:”, a);
printf(”\n b is:”, b);
getch( );
}
swapv (int *x, int *y)
{
int t;
t = *x;
*x = *y;
*y = t;
printf(”x is:”,x); //values are exchanged here but
now impact is on the
main( )
//above.
printf(”y is:”, y);
}
OUTPUT (after running):
x = 20
y = 10
a = 20
b = 10
Explanation: Let us review the concept of pointers. A pointer is a vari-
able that holds the memory address of another variable. For example,
int a =10;
int *ptr = &a;
That is, ptr is an integer pointer that holds the memory address of another
integer variable, ‘a’. We must declare a pointer variable also, many of which can
be declared on a single line, as in the following:
int *ptr1, *ptr2, *ptr3;</dsp>
Arrays and Pointers • 243
Just like ordinary variables, we can also pass a complete array by using its base
address.
For example,
#include<stdio.h>
void main( )
{
int a[5];
void aread(int *, int);
void adisplay(int*, int);
printf(“\nEnter any 5 integers:”);
aread(a, 5);
printf(“Array elements are :”);
adisplay(a, 10);
}
void aread(int *aptr, int n)
{
for (int i=0; i<n; i++)
scanf(“%d”, &aptr[i];
}
void adisplay(int *ptr, int n)
{
for (int i=0; i<n; i++)
printf(“\n Array Elements:”, aptr[i]);
}
OUTPUT (after running):
Enter any 5 integers: 1 2 3 4 5
Array elements are:
1
2
3
4
5
Explanation: Here we have used two functions—aread( ) and adisplay( )—
to read an integer array and to display its elements, respectively. Their proto-
types are as follows:
Arrays and Pointers • 245
function does not need to know how many rows there are in such a 2D array,
but the length of each row (i.e., column) is mandatory.
We are in a position to solve an example now.
Example 1: Write a C program to find the trace of a 2D matrix.
Solution 1: Trace of a matrix is defined as the sum of its diagonal
elements. The program is as follows:
#include<stdio.h>
void main( )
{
void readarray(int a[ ] [4], int n);
void trace(int a[ ] [4], int n);
void display(int a[ ] [4], int n);
int a[4][4];
readarray(a, 4);
display(a, 4);
trace(a, 4);
}
void readarray(int a[ ] [4], int n)
{
int i, j;
printf(”\nEnter the elements of 2D matrix:\n)”;
for (i =0; i<4; i++)
{
for(j=0; j<4;j++)
scanf(“%d”, &a[i][j]);
}
}
void display(int a[ ] [4], int n)
{
int i, j;
printf(”\nMatrix is:”);
for (i =0; i<n; i++)
{
printf(”\n”);
for(j=0; j<n; j++)
printf(“ Array is:\t”, a[i] [j]);
}
Arrays and Pointers • 247
}
void trace(int a[ ] [4], int n)
{
int diagonal_sum = 0;
// trace calculated now
for (int i =0; i<n; i++)
diagonal_sum += a[i][j];
printf(“\n Trace=”, diagonal_sum);
}
OUTPUT (after running):
Enter the elements of 2D matrix:
1 2 3 4
5 6 7 8
9 10 11 12
13 14 15 16
Matrix is:
1 2 3 4
5 6 7 8
9 10 11 12
13 14 15 16
Trace = 34
We are in a position to write some programs now.
Example 1: Give the output of the following C program:
#include<stdio.h>
main( )
{
static int a[ ] = {1, 2, 3, 4 };
int *ptr;
ptr = a;
*(a + 3) = (*ptr++) + *(ptr++);
printf(“\n\t\t Elements are:”, *(a + 3);
printf(“\n\t\t”, a[0], a[1], a[2], a[3]);
getch( );
}
248 • C Programming
(a) When the array name is used with the sizeof operator
(b) When the array name is an operand of the & operator
If we pass the name of a 1d int array to a function, it decays into a pointer
to an int. But if we pass the name of a 2d array of integers to a function, then it
decays into a pointer to an array and not a pointer to a pointer.
Example 4: Give the output:
void main( )
{
printf(“%c”, “abcdefgh”[5] );
}
Solution 4: f is the output.
Example 5: How will you display \n as an output?
Solution 5: Simply write:
printf(“\\n”);
Arrays and Pointers • 249
Example 11: Write a C program to find the sum of the digits of an inte-
ger number. Use functions only.
Arrays and Pointers • 251
n
Cr = n! / r! (n – r)!
Solution 12: The program is as follows:
#include<stdio.h>
#include<conio.h>
void main( )
{
int ncr;
long n, r;
252 • C Programming
clrscr( );
printf(“\n Enter value of n and r”);
scanf(“%ld%ld”, &n, &r);
ncr = fact(n) / (fact (r) * fact(n – r));
printf(“\n Value of ncr = %d”, ncr);
getch( );
}
fact (int num)
{
int i;
long f = 1;
for (i =1; i <= num; i++)
f = f * i;
return (f );
}
NOTE Please run the program yourself.
clrscr( );
printf(\n Enter the number of terms:”);
scanf(“%d”, &n);
printf(“\n Enter the value of x:”);
scanf(“%d”, &x);
for ( i = 3; i <= n; i += 2)
{
t1 = power (x, i);
t2 = fact (i);
sum = sum + (float) t1/t2;
}
printf(“\n The sum of the series = %f”, sum);
getch( );
}
power (int x, int y)
{
int i, pow = 1;
for (i=1; i <=y; i++)
pow = pow * x;
return (pow);
}
fact (int n)
{
int j, fact = 1;
for (j=1; j<=n; j++)
fact = fact * j;
return (fact);
}
Please run this program yourself.
(a) Only one disk can be moved at a time and that is the top disk.
(b) A Larger disk cannot be placed on top of a smaller disk.
Write a C program to simulate this Tower of Hanoi problem.
Solution 16: Let us write its algorithm first:
if (n = = 1) then
move disk 1 from tower A to C
else
Arrays and Pointers • 255
turbo c). After adding the function, the linker will automatically link it with your
program code as it does with inbuilt functions of C. Consider an example of a
factorial function as follows:
int fact(int n)
{
int i, f = 1;
for (i=1; i<=n; i++)
f = f *i;
return (f);
}
Save this program in some file—say, facto.c
Now compile this file using the ctrl+F9 key. This creates a “facto.obj” file
having object code.
From the DOS prompt, add the function to the library by using the
command:
C:\>TLIB\TC\LIB\math.lib + \TC\facto.obj
Please note here that math.lib is the library name, + is used to add
a new function to the library, and facto.obj is the file to be added. Also
note that minus (-) is used to delete existing functions.
Now declare the prototype of the fact( ) in the header file—say, fact.h. This
file should be included while calling the function. To use the function create a
program as follows:
#include “c:\\fact.h”
main( )
{
int f;
f = fact (5);
printf(“%d”, f);
}
Now compile and execute the program using ctrl+F9.
Example 18: Distinguish between formal and actual parameters.
Solution 18: The following are the differences:
Arrays and Pointers • 257
void hello( )
{
char name[20];
printf(“Enter your name”);
scanf(“%s”, name);
printf(“%s\n\n”, name);
printf(“Hello %s, good morning”, name);
}
OUTPUT (after running):
Enter your name: Dr. Rajiv
Hello Dr. Rajiv good morning
Example 23: Write a C program to implement a simple calculator that
can add, subtract, multiply, and divide two numbers read from the key-
board.
Solution 23: The program is as follows:
#include<stdio.h>
main( )
{
float num1, num2, result;
char opn;
void arithop( );
printf(“Enter any two numbers and the \n”);
printf(“operation symbol (+, -, * or /) \n”);
scanf(“%f %f %c”, &num1, &num2, &opn);
printf(“\n %8.2f %c %8.2f = “, num1, opn, num2);
arithop(num1, num2, opn);
}
void arithop (a, b, op) /*arithop function */
float a, b;
char op;
{
switch (op) {
case ‘+’ :
printf(“%10.2f\n”, a+b);
break;
case ‘-’ :
printf(“%8.2f\n”, a-b);
break;
case ‘*’ :
260 • C Programming
printf(“%8.2f\n”, a*b);
break;
case ‘/’ :
printf(“%8.2f\n”, a/b);
break;
default:
printf(“Invalid operation”);
break;
}
}
OUTPUT (after running):
Enter any two numbers and the
Operation symbol (+, -, *, or /)
44.00 / 11.00 = 4.00
Example 24: Write a C program to compute the mean and standard de-
viation of n numbers that are read from the keyboard.
Solution 24: The program is as follows:
#include<stdio.h>
#include<math.h>
main( )
{
int i, n;
float deviation, list[20];
float sd( ); /* function declaration */
printf(“Calculating standard deviation of a…… “);
printf(“list of numbers:”);
printf(“\n Enter the size of the list:”);
scanf (“%d”, &n);
printf(“%d\n”, n);
printf(“\n Enter the %d elements\n”, n);
for(i=0; i<n; i++)
scanf(“%f”, &list[i]);
for(i=0; i<n; i++)
printf(“%8.2f”, list[i]);
deviation = sd(list, n);
printf(“\n Standard Deviation is: %10.5f\n”, devia-
tion);
}
/* function to compute standard deviation */
Arrays and Pointers • 261
float sd(x, m)
float x[20];
int m;
{
int i;
float mean, dev, sum = 0.0;
float avg ( ); /* function declaration */
mean = avg(x, m);
printf(“\n\n Mean of %3d elements is:%10.2f\n”, m,
mean);
for(i=0; i<m; i++)
sum = sum + (mean – x[i]) * (mean – x[i]);
dev = sqrt(sum/(float) m);
return (dev);
}
/* function to compute mean */
float avg(a, n)
float a[20];
int n;
{
int i;
float sum = 0.0;
for (i=0; i<n ; i++)
sum += a[i];
return (sum / (float) n);
}
OUTPUT (after running):
Calculating standard deviation of a … list of numbers.
Enter size of the list: 5
Enter 5 elements: 12.34 56.00 78.90 34.00 78.45
Mean of 5 elements is: 51.94
Standard deviation is: 25.83064
Example 25: Write a C program to reverse n characters using recursion.
Solution 25: The program is as follows:
#include<stdio.h>
#include<math.h>
main( )
{
262 • C Programming
int n;
void rev( );
printf(“Enter the number of characters to be re-
versed:”);
scanf(“%d”, &n);
printf(“%d”, n);
printf(“\n”);
rev (n);
printf(“\n”);
}
void rev(n)
int n;
{
char c;
if (n = = 1)
{
c= getchar( );
c= getchar( );
putchar ( c );
}
else
{
c= getchar( );
c = getchar( );
rev ( - - n);
putchar ( c );
}
return;
}
OUTPUT (after running):
Enter the number of characters to be reversed: 5
rajiv
vijar
Example 26: Write a C program to implement a binary search using
recursion.
Solution 26: The program is as follows:
#include<stdio.h>
int key; /* global variable */
main( )
Arrays and Pointers • 263
{
int a[50], I, n, loc;
int bin( );
printf(“\n\t Enter the array size:”);
scanf(“%d”, &n);
printf(“%d\n”, n);
printf(“\n\t Please enter the array elements in ascending
order:”);
for (i=0; i<n; i++)
scanf(“%d”, &a[i]);
for (i=0; i<n; i++)
printf(“%d”, a[i]);
printf(“\n”);
printf(“Enter the element to be searched:”);
scanf(“%d”, &key);
printf(“%d”, key);
loc = bin (a, 0, n);
printf(“\n\n”);
if (loc = = 0)
printf(“Unsuccessful search. %d not found \n”,
key);
else
{
printf(“Successful search\n”);
printf(“%d found at position %d. \n”, key, loc);
}
}
/* recursive binary search method */
int bin (b, low, high)
int b[5], low, high;
{
static int mid;
int i;
if (low <= high)
{
mid = (low + high)/2;
if (key < b[mid]) {
/* element in the lower half */
high = mid – 1;
bin (b, low, high);
}
else if (key > b[mid]) {
264 • C Programming
item = STACK_EMPTY;
}
return (item);
}
Summary
Arrays and pointers are related to each other. In this chapter, we have studied
1D, 2D, and 3D arrays. We have also seen the purpose of writing functions for
modular programming. Different techniques of parameter passing have been
dealt with. Pointers have been examined in depth using a simpler approach.
Exercises
Q1. Write a C program to find the roots of a given quadratic equation.
Q2. Write a C function to find the GCD and LCM of two numbers.
Q3. Write a function prime that returns 1 if its argument is a prime and returns
0 otherwise.
Q4. Write a C program to check whether the given year is a leap year.
[Hint:
/* testing for leap years using a ‘boolean’ function */
main( )
{
int year;
printf(“Please enter a year:”);
scanf(“%d”, &year);
if (is_leap(year))
printf(“%d is a leap year.\n”, year);
else
printf(“%d is not a leap year. \n”, year);
}
/* ‘Boolean’ function is_leap returns true if year is a
leap year */
is_leap(year)
int year;
{
return (year % 4 = = 0 && year % 100 !=0 || year % 400
= = 0);
}
270 • C Programming
Q5. Write a C function to read the three sides of a triangle and to determine
whether they form a triangle. Also determine the type of triangle they
form. You should return true if the triangle is formed and false otherwise.
Q6. The area of a triangle can be computed using Heron’s formula, which de-
fines the semi-perimeter ‘s’ as half of the sum of the sides of the triangle.
The area of the triangle is given by the formula:
Area = the square root of (s(s-a)(s-b)(s-c))
where a, b, and c are the sides of the triangle. Write a function which,
when passed the sides of a triangle, returns the area using Heron’s formula.
The function should first make sure that the triangle is valid; if it is not, the
function can return zero or a negative value as an error indicator. Use the
sqrt( ) function that is inbuilt in the math library.
Q7. Write a C program to reverse an array using a single array ‘a’ only.
[Hint:
for(I = ARRAY_SIZE – 1; i>=0; i- - )
printf(“%d”, array[i]);
printf(“\n”);
]
Q8. Write a simple bubble sort function.
[Hint:
void sort (int a[ ] , int n)
{
int i, j, temp;
for (i =0; i < n -1; ++i)
for (j = i +1; j <n; ++j)
if ( a[i] > a[j])
{
temp = a[i];
a[i] = a[j];
a[j] = temp;
}
}
In the main( ) function, you can just call sort(array, 10);].
Q9. Write a simple function to find the GCD of two numbers, u and v.
[Hint:
int gcd (int , int v)
{
Arrays and Pointers • 271
int temp;
while ( v!= 0) {
temp = u % v;
u = v;
v = temp;
}
return u;
} ].
Q10. Now modify the module in Q9 above to find the LCM of these two
numbers, u and v.
[Hint:
Use formula: lcm (u, v) = uv / gcd (u, v) where u, v >= 0. ]
Q11. Write a function called substring( ) to extract a portion of a character
string. The function should be called as follows:
substring (source, start, count, result);
where source is the character string from which you are extracting the
substring, start is an index number into source indicating the first char-
acter of the substring, count is the number of characters to be extracted
from the source string, and result is an array of characters that is to
contain the extracted substring. For example,
substring(“character”, 4, 3, result);
extracts the substring “act” (3 characters starting with character num-
ber 4) from the string “character” and places the result in result.
Q12. Write a C program to insert an element into an existing array.
[Hint:
#include<stdio.h>
#include<conio.h>
void main( )
{
int i, element, loc, n, a[10];
clrscr( );
printf(“\n Enter number of elements:”);
scanf(“%d”, &n);
printf(“\t Enter elements:”);
for (i=0; i<n; i++)
scanf(“%d”, &a[i]);
printf(“\n Enter element to insert:”);
scanf(“%d”, &element);
272 • C Programming
Q20. Write a function that receives 5 integers and returns their sum, average,
and standard deviation. Call this function from the main( ) and print the
results in main.
Q21. Write a program to generate prime numbers from 1 to 1000 using ar-
rays.
Q22. Demonstrate call by value and call by reference with suitable example
programs.
Q23. Discuss all string functions and explain with example programs.
Q24. Demonstrate the relationship between arrays and pointers with suit-
able programs.
Q25. Which is generally more efficient—recursion or iteration? Why?
Q26. Write a C program to find if a square matrix is symmetric. Note that a
square matrix is symmetric if it is equal to its transpose.
Q27. Under what conditions can one pointer to a variable be subtracted from
another? How will this difference be interpreted?
Q28. Give the output:
int a=10, b=8, c;
c = a++ + b + a++;
printf(“%d”, c);
c = ++a + b + ++c;
printf(“%d”, c);
[Hint: 30 50].
Q29. Write a C program to input an array of 10 characters and find the num-
ber of duplicate characters, if any.
[Hint:
#include<stdio.h>
int x, c=0;
printf(“\n\n Enter characters…”);
for (x=0; x<10; x++)
{
scanf(“%c”, &ch[x]);
}
274 • C Programming
4
Structures and Unions
4.0 INTRODUCTION
W
e have seen that an array is a collection of similar (homogeneous)
data items. But C also provides two more user-defined data types—
structures and unions. They are called user-defined data types as
users define them as per their needs. We define structure as a collection
of heterogeneous (dissimilar) elements that are stored contiguously in
memory. Understand that a structure is a collection of a fixed num-
ber of elements that are accessed by name, not by index (as arrays are
done). The elements of a structure may be of different data types.
Say we want to store a current date—let’s call it March 24, 2016—in a pro-
gram. We take three different variables to store 24 (day), 03 (month), and 2016
(year). Now say again we want to store a date of purchase; again we need three
variables—say, date_of_purchase, month_of_purchase, and year_of_purchase.
This means we now need another set of three variables. This consumes a lot of
memory. Structures are helpful here. Thus, we can declare a structure of date
as follows:
struct date
{
int month;
int day;
int year;
};
276 • C Programming
For example,
struct Emp
{
char fname[40], lname[40];
int age;
float basic_salary;
char address[80];
};
Here, Emp is a new user-defined structure data type.
Please note that a structure declaration does not reserve any space
for memory because a structure declaration is just a data type, like an
int, a float, or a char. Memory is allocated only when a variable of the
corresponding structure type is declared. A structure variable is declared
as follows:
Syntax
struct stname stvar;
Here, stvar is a structure variable of the type struct stname.
For example,
struct date today;
We now write a complete program for the date problem:
#include<conio.h>
main( )
{
struct date
{
int month;
int day;
int year;
};
struct date today;
today.month = 03;
today.day = 24;
today.year = 2016;
printf(“Todays date is %d/%d/%d. \n”, today.month, to-
day.day, today.year % 100);
}
278 • C Programming
.month 03
today .day 24
.year 2016
But the problem here is that in such a declaration you cannot subsequently
declare another variable whose type is the same as that of emp, in this case.
So we will access these members as:
emp.fname;
emp.age;
emp.bas_salary;
And once we know this, we can initialize the values of these member vari-
ables as follows:
strcpy(emp.fname, “DR. RAJIV”);
strcpy(emp.lname, “CHOPRA”);
emp.age = 41;
emp.salary = 82000.00;
strcpy(emp.address, “GTB NAGAR”);
Array of Structures
When we want to store a large number of similar records—say, of 100 employ-
ees—then an array of structures is defined as follows:
struct Emp
{
char fname[40], lname[40];
int age;
float salary;
char address[30], dept[30];
};
struct Emp emp1[100]; /* declaring array of structures */
This means that emp1 is an array having 100 elements of type struct Em-
ployee. It is after this statement only that the C compiler reserves memory space
for 100 structures; the same rule applies for array of structures as for array of
primary data types like ints, floats, or chars.
Structures and Unions • 283
emp[2].fname
emp[2].lname
emp[2].age
emp[2].salary
emp[2].address
emp[2].dept
emp1[0].salary;
emp1[0].address;
emp1[0].dept;
Similarly, the 2nd employee record is referred to as:
emp1[1].fname;
emp1[1].lname;
emp1[1].age;
emp1[1].salary;
emp1[1].address;
emp1[1].dept;
And the 100th employee record is referred to as:
emp1[99].fname;
emp1[99].lname;
emp1[99].age;
emp1[99].salary;
emp1[99].address;
emp1[99].dept;
There is another way of showing this structure:
struct Emp
{
char fname[40], lname[40];
int age;
float salary;
char address[30], dept[30];
};
struct Emp emp1[100]; /* declaring array of struc-
tures */
Structures and Unions • 285
Rajiv
.fname
Chopra
.lname
.age 40
emp1[0]
82000.00
.salary
GTB Nagar
.address
Ajay 30 67000.00
Amit 30 70000.00
Mayur 20 6700.00
Adi 30 50000.00
You have entered these records
Rajiv: 40: 82000.00
Ajay: 30: 67000.00
Amit: 30: 70000.00
Mayur: 20: 6700.00
Adi: 30: 50000.00
Note the following statement in this program:
float x, *y = &x, x= *y;
If this statement is not present, you will get an error message:
scanf: floating point formats not linked.
Abnormal program termination.
Explanation: This error is due to the floating point emulator. A floating
point emulator is used to manipulate floating point numbers in runtime
library functions like scanf( ) and atof( ). There are some cases, such as ar-
rays of structures, where float is a structure member and the reference to the
float is a bit obscure; that’s why the compiler does not detect the need for the
emulator. To overcome this limitation, a reference to the address of a float is
made. When the compiler encounters an address of a float, it automatically sets
a flag to have linker link in the floating point emulator. That is why these state-
ments force the linking of the floating point emulator into a program. Thus, to
prevent this error, include the statement in the beginning of your programs.
Nesting Structures
It is possible to nest one structure within another. Such structures are known as
nested structures.
For example,
struct date
{
288 • C Programming
int day;
int month;
int year;
};
struct Emp
{
char fname[40], lname[40];
int age;
float salary;
struct date dob;
struct date dobj;
char address[30], dept[30];
};
Note the restriction in a nested structure shown by the next example:
struct Emp
{
char name[40];
int age;
float salary;
struct Emp e; /* is illegal */
};
Thus, a member of a structure can also be another structure. That is, you
can say that the individual structure members of a structure can be other struc-
tures as well. Structures whose members are themselves structures are
called nested or hierarchical structures.
For example, say we want to nest a structure named address inside an-
other structure Employee; there are two ways of declaring such a nested struc-
ture:
I. First method:
struct date
{
int day;
int month;
int year;
};
struct Emp
Structures and Unions • 289
{
char fname[40], lname[40];
int age;
float salary;
struct date dob;
struct date dobj;
char address[30], dept[30];
};
While using this notation, remember that the embedded structure type
(date) should be declared before its use within the containing structure; other-
wise, the compiler will not recognize it.
In this example, the structure date is used in the structure Emp. A par-
ticular member inside the structure can be accessed by repeatedly ap-
plying the dot (.) operator.
For example, in this statement,
emp.dob.day = 5;
we set the day variable in the dob structure within emp to 5. Similarly,
other members of a nested structure are accessed as follows:
emp.dob.month = 3;
emp.dob.year = 2016;
Also we can display the members of a nested structure as follows:
printf(“%d”, emp.dob.day);
printf(“%d”, emp.dob.month);
printf(“%d”, emp.dob.year);
Note that this level of nesting can go up to any level. There is no
limit. Also note that a structure cannot be nested within itself.
For example,
struct Emp
{
char name[40];
int age;
float salary;
struct Emp e; /* is illegal */
};
But it is possible to have a structure pointer of its own type as its structure
member.
For example,
struct Emp
{
char name[40];
int age;
float salary;
struct Emp*e; /* is illegal */
};
Structures and Unions • 291
a_month.name[1] = ‘a’;
a_month.name[2] = ‘n’;
Or we can initialize this variable to the same values with the following state-
ment:
static struct month a_month = {31, { ‘J’, ‘a’, ‘n’ } };
And we can set up 12-month structures inside an array to represent each
month of the year:
struct month months[12];
Let us now write a program to show the concept of structures and arrays:
/* Program to set up initial values inside the array and display them */
/* It illustrates the structures and arrays concept */
struct month
{
int number_of_days;
char name[3];
};
main( )
{
int i;
static struct month months[12] =
{ { 31, {‘J’, ‘A’, ‘N’ } }, {28, {‘F’, ‘E’, ‘B’ } },
{ { 31, {‘M’, ‘A’, ‘R’ } }, {30, {‘A’, ‘P’, ‘R’ } },
{ { 31, {‘M’, ‘A’, ‘Y’ } }, {30, {‘J’, ‘U’, ‘N’ } },
{ { 31, {‘J’, ‘U’, ‘L’ } }, {31, {‘A’, ‘U’, ‘G’ } },
{ { 30, {‘S’, ‘E’, ‘P’ } }, {31, {‘O’, ‘C’, ‘T’ } },
{ { 30, {‘N’, ‘O’, ‘V’ } }, {31, {‘D’, ‘E’, ‘C’ } }
};
printf(“Month Number of Days\n”);
printf(“-------- ---------------------\n”);
for(i=0; i<12; ++i)
printf(“ %c%c%c %d\n”,
months[i].name[0], months[i].name[1],
months[i].name[2], months[i].number_of_days);
}
Structures and Unions • 295
31
.number_of_days
[0] ‘J’
[2] ‘N’
28
‘F’
296 • C Programming
It is crystal clear from the figure that months[0] refers to the entire
month structure contained in the first location of the months array. This
expression is of type struct month. So, when passing months[0] to a function
as an argument, the corresponding formal parameter inside the function must
be declared to be of type struct month. Then the expression:
months[0].number_of_days
refers to the number_of_days member of the month structure contained
in months[0]. The type of this expression is int. The expression:
months[0].name
references the 3-character array called name inside the month structure
of months[0]. If passing this expression as an argument to a function, then the
corresponding formal parameter would be declared to be an array of type char.
Finally, the expression
months[0].name[0]
references the first character of the name array contained in months[0]
(the character ‘J’).
Like structures, unions are user-defined data types. A union is a data type
that allows different types of variables to share the same space in mem-
ory. Unlike structures where each member has its own memory space, unions
allow sharing of space among its members in memory.
Syntax
union unname
{
datatype-1 ListOfVariables;
datatype-2 ListOfVariables;
………………
datatype-n ListOfVariables;
};
Here, union is a keyword and uname is the name of the union data type.
A union variable is declared as a structure variable is declared. When a union
Structures and Unions • 297
data type can be defined for a finite set of values in the type specifier. Also
remember that C does not provide facilities for reading and displaying values of
enumeration types. They may only be read or displayed as integer values.
We are in a position to write some programs now.
Example 1: Write a C program to read a student’s record and find his
grade percentage. It should also assign the grade according to the rules
given below:
Percentage marks Grade
>=80 A
>=60 < 80 B
>=50 < 60 C
< 50 D
Solution 1: The program is as follows:
#include<stdio.h>
#include<conio.h>
void main( )
{
struct student
{
char name[30];
int roll;
int sub1, sub2, sub3, sub4;
float per;
}s1;
clrscr( );
printf(“\n \t Enter the record of the student”);
printf(“\n\t Name:”);
gets(s1.name);
printf(“\n\t Roll No. :”);
scanf(“%d”, &s1.roll);
printf(“\n\t Subject 1:”);
scanf(“%d”, &s1.sub1);
printf(“\n\t Subject 2:”);
scanf(“%d”, &s1.sub2);
printf(“\n\t Subject 3:”);
scanf(“%d”, &s1.sub3);
printf(“\n\t Subject 4:”);
Structures and Unions • 303
scanf(“%d”, &s1.sub4);
s1.per = (s1.sub1 + s1.sub2 + s1.sub3 + s1.sub4) / 4.0;
if (s1.per >= 80)
printf(“\n A grade with %f per”, s1.per);
else
if(s1.per >= 60)
printf(“\n B Grade with %f per”, s1.per);
else
if(s1.per >=50)
printf(“\nC Grade with %f per”, s1.per);
else
printf(“\n D Grade with %f per”, s1.per);
getch( );
}
Example 2: Modify the preceding C program to read n number of stu-
dents and calculate their percentages using an array of structures.
Solution 2: The program is as follows:
#include<stdio.h>
#include<conio.h>
void main( )
{
struct student
{
char name[30];
int roll;
int sub1, sub2, sub3, sub4;
float per;
}list[20];
int i, n;
clrscr( );
printf(“\n \t Enter the value of n (total students):
“);
scanf(%d”, &n);
printf(“\n Enter data of %d students”, n);
for(i=0; i<n; i++)
{
printf(\n Enter name, roll no, marks in 4 subjects
of %d student \n”, i+1);
fflush(stdin);
gets(list[i].name);
scanf(“%d%d%d%d%d”, &list[i].roll, &list[i].sub1,
304 • C Programming
&list[i].sub2, &list[i].sub3,
&list[i].sub4);
list[i].per = (list[i].sub1 + list[i].sub2 + list[i].
sub3 + list[i].sub4) / 4.0;
}
printf(“\n Print the data of %d students”, n);
for (i=0;i<n; i++)
printf(“\n%s\t%d\t%f\n”, list[i].name, list[i].roll,
list[i].per);
getch( );
}
Example 3: Write the steps to implement a self-referential structure—a
linked structure.
Solution 3: When a member of a structure is declared as a pointer to the
structure itself, then the structure is called a self-referential structure.
For example,
struct link
{
int data;
struct link *p;
};
This means that the structure link consists of two members: data and p.
The member data is a variable of type int whereas the member p is a pointer
to a structure of type link. Thus, the structure link has a member that can
point to a structure of type link. This type of self-referential structure can be
shown as follows:
Data p A B
link
Since the pointer p can point to a structure variable of type link, we can
connect two such structure variables, A and B, to obtain a linked structure as
shown above. This linked structure can be obtained by the following procedure:
S1: Declare structure-link.
S2: Declare variable A and B of type link.
S3: Assign the address of structure B to member p of structure A.
Structures and Unions • 305
70 80 NULL
data data
Structure Union
1. Structures are used to store differ- 1. A union is used to store different
ent members at different places in members at the same memory loca-
memory. tion.
2. They are not used to conserve 2. They are used to conserve memory.
memory.
3. Total memory used is equal to the 3. Total memory assigned is equal to the
sum of the sizes of its individual ele- maximum/largest of all of the sizes of
ments/members. its members.
4. The keyword struct is used. 4. The keyword union is used.
5. Syntax: 5. Syntax:
struct <name> union <name>
{ {
member-1; member-1;
member-2; member-2;
……… ………
member-n; member-n;
}; };
(a) Packing several objects into a machine word like 1-bit flags can be
compacted—symbol tables in compilers.
Structures and Unions • 311
• Some bit fields are stored left to right while others are stored
from right to left in memory.
7. The solution to the portability problem is to use bit shifting and masking
to get the same results, although this is not very easy.
Summary
In this chapter, we have studied about structures and unions in C. Both have
their own advantages, disadvantages, and applications. We have also discussed
the linked structure known as a self-referential structure, which is used in
the creation of linked lists and tree data structures. Also, we compared arrays
with structures and unions. Bit fields were also discussed. Using structures sev-
eral complex problems have been solved.
Structures and Unions • 313
Exercises
Q1. (a) Create a structure declaration for an employee of an organization con-
sisting of the following fields:
employee code, name, department, date of birth, date of hiring, basic salary
Write a program to print details of the employee, whose basic salary is
greater than $20,000.
(b) Write short notes on union data types and enumerable data types.
Q2. Write down the declarative statement that creates a structure consisting of
the following information about books in the store:
Book-Id 4 characters
Book-Name 20 characters
Book-Price real number
Num-copies positive integer
How much memory is needed by this structure? Create two variables, b1
and b2, of this structure type. Write down a statement in C to calculate the
sum of books processed, represented by b1 and b2.
[Hint:
struct Book
{
char book-id [4];
char book-name[20];
float book-price;
unsigned int num_copies;
} b1, b2;
Total memory required by the structure: 30 bytes (i.e., 4 + 20 + 4 + 2 bytes =
30 bytes).
The statements in C are:
struct book b1, b2;
flat sum;
sum = b1.num_copies * b1.book-price + b2.num_copies * b2.book-price;].
Q3. Explain structure and union.
314 • C Programming
Q4. (a) Explain briefly the difference between a structure and a union and pro-
vide an example.
(b) How does a structure differ from an array? Write a C program to imple-
ment an array of structures.
Q5. What is the difference between a structure and a union?
Q6. Differentiate between structure and union in C. Write a C program to
store student details using union.
Q7. Explain how a structure can be passed to a function?
Q8. Write a C program to read n records with names and addresses and sort them.
[Hint:
#include<stdio.h>
#include<conio.h>
struct list
{
char name[12];
char add[50];
};
void main( )
{
struct list1[10], t;
int i, n;
clrscr( );
printf(\n Enter the number of records to arrange:”);
scanf(“%d”, &n);
printf(“\n Enter %d names and addresses”, n);
for (i=0; i < n; i++)
{
fflush(stdin);
printf(“\n Enter %d name”, i+1);
gets( l[i].name);
printf(“\n Enter %d address”, i+1);
gets( l[i].add);
}
for (i=0; i < n; i++)
{
for (j = i+1; j < n; j++)
{
if ((strcmp (l[i].name, l[j].name) > 0))
Structures and Unions • 315
{
t = l[i];
l[i] = l[j];
l[j] = t;
}
}
}
printf (“\n Sorted list is: \n”);
for (i =0; i<n; i++)
printf(“\n %s\t %s”, l[i].name, l[i].add);
getch( );
} ].
CHAPTER
5
File Handling in C
5.0 INTRODUCTION
F
iles have long been used for storing data. Files are traditional data struc-
tures. They are useful for sequential operations like reading from or writ-
ing to a file. You need to create a file, open it, write to it, and finally close
the file. You can also read from a file. When the data of a file is stored in the
form of readable and printable characters, the file is called a text file. On the
other hand, if a file contains nonreadable characters in binary code, the file is
called a binary file. For example, the program files that are created by an edi-
tor are stored as text files whereas executed files generated by a compiler are
stored as binary files.
First, we have to open a file. As we open a file a link is established between the
program and the OS. Thus, the OS now comes to know the name of the file,
the data structure, and the mode in which the file is to be opened (reading or
writing; text mode or binary mode). The filename can have any extension like
.docx, .xlsx, .txt, and so on. Note that the data structure of a file is defined
as FILE, which is present in the <stdio.h> header file.
Syntax (of declaring a file pointer)
FILE *fp;
318 • C Programming
where FILE is the data structure included in stdio.h and fp is a file pointer
which points to the start of the file.
Syntax (of opening a file)
fp = fopen (“filename”, “mode”);
where fp is a pointer to a structure of FILE type. fopen( ) is a library func-
tion having two arguments; one is the filename and the other is the mode in
which we want to open the file. It is defined in stdio.h and returns a pointer
known as a file pointer to the FILE structure for the specified file, which we
store in a pointer variable fp. Table 5.1 lists the different file-opening modes:
Table 5.1: File-Opening Modes
Mode Purpose
r Opens a text file for reading. If the file exists, it sets up a pointer
that points to the first character in it, else it returns NULL.
w Opens a text file for writing. If the file exists, its contents are
overwritten, else a new file is created with a pointer pointing to
the first position.
a Opens a text file for adding data at the end of an already existing
file. If the file does not exist, a new file is created with a pointer
pointing to the first character, else data is added at end.
r+ Opens a text file for both reading and writing. Possible opera-
tions are reading existing contents, writing new contents, and
modifying existing contents. Returns NULL if file does not exist.
w+ Opens a text file for both reading and writing. Possible opera-
tions are writing new content or reading and modifying existing
content. If file does not exist, it will be created for update.
a+ Opens a text file for both reading and appending. Possible op-
erations are reading existing contents and adding new contents
at the end of file; it cannot modify existing contents. If file does
not exist, it will be created.
rb, wb, ab, rb+, Binary file versions of the preceding modes, each with the same
wb+, ab+ characteristics as its respective text file mode.
For example,
fp = fopen (“text.dat”,”w”);
The OS will now open the file text.dat and prepare it for writing.
File Handling in C • 319
Just as we can read and write data from the keyboard using getchar( ) and
putchar( ) functions, we can read or write one character at a time using charac-
ter I/O functions.
Writing to a File
Before writing to a file we must open it in write mode.
Syntax
fputc (ch, fp);
where ch is a character variable or constant and fp is a file pointer.
Reading Data from a File
The data that is written into a file can also be read from the same file using the
fgetc( ) function.
Syntax
ch = fgetc(fp);
where ch is a character variable and fp is a file pointer.
The fgetc( ) function is used to read one character at a time from a file to
which fp is pointing. It gives either the read character or the end-of-file (EOF)
File Handling in C • 321
character if EOF is reached. Please note here that EOF is also present in
the <stdio.h> file.
It is also possible to read or write data more easily in the form of strings.
Writing to a File
We can write data into a file in the form of strings. We use the fputs( ) function
for this.
Syntax
fputs (s, fp);
where s is a string constant or variable and fp is a file pointer. This function
is used to put or write data into a file as compared to the puts( ) function, which
is used to write data onto the screen.
Reading Data from a File
The data that is written into a file in the form of strings can also be read by using
the fgets( ) function.
Syntax
fgets (s, n, fp);
where s is string, n is the maximum length of the input string, and fp is the
file pointer.
This function reads a string at a time; if it reads the EOF character, it will
return a NULL value.
Syntax
putw (n, fp);
where n is an integer constant or variable to be written into a file and fp
is a file pointer.
Reading Data from a File
For reading data from file, use the getw( ) function:
Syntax
getw (fp);
This function returns an EOF character when an EOF is encountered.
Formatted I/O functions are used to read or write any type of data (char, int,
float, string, etc.) from a file. These functions behave like console I/O func-
tions—scanf( ) and printf( ). The only difference is that the formatted I/O func-
tions are used for files now.
Writing Data to a File
For writing formatted output from a file, we use the fprintf( ) function:
Syntax
fprintf(fp, “format string”, list);
where fp is a file pointer; format strings are %c for char, %d for int, or %f
for float; and list is the number of variables to be written to a file.
Reading Data from a File
For reading formatted data from a file, we use the fscanf( ) function:
Syntax
fscanf(fp, “format string”, list);
where list is the list of addresses where the values are to be stored.
File Handling in C • 323
{
FILE *fp;
char ch;
clrscr( );
fp = fopen(“test1.dat”, “w”);
if (fp = = NULL)
{
printf(“\n Cannot open file”);
exit(1);
}
printf(“\n Type a line of text and press Enter key
\n”);
while (( ch = getche( ) ) != ‘\r’)
fputc(ch, fp);
fclose (fp);
}
OUTPUT (after running):
Type a line of text and press Enter key
I am Dr. Rajiv Chopra
/* now reading data from the file */
#include<stdio.h>
#include<conio.h>
void main( )
{
FILE *fp;
char ch;
clrscr( );
if ((fp = fopen(“test1.dat”, “r”)) = =NULL)
{
printf(“\n Cannot open file”);
exit(1);
}
while ((ch = fgetc (fp)) != EOF)
putchar(ch);
fclose(fp);
getch( );
}
OUTPUT (after running):
I am Dr. Rajiv Chopra
File Handling in C • 325
If you have to read and write strings rather than characters (as shown
NOTE above), we use the fputs( ) and puts( ) functions.
clrscr( );
if ((fp = fopen(“test4.dat”, “w”)) = =NULL)
{
printf(“\n Cannot open file”);
exit(1);
}
while (ch = =’y’)
{
printf(“\n Enter name, age and salary:”);
scanf(“%s%d%f”, name, &age, &salary);
fprintf(fp, “%s\t/%d\t%f\n”, name, age,
salary);
printf(“\n More records (y/n)?”);
ch = tolower (getche( ));
}
fclose (fp);
}
OUTPUT (after running):
Enter name, age and salary: Rajiv 41 82000.00
More records (y/n)? y
Enter name, age and salary: Ajay 52 52000.00
More records (y/n)? y
Solution 3(b):
#include<stdio.h>
#include<conio.h>
void main( )
{
FILE *fp;
char name[30];
int age;
float salary;
clrscr( );
if ((fp = fopen(“test4.dat”, “r”)) = =NULL)
{
printf(“\n Cannot open file”);
exit(1);
}
while ( fscanf(fp, “%s%d%f”, name, &age, &salary)!=
EOF)
328 • C Programming
44
55
66
77
88
Solution 4(b):
#include<stdio.h>
#include<conio.h>
void main( )
{
struct
{
char name[30];
int age;
float sal;
} emp;
FILE * fp;
char ch = ‘y’;
if ((fp = fopen(“test.dat”, “wb”)) = =NULL)
{
printf(“\n Cannot open file”);
exit(1);
}
while (ch = = ‘y’)
{
printf(“\n Enter name, age and salary:”);
scanf(“ %s %d %f”, emp.name, &emp.age, &emp.
sal);
fwrite(&emp, sizeof(emp), 1, fp);
printf(“\n More records (y/n)?”);
ch = tolower (getche( ));
}
fclose(fp);
}
OUTPUT (after running):
Enter name, age and salary: Rajiv 41 82000.00
More records (y/n)? y
330 • C Programming
char ch;
int c=0, s=0, t=0, l=0;
if ((fp = fopen(“file1.dat”, “r”)) = =NULL)
{
printf(“\n Cannot open file”);
exit(1);
}
while (1)
{
ch = fgetc (fp);
if ( ch = =EOF)
break;
c++;
if ( ch = =’ ‘ )
s++;
if ( ch = =’\t‘ )
t++;
if ( ch = =’\n‘ )
l++;
}
fclose(fp);
printf(“\n Number of characters = %d”, c);
printf(“\n Number of blank spaces = %d”,
s);
printf(“\n Number of tabs = %d”, t);
printf(“\n Number of lines = %d”, l);
getch( );
}
Example 6: Write a C program to copy the content of one file into an-
other file on a character-by-character basis.
Solution 6: The following is the file copy program (i.e., from source file to
destination file):
#include<stdio.h>
#include<conio.h>
void main( )
{
FILE *fp, *ft;
char ch;
clrscr( );
if ((fp = fopen(“file1.dat”, “r”)) = =NULL)
{
332 • C Programming
{
printf(“\n Numbers in the 2 files should be in as-
cending order\n”);
printf(“Terminate entry of each file ctrl-d (EOF)
\n”);
printf(“\n Input numbers for file %s\n”, argv[1]);
fp1 = fopen (argv[1], “w”);
while ((scanf (“%d”, &i)) != EOF)
{
putw (i, fp1);
c1++;
}
fclose (fp1);
/* Displaying contents of file-1 */
printf(“\n List of %d numbers in file %s \n\n”, c1,
argv[1]);
fp1 = fopen (argv[1], “r”);
while ((i = getw (fp1) != EOF)
printf (“%5d”, i);
fclose (fp1);
printf(“\n”);
printf(“\n Input numbers for file %s\n”, argv[2]);
fp2 = fopen (argv[2], “w”);
while ((scanf (“%d”, &i)) != EOF)
{
putw (i, fp2);
c2++;
}
fclose (fp2);
/* Displaying contents of file-2 */
printf(“\n List of %d numbers in file %s \n\n”, c2,
argv[2]);
fp2 = fopen (argv[2], “r”);
while ((j = getw (fp2) != EOF)
printf (“%5d”, j);
fclose (fp2);
printf(“\n”);
c3 = c1 + c2;
i =0;
j =0;
334 • C Programming
/* simple merge-sort */
fp1 = fopen (argv[1], “r”);
fp2 = fopen (argv[2], “r”);
fp3 = fopen (argv[3], “w”);
n1 = getw (fp1);
n2 = getw (fp2);
while ((i != c1) && (j!= c2))
{
if (n1 < n2)
{
putw (n1, fp3);
n1 = getw (fp1);
i++;
}
else {
if (n1 > n2)
{
putw (n2, fp3);
n2 = getw (fp2);
j++;
}
else {
putw (n1, fp3);
n1 = getw (fp1);
n2 = getw (fp2);
i++;
j++;
dup++;
}
}
}
if ( i = = c1) {
do {
putw (n2, fp3);
} while ((n2 = getw (fp2)) != EOF);
}
else {
do {
putw (n1, fp3);
} while ((n1 = getw (fp1)) != EOF);
}
fclose(fp1);
File Handling in C • 335
fclose(fp2);
fclose(fp3);
printf(“\n\n List of %d numbers in file %s\n”, c3 –
dup, argv[3]);
printf(“After simple merge sort: \n\n”);
fp3 = fopen (argv[3], “r”);
while ((k = getw (fp3)) != EOF)
printf(“%5d”, k);
fclose(fp3);
printf(“\n”);
}
}
OUTPUT (after running):
Numbers in the 2 files should be in ascending order
Terminate entry of each file with ctrl-d (EOF)
Input numbers for file f1
List of 7 numbers in file f1
1 3 5 7 9 11 13
Input numbers for file f2
List of 9 numbers in file f2
2 4 6 8 10 12 14 16 18
List of 16 numbers in file f3
After simple merge sort:
1 2 3 4 5 6 7 8 9 10
11 12 13 14 16 18
Example 8: In the following code
#include<stdio.h>
main( )
{
FILE *fp;
fp = fopen(“trial”, “r”);
}
336 • C Programming
fp points to
Solution 12: n = 5
Example 13: Write a C program that reads a text file and displays the
number of vowels, consonants, words, and lines in the file.
Solution 13: The program is as follows:
#include<stdio.h>
#include<conio.h>
main( )
{
int vowel = 0, words =0, cons = 0, line = 0;
FILE *F1;
char a, *name;
printf(“\n enter the name of file”);
scanf(“%s”, name);
f1 = fopen (name, “r”);
while (( a = fgetc(F1)) != EOF)
{
if (toupper(a) = =’A’ || toupper(a) = =’E’ ||
toupper(a) = =’I’ || toupper(a) =
=’O’ || toupper(a) = =’U’ )
{
vowel ++;
}
else
{
cons++;
if (a = =’ ‘ || a = = ‘.’)
{
words++;
}
if (a = =’\n’)
{
line++;
}
}
}
fclose(f1);
printf(“\n Number of vowels are = %d”, vowels);
printf(“\n Number of consonants are = %d”, cons);
printf(“\n Number of words are = %d”, words);
printf(“\n Number of lines are = %d”, line);
338 • C Programming
getch( );
}
Example 14: Write short notes on random access files.
Solution 14: In random access files, it may be possible to access a particular
data item from any position in the file. There is a restriction for random access-
ing—all data items must be of the same size or record length must be fixed. In
the case of random access, the file pointer is used. By controlling the position
of the file pointer, random access of a file can be made possible. Here, random
means that data can be read from or written to any position in a file without
reading or writing all of the preceding data. For random access to files of re-
cords, the following functions are used:
Summary
Despite the popularity of databases today, the concept of files still exists. This
is because files perform certain tasks that are best done using that format, like
sequential processing of records. Files are used for storing information that can
be processed by programs. All data and programs are stored in files. Even the
editor you use, like tc editor or tc++ editor, uses and works on files only. Even
when you are sending attachments in an email, these are files that are attached
and sent.
Exercises
Q1. Write a C program that compares the contents of two files and issues the
following messages:
File 1 and file 2 are identical.
Files are the same.
File 1 and file 2 are different at line number = …
Files are different.
Names of the files are taken to be command line arguments.
File Handling in C • 339
Q3. What are command line arguments? Why do we use them? How are they
passed to main? Discuss with suitable examples.
Q4. Write a C program to read and display the last few characters of a file.
Read the name of the file and number of characters from the keyboard.
Q5. How do you print the contents of a file on the printer?
[Hint:
fputc (ch, stdprn);
where ch is the character we want to print and stdprn is the
standard printer instead of using fp (i.e., file pointer)]
Q6. What functionality is given by files? Showcase the use of sequential files
and their implementation in detail with the help of suitable C program-
ming codes.
340 • C Programming
Q7. A file contains student records with the following data: roll number, name,
and marks in four subjects. Write a C program that reads the records in the
file and outputs a list showing the roll numbers of students whose marks
exceed 40% in each of the four subjects.
Q8. In the context of C programming, explain the different file opening modes.
Q9. Write a C program to read records, arrange them in ascending order, and
write them to a target file.
APPENDICES
Appendix A: C Programming
Lab Projects
1. Write a C program to find the roots of a given quadratic equation
using:
(a) If-then-else statements.
(b) Switch statements.
2. Write a C program to find the GCD and LCM of two integers.
3. Write a C program to reverse a given number and check whether it is a
palindrome. Output the given number with a suitable message.
4. Write a C program to evaluate the given polynomial f(x) = a4x4 + a3x3 +
a2x2 + a1x + a0 for a given value of x and the coefficients using Horner’s
method.
5. Write a C program to copy its input to its output, replacing each string
of one or more blanks by a single blank.
6. Write a C program to read n integer numbers in ascending order into
a single-dimensional array and then to perform a binary search for a
given key integer number and report success or failure in the form of a
suitable message.
7. Write a C program to implement the bubble sort technique on a sin-
gle-dimensional array. Display your arrays properly.
8. Write a C program to find out the average word length on the host
machine.
9. Write a C program to compute the approximate value of exp(0.5) using
the Taylor series expansion for the exponential function.
342 • Appendices
Functions Use
strlen( ) finds the length of string
strlwr( ) converts a string to lowercase
strupr( ) converts a string to uppercase
strcat( ) appends one string at the end of another
strncat appends first n characters of a string at the end of another
string
strcpy( ) copies a string into another
strncpy( ) copies first n characters of one string into another
strcmp( ) compares two strings
strncmp( ) compares first n characters of two strings
strcmpi( ) compares two strings without regard to case
strnicmp( ) compares first n characters of two strings without regard
to case
strdup( ) duplicates a string
strchr( ) finds first occurrence of a given character in a string
strrchr( ) finds last occurrence of a given character in a string
strstr( ) finds first occurrence of a given string in another string
strset( ) sets all characters of a string to a given character
strnset( ) sets first n characters of a string to a given character
strrev( ) reverses a string
References
Const 49 Delimiters 28
Const variables 49 do-while Loop 84–87
Continue Statement 110–111
C programming language E
algorithms and pseudocodes 2–8 Empty statement 112
assembler, linker, and loader 19–22 Enumeration 47–51
auto storage class 119 End-of-file (EOF) 41
block statement 112–118 Extern 121
break Statement 109–110 Extra bit 139
compiler 15–19
continue statement 110–111 F
data input and data output 42–44 Fclose (fp) 319
data types 44–47 Fgets (s, n, fp) 321
definition 1 Fibonacci series 80, 91, 227
do-while Loop 84–87 File pointers 317–320
enumeration 47–51 Files
extern 121 and binary files 339
file handling (see Files) block/record I/O functions 323–338
flowchart 8–14 character input/output 320–321
for loop 87–108 formatted I/O function 322
getchar( ) function 41 integer I/O functions 321–322
global declaration section 39 pointers 317–320
if statement 63–67 string I/O functions 321
ISO/IEC 9899:1990 1 Floyd triangle 106–107
library functions 44 Flowchart
main( ) Function 39–40 and algorithm 12
operators 51–61 definition 8
preprocessor 35–38 notations 11
preprocessor directive/command 22–27 parallelogram 10
putchar( ) function 41–42 symbols 10
register 122–135 Fopen( ) function 319
return statement 111–112 For Loop 87–90
special constant section 38–39 Formal parameters 257
static storage class 119–121 Formatted I/O function 42–44, 322
switch and break 68–73 fprintf( ) function 322
type casting (or coercion) 62 Fputs (s, fp) 321
while Loop 73–84 Functions
definition 215–216
D library/inbuilt functions 215
Debugging phase 18 return Statement 218
Data types user-called functions 218–228
character 45 user-defined functions 215
double precision floating point 45–46 fwrite( ) function 323
floating point 45
integer 45 G
void 46 gcc. 16
Declaration section 23 getchar Function 41, 182
Declare 2d-arrays in C 155 Global declaration 39
#define constants 49 Global variables 50–51
Index • 351