Introduction to C Programming
Introduction to C Programming
Partha Bhowmick
Professor
CSE Department, IIT Kharagpur
http://cse.iitkgp.ac.in/~pb
©Partha Bhowmick
Contents
1 Introduction 5
1.1 Computer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
1.2 Components of a computer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
1.3 Algorithm and flowchart . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
1.4 Computer program . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
1.5 Exercise problems . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 7
3 Conditionals 23
3.1 Solved problems . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24
3.2 Exercise problems . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 30
4 Loops 31
4.1 Syntax of while loop and do-while loop . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31
4.2 Syntax of for loop . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32
4.3 break and continue . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 32
4.4 Nested loops . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 33
4.5 Solved problems . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35
4.6 Exercise problems . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 40
3
4 Contents
5 One-dimensional arrays 41
5.1 What is array? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41
5.2 Why array? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41
5.3 Declaring arrays . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43
5.4 Initializing arrays . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43
5.5 Accessing and working with arrays . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 44
5.6 Solved problems . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45
5.7 Exercise problems . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 49
6 Functions 51
6.1 What is function? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51
6.2 Why function? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51
6.3 Defining a function . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51
6.4 Recursive function . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54
6.5 The return statement . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 54
6.6 Local and global variables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55
6.7 Scope of a variable . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55
6.8 Parameter passing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56
6.8.1 Passing by value . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56
6.8.2 Passing by reference . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56
6.9 Passing an array to a function . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 56
6.10 More on recursion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 57
6.11 Macros (#define) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 58
6.12 #define with arguments . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59
6.13 Extra topics . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61
6.13.1 Generating random input using rand . . . . . . . . . . . . . . . . . . . . . . . . . . . . 61
6.13.2 main() with arguments . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 63
6.14 Solved problems . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 65
6.15 Exercise problems . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 70
©Partha Bhowmick
1 | Introduction
1.1 Computer
Computers have changed our world, making it easier to work, learn, and play. At the heart of every
computer is programming, which tells the computer what to do. Programming turns ideas into instructions
that computers can follow, enabling amazing things in science, medicine, and everyday life. As we dive into
C programming, we will learn the basics that allow these incredible machines to solve problems, run apps,
and power the digital world. Understanding programming is like unlocking a superpower, giving you the
skills to create and innovate with technology.
A computer is a rapidly evolving machine engineered to process data and extract information. The
processing is done according to a given sequence of instructions called a program or code. These programs
enable computers to perform a wide range of computational tasks. More importantly, many of these tasks
are performed at lightning speed—much faster than even the most brilliant minds—such as adding a million
numbers in less than a millisecond!
Monitor Computer
drwxrwxr-x 5 root root 4096 2008-07-23 02:32 kernel
drwxrwxr-x 5 root root 4096 2008-07-23 02:15 lib
drwxrwxr-x 2 root root 4096 2008-07-23 02:15 mm
drwxrwxr-x 41 root root 4096 2008-07-23 02:33 net
drwxrwxr-x 9 root root 4096 2008-07-23 02:12 scripts
drwxrwxr-x 4 root root 4096 2008-07-23 02:15 security
drwxrwxr-x 18 root root 4096 2008-07-23 02:15 sound
drwxrwxr-x 2 root root 56 2008-07-23 02:12 usr
-rw-r--r-- 1 root root 466 2008-07-23 02:33 ..tmp_kallsyms1.o.cmd
-rw-r--r-- 1 root root 466 2008-07-23 02:33 ..tmp_kallsyms2.o.cmd
-rw-r--r-- 1 root root 634 2008-07-23 02:33 ..tmp_vmlinux1.cmd
-rw-r--r-- 1 root root 650 2008-07-23 02:33 ..tmp_vmlinux2.cmd
-rw-r--r-- 1 root root 41410 2008-07-23 02:32 .config
-rw-r--r-- 1 root root 40956 2008-07-23 02:12 .config.old
-rw-rw-r-- 1 root root 572 2008-02-25 17:59 .gitignore
-rw-rw-r-- 1 root root 3657 2008-02-25 17:59 .mailmap
-rw-r--r-- 1 root root 70 2008-07-23 02:32 .missing-syscalls.d
-rw-r--r-- 1 root root 851087 2008-07-23 02:33 .tmp_System.map
-rw-r--r-- 1 root root 1244271 2008-07-23 02:33 .tmp_kallsyms1.S
-rw-r--r-- 1 root root 309464 2008-07-23 02:33 .tmp_kallsyms1.o
-rw-r--r-- 1 root root 1244271 2008-07-23 02:33 .tmp_kallsyms2.S
-rw-r--r-- 1 root root 309464 2008-07-23 02:33 .tmp_kallsyms2.o
-rwxr-xr-x 1 root root 4932528 2008-07-23 02:33 .tmp_vmlinux1
-rwxr-xr-x 1 root root 5129136 2008-07-23 02:33 .tmp_vmlinux2
-rw-r--r-- 1 root root 2 2008-07-23 02:33 .version
-rw-r--r-- 1 root root 638 2008-07-23 02:33 .vmlinux.cmd
-rw-rw-r-- 1 root root 18693 2008-02-25 17:59 COPYING
-rw-rw-r-- 1 root root 91435 2008-02-25 17:59 CREDITS
-rw-rw-r-- 1 root root 1530 2008-02-25 17:59 Kbuild
-rw-rw-r-- 1 root root 89876 2008-02-25 17:59 MAINTAINERS
-rw-rw-r-- 1 root root 50404 2008-02-25 17:59 Makefile
-rw-r--r-- 1 root root 182981 2008-07-23 02:33 Module.symvers
-rw-rw-r-- 1 root root 16930 2008-02-25 17:59 README
-rw-rw-r-- 1 root root 3119 2008-02-25 17:59 REPORTING-BUGS
Printer
-rw-r--r-- 1 root root 851087 2008-07-23 02:33 System.map
-rwxr-xr-x 1 root root 5129136 2008-07-23 02:33 vmlinux
root@rainbird:/usr/src/linux-2.6.22.19# _
Mouse
Keyboard
5
6 Chapter 1. Introduction
Library It contains many files written by experts. We call them header files or library files. One such
header file is stdio.h, which must be included in any C code in its first line, using the instruction
#include <stdio.h>. Any other header file, such as math.h or stdlib.h, should be included this way
in the beginning. Each header file contains detailed instructions for complicated tasks. For example, the
©Partha Bhowmick
Chapter 1. Introduction 7
Start
Read a and b
1. Read a and b scanf("%d%d", &a, &b);
Yes No 2. If (a > b) then if (a > b)
a ą b? 3. print a printf("%d", a);
4. Else else
Print a Print b 5. print b printf("%d", b);
End
Start
Read a, b, c
Yes No
a ą b?
Yes No Yes No
a ą c? b ą c?
End
Figure 1.2: Top: The flowchart, the related algorithm, and a part of the C program needed to find and
print the larger between two numbers, a and b.
Bottom: The flowchart to find and print the largest among three numbers.
functions scanf and printf are contained in stdio.h, and the square-root function sqrt is contained in
math.h. You have to include these library files in your C program to use their functions. For example, you
have to include stdio.h to use scanf or/and printf, by writing #include <stdio.h> in the beginning of
your code. Similarly, you you have to include math.h to use its sqrt function, by writing #include <math.h>
just after #include <stdio.h>.
1. rLargest among three numberss Draw a flowchart to read three numbers and determine the largest.
You may use an extra variable but must not exceed two comparisons in total.
©Partha Bhowmick
8 Chapter 1. Introduction
e
e
d
d
de
co
co
co
e
Compiler Linker
bl
t
ce
ec
ta
ur
u
bj
ec
So
O
gcc
Ex
a01-1.c Library a.out
stdio.h, math.h, stdlib.h, etc.
Figure 1.3: The steps of compilation in C using the command gcc a01-1.c.
2. rSum of 10 numberss Draw a flowchart to read 10 numbers one by one and compute their sum. You
may use two extra variables and a maximum of 9 additions in total.
3. rLargest among 10 numberss Draw a flowchart to read 10 numbers one by one and determine the
largest. You may use two extra variables and a maximum of 9 comparisons in total.
4. rLargest and smallest among 10 numberss Draw a flowchart to read 10 numbers one by one and
determine both the largest and the smallest. You may use three extra variables and should aim to
minimize the total number of comparisons.
©Partha Bhowmick
2 | Variables and expressions
2.1 Variables
The data used by any computer program are stored in variables. A variable is identified by its four attributes:
name, type, value, address. These are explained below.
The name of a variable is written by the programmer. It can be any word or string composed of letters,
digits, and the underscore character. It must begin with either a letter or an underscore. Uppercase and
lowercase letters are treated as distinct in the C language. Here are some examples of variable names:
x, dx, y12, sum_1, _MYvar, realNum, complexNum, point, area, tax_rate, list, Set, Vector
The type of a variable is determined based on the type of data it stores. Accordingly, we have different
types of variables, which are also termed as data types. Further details are given in §2.2.
Depending on the type, a variable has a specific value within a specific domain. This value is either
assigned or computed when the program runs. To store this value in the main memory (i.e., RAM), a variable
needs some space during execution of the program. The amount of space, referred to as size, depends on
the data type of the variable. Hence, before using any variable, its type must be declared in the program.
This is called variable declaration. For example, by the declaration int a, the variable name is a and its
type is declared as an integer; hence, a space of 4 bytes will be allocated in the memory during execution of
the program. As another example, by the declaration char c, the variable c is declared as a character, and
hence a space of 1 byte will be allocated in the memory.
The address of a variable specifies its storage location in the main memory, which is settled during the
execution of the code. The address is denoted by the ampersand character, i.e., &; for example, for the
declaration int a, the address of a is denoted by &a. While reading the value of a variable for taking input
using scanf, its address is needed to store the value; that’s why in scanf the address is passed as an argument.
For example, to take as input the value of the integer variable a, we have to write scanf("%d", &a) to tell
the compiler that an integer has to be scanned in the decimal number system ("%d" means that) and stored
at the address &a.
Apart from the above-mentioned attributes, every variable has a scope and an extent in its corresponding
code. Its scope describes the part or block of code where it can be used. The extent describes its lifetime in
the execution of the code, i.e., the duration for which it has a meaningful value. The scope of a variable is
actually a property of the name of the variable, and the extent is a property of the storage location of the
variable. Scope is an important part of the name resolution of a variable. Because two variables (in the same
code) may have the same name but with different scopes. For example, a variable with the name x can be
declared and used in one for loop, and another variable with the same name x may be declared in another
for loop. They will be assigned different memory locations and will work therefore without any conflict.
There are certain reserved words, called keywords, that have predefined meanings in C. These keywords
cannot be used as variable names. They are listed in Table 2.1. Note that the keywords are all written
in lowercase only. Since uppercase and lowercase characters are not equivalent in programming language,
it is not illegal to write a variable name as an uppercase keyword. However, this is considered a poor
programming practice.
9
10 Chapter 2. Variables and expressions
A handful of basic data types are defined in C language (Table 2.2). Clearly, all the above data types
basically store numbers. It should be understood that the data type char also stores just a number, which
actually represents a single character.1 Since the number of characters is limited, one byte is enough to
represent all of them in a unique manner. Unless specified as unsigned, each of the above data types is
signed. For example, the declaration unsigned int a specifies that the variable a is unsigned, i.e., all its 48
bits are used to represent its absolute value. If it is not unsigned, then its leftmost bit is used to represent
the sign and hence termed as sign bit. If the sign bit is 0, then it is a positive number, else it is negative.
In case of char, there are 8 bits; by default, it is considered unsigned, and hence its value ranges from
0000 0000 “ 0 to 1111 1111 “ 255. If it is declared as unsigned, then this range is same. However, if it
is declared as signed, e.g., signed char c, then the leftmost bit is used to fix its sign, and so its value
ranges from 1000 0000 “ ´128 to 0111 1111 “ 127. Know that the magnitude of 1000 0000 is given by
its 2’s complement as follows: 1’s complement of 1000 0000 “ 0111 1111 (by reversing each bit); now, the
2’s complement is given by adding 1 to the 1’s complement, thus giving 0111 1111 + 1 “ 1000 0000 “ 128;
taking the negative sign into account, we get ´128 in the decimal number system.
For every other basic data type, the default specifier is signed. Explicit declaration has to be done to
make it unsigned. For example, int a means a can be a positive or negative integer, and since it uses 32 bits,
its range is from ´231 to 231 ´ 1, which is ´2,147,483,648 (1 followed by 31 0’s in binary) to 2,147,483,647
(0 followed by 31 1’s in binary). If during execution of the code, the value of a goes out of this range, there
could be faulty output. If the declaration is unsigned int a, then the variable a can take only non-negative
integer values from 0 (32 0’s in binary) to 232 ´ 1 “ 4,294,967,295 (32 1’s in binary).
Apart from the above basic data types, there is also a special type specifier named void, which indicates
that no value is available. It is used to specify the data type returned by a function, which we shall see later.
1 In
this context, it should also be well-understood that all data in the computer are essentially binary numbers or binary
strings; the data may be simply a text or an image or an audio or a video or any other entity.
©Partha Bhowmick
Chapter 2. Variables and expressions 11
We also have another useful data type called pointer that can store the memory-address of any variable.
This will also be discussed later.
Using the basic data types, a programmer can obtain new data types called derived data types. These
include string, array, structure, and union, which will come up in later chapters.
2.3 Constants
Constants are broadly of two types: numeric and character. A numeric character is either integer or real.
Character constant means either a single character or a string of characters. A single character is specified
within single quotes, e.g., ’0’, ’y’, ’+’. A string is specified within double quotes. Some typical examples
are as follows.
Integer constants can also be written in hexadecimal number system. A hexadecimal integer must begin
with 0x or 0X and then contain one or more hex digits. The hex digits are 0 through 9 and a through f
(or A through F). The six letters a through f (or A through F) represent the decimal numbers 10 through 15,
respectively. Following are some hexadecimal numbers: 0x, 0xA, 0X2D, 0xf5a; check that their respective
values in decimal number system are 0, 10, 45, 3930.
There are also multiple ways of representing a real number. For example, 5 ˆ 104 can be represented by
any of the following floating-point constants: 50000, 5e4, 5e+4, 5E4, 5.0e+4, .5e5, 50E3, 50.E+3, 500e2.
2.4 Statements
In C language, a statement is a complete instruction that tells the computer to perform a specific task.
Statements are the building blocks of a program and typically end with a semicolon (;). Statements can
include operations like assigning values to variables, controlling the flow of execution, or calling functions.
Following are some examples.
Note that the sign of equality (=) is used to assign values to variables. Assignment is an operation, and
hence = is called the assignment operator. The left of = is termed as l -value. In x = a + b/2, the l -value
refers to the value of x. An l -value has a definite address in memory during execution. On the contrary,
whatever occurs at the right side of = is referred to as the r -value. In the last example, it corresponds to
the expression a + b/2. It has no address of its own, although the variables a and b have definite addresses
in the memory during the execution.
©Partha Bhowmick
12 Chapter 2. Variables and expressions
Types of l -value and r -value should preferably be the same; e.g., either both are integers or both are
real. If not, the type of the r -value will be converted to the type of the l -value, and then assigned to it.
Consider the following example.
double a;
a = 2*3;
In the assignment statement, the type of r -value is int because 2 and 3 are both integers, and so its value
is 6. However, since the type of l -value is double, the value stored for a is real, i.e., 6.0.
Now, consider another example:
int a;
a = 2*3.4;
Here, the type of r -value is real and the value is 6.8. But, since the type of l -value is int, so its integer part,
i.e., 6, is stored in a.
©Partha Bhowmick
Chapter 2. Variables and expressions 13
The value of c will be the integer obtained by dividing 10 by 4. In the integer domain, this value is the
quotient of dividing 10 by 4, and so c receives the value 2. The value of x will be the integer obtained by
dividing 10 by 4, which is 2 again, and but mapping it to the real domain gives 2.0; hence, x gets the value
2.0. By type casting, we can store the value 2.5 to x. It can be done by:
x = (float)a / b;
Since the right side is a mix of real ((float)a) and integer (b), the operation is done in the real domain.
As another example, the following code won’t produce correct output when a+b is odd.
int a, b;
scanf("%d%d", &a, &b);
avg = (a + b)/2;
printf("%f\n", avg);
©Partha Bhowmick
14 Chapter 2. Variables and expressions
1. Arithmetic expression: b+c is an arithmetic expression in which the addition operator + acts on the
operands b and c. On assigning the values 2 and 3 to b and c respectively, the value of the expression
b+c becomes 5.
Although it may sound strange to one who is new to computer programming, a=b+c is also an
arithmetic expression with two operators, namely addition (+) and assignment (=). Here, the value of
the expression b+c is computed first, and that value is assigned to a, which eventually becomes the value
of the whole expression a=b+c. For example, on assigning the values 2 and 3 to b and c respectively,
the variable a gets the value 5, and hence the value of the expression a=b+c becomes 5. Note that the
value of a=b+c is same as the value of a, because in C language, due to the assignment operator, such an
expression always gets the value of the variable (i.e., operand) to the left side of the assignment operator.
It is the l -value and refers to the value of a, as explained in §2.4.
The value of an expression is important because that expression may be used as an operand in
another expression. For example, d=(a=b+c)+1 is an expression composed with the previous expression,
a=b+c. On assigning the respective values 2 and 3 to b and c, the value of a becomes 5, which means
the expression a=b+c receives the value 5, which gives 6 as the value of d, and this finally sets the value
of the whole expression d=(a=b+c)+1 to 6.
2. Relational expression: Consider the relational operator < used in the relational expression a<b. The
value of a<b will be 1 if a is less than b, and 0 otherwise.
A relational operator is used to compare an operand with another. The operand may be a variable
or a non-variable expression. For example, in the expression a != b the operand != is used between
two variables; it yields 1 if a and b are unequal, and yields 0 if not. On the contrary, in the expression
a != b*b+1, the same operand works between a variable and an expression.
3. Logical expression: Here we need to be careful — any nonzero integer means True, and only the
integer 0 means False. For example, a&&b evaluates to 0 if and only if at least one of a and b is 0. On
the contrary, a||b evaluates to 0 if and only if both a and b are 0. Equivalently, a&&b evaluates to 1 if
and only if both a and b are nonzero, whereas a||b evaluates to 1 if and only if at least one of a and b
is nonzero. The notation && denotes the logical and operator, whereas || denotes the logical or.
The notation ! denotes the logical not; it is a unary operator and hence acts on a single operand.
For example, the expression !a evaluates to 0 if and only if a is nonzero. That is, if a is any number
other than 0, then !a evaluates to 0, and it evaluates to 1 only if a is 0.
Clearly, since a logical expression basically works with the truth value of the associated operands,
the operands can be any real number.
Consider a practical expression: ((!weekday && hobby) || (weekday && study)). It has three
variables working as operands, namely weekday, hobby, and study; and it has four logical operators
in total. With weekday “ 0, hobby “ 1, study “ 0, it evaluates to (1 || 0) “ 1. With weekday “
1, 2, . . . , 6, it evaluates to 0 if study “ 0, no matter the value of hobby — can you check and argue?
4. Bitwise expression: An expression where bitwise operators are used for computation at the bit level.
It makes the computation fast. Bitwise operators work with integer -valued operands and cannot be
applied to non-integer real numbers such as float or double. The bitwise binary operators are & (and),
| (or), ^ (xor), << (left shift), and >> (right shift); the bitwise unary operator is ~ (1’s complement).
©Partha Bhowmick
Chapter 2. Variables and expressions 15
For example, a<<k means a left shift of the bits of a by k places. Say a has the value 5; so, its 8-bit
representation is 00000101; then a<<3 means a left shift of the bits of a by 3 places, appending three
0’s at the right side so that it again has 8 bits. This gives 00101000, thereby changing the value of a to
5 ˆ 23 “ 40. On the contrary, a>>3 does a right shift by 3 bits, changing the value of a to 00000000 “ 0.
Similarly, a>>1 applies a right shift by 1 bit, changing the value to 00000010 “ 2; and a>>2 applies a
right shift by 2 bits, changing the value to 00000001 “ 1. That is, bitwise left shift by k bits is equivalent
to multiplying by 2k , and bitwise right shift by k bits is equivalent to dividing by 2k .
The following code shows uses of the bitwise operators. Note that if the leftmost bit is 1, then it is
a negative number. For example, the 1’s complement of a (i.e., ~a) is a negative number. To print its
unsigned value, the format is %u. To print its signed value, the format is %d; and that value is given by
the 2’s complement of ~a, which, in turn, is given by the 1’s complement of ~a (i.e., a) plus 1.
1 #include <stdio.h>
2
3 int main() {
4 int a = 20; // 00...0 0001 0100 = 20
5 int b = 13; // 00...0 0000 1101 = 13
6
17 return 0;
18 }
1. rOne-variable integer expressionss Given an integer a, compute and print the values of the following
expressions: ´a, 2a ´ 3, 2a2 ´ 3a ´ 4.
1 #include <stdio.h>
2
3 int main(){
4 int a;
5
13 return 0;
14 }
©Partha Bhowmick
16 Chapter 2. Variables and expressions
2. rTwo-variable integer expressionss Given two integers a and b as input, compute and print the val-
ues of the following expressions: a ` b, ´a ´ 2b ` 3, ´2ab, 1 ´ 2apb ´ 3q.
1 #include <stdio.h>
2
3 int main(){
4 int a,b;
5
14 return 0;
15 }
3. rLeft shifts Given two integers a and b as input, compute and print the value of 2a ` 4b without using
any multiplication.
1 #include <stdio.h>
2
3 int main(){
4 int a,b;
5
9 a <<= 1;
10 b <<= 2;
11
14 return 0;
15 }
4. rReal-domain expressionss Compute and print the values of the xy and x1 ` y1 in floating point, where
x, y are nonzero real numbers given as input. The value of the 1st expression should be printed up to
the 6th decimal place, and that of the 2nd expression up to the 3rd decimal place. For example, if x “ 2
and y “ 3, then the printed values should be 0.666667 and 0.833, respectively.
1 #include <stdio.h>
2
3 int main(){
4 float x, y, z;
5
©Partha Bhowmick
Chapter 2. Variables and expressions 17
10
11 return 0;
12 }
5. rInteger-to-real maps Compute and print the values of the following expressions in floating point
(rounded off to 3rd decimal place), where a, b are positive integers given as input.
˜c 1
¸ a`b
a 1 1
a ` b, , ` .
b a b
For example, if a “ 2 and b “ 3, then the respective printed values will be 5.000, 0.667, 0.982.
As the values should be real, the computations should be in the real domain. You should use the math
library (math.h) and compile your code as follows: gcc <input file> -lm
1 #include <stdio.h>
2 #include <math.h>
3
4 int main(){
5 int a, b;
6
14 return 0;
15 }
6. rPre-increment and post-increments Write the new values obtained after the following statements
are executed one after the other.
int a, b, x; ÝÑ a, b, x all have ‘garbage values’
a = 10, b = 20, x; ÝÑ a gets 10, b gets 20
x = 50 + ++a; ÝÑ a = 11, x = 61 (a is first incremented and then added)
x = 50 + a++; ÝÑ x = 61, a = 12 (a is first added and then incremented)
x = a++ + --b; ÝÑ b = 19, x = 31, a = 13 (b is first decremented and then added)
x = a++ - ++a; ÝÑ x = -2, a = 15 (a++ is 13 as operand, ++a is 15 as operand)
In the last statement, there is a side effect: while calculating some values, something else get changed.
It is always better to avoid such complicated statements.
7. rOne-variable integer expressionss Given an integer a, compute and print the values of the following
expressions: ´a, 2a ´ 3, 2a2 ´ 3a ´ 4.
1 #include <stdio.h>
2
3 int main(){
4 int a;
5
©Partha Bhowmick
18 Chapter 2. Variables and expressions
13 return 0;
14 }
8. rTwo-variable integer expressionss Given two integers a and b as input, compute and print the val-
ues of the following expressions: a ` b, ´a ´ 2b ` 3, ´2ab, 1 ´ 2apb ´ 3q.
1 #include <stdio.h>
2
3 int main(){
4 int a,b;
5
14 return 0;
15 }
9. rMinimum multiplicationss Given two integers a and b as input, compute and print the values of a2 b,
a2 b2 , and a2 b4 , using at most 6 multiplications for all three of them in total, without using any extra
variable, and without using the math library.
1 #include <stdio.h>
2
3 int main(){
4 int a,b;
5
9 a = a*a;
10 printf("Answers = %d, ", a*b);
11 b = b*b;
12 printf("%d, ", a*b);
13 b = b*b;
14 printf("%d.\n", a*b);
15
16 return 0;
17 }
10. rLeft shifts Given two integers a and b as input, compute and print the value of 2a ` 4b without using
any multiplication.
1 #include <stdio.h>
2
3 int main(){
4 int a,b;
©Partha Bhowmick
Chapter 2. Variables and expressions 19
9 a <<= 1;
10 b <<= 2;
11
14 return 0;
15 }
11. rReal-domain expressionss Compute and print the values of the xy and x1 ` y1 in floating point, where
x, y are nonzero real numbers given as input. The value of the 1st expression should be printed up to
the 6th decimal place, and that of the 2nd expression up to the 3rd decimal place. For example, if x “ 2
and y “ 3, then the printed values should be 0.666667 and 0.833, respectively.
1 #include <stdio.h>
2
3 int main(){
4 float x, y, z;
5
11 return 0;
12 }
12. rAverages Read in three integers and print their average as a real number.
1 #include <stdio.h>
2
3 int main(){
4 int a, b, c;
5 printf("Enter three integers: ");
6 scanf("%d%d%d", &a, &b, &c);
7 printf("Average = %f\n", ((float)(a+b+c))/3);
8 return 0;
9 }
13. rArea of a triangles Read in the coordinates (as double-precision real numbers) of three points on
xy-plane, and print the area of the
atriangle formed by them.
You can use the Heron’s formula sps ´ aqps ´ bqps ´ cq, where s “ 21 pa ` b ` cq, and a, b, c denote the
lengths of three sides.
You can use sqrt function of math.h library to compute the square root, but should not use any other
function.
1 #include <stdio.h>
2 #include <math.h>
3
4 int main(){
©Partha Bhowmick
20 Chapter 2. Variables and expressions
14 a = sqrt((x2-x3)*(x2-x3) + (y2-y3)*(y2-y3));
15 b = sqrt((x1-x3)*(x1-x3) + (y1-y3)*(y1-y3));
16 c = sqrt((x1-x2)*(x1-x2) + (y1-y2)*(y1-y2));
17
18 s = (a+b+c)/2;
19 area = sqrt(s*(s-a)*(s-b)*(s-c));
20 printf("Area = %f\n", area);
21
22 return 0;
23 }
14. rCompound interests Read in the principal amount P, the interest rate R in percentage, the number
of years N, and print the compound interest C earned after N years. Read P and R as floating-point
numbers, and N as an integer. The compound interest C should be printed as the nearest whole number.
For example, if P = 100, R = 10, N = 7, then the value of C is Rs. 94.871712, which should be printed as
Rs. 95.
You can use pow function of math.h.
1 #include <stdio.h>
2 #include <math.h>
3
4 int main(){
5 float P, R, C;
6 int N;
7 printf("Enter P: ");
8 scanf("%f", &P);
9 printf("Enter R: ");
10 scanf("%f", &R);
11 printf("Enter N: ");
12 scanf("%d", &N);
13
14 C = P*pow((double)(1+R/100.0), (double)N) - P;
15 printf("Compound interest = Rs. %0.0f\n", C);
16
17 return 0;
18 }
15. rOne-variable logical expressionss Compute and print the logical value of !a, where a is any integer
given as input. You should check (and know) that !a “ 1 if and only if a “ 0. That is, !a “ 1 when
a “ 0, and !a “ 0 when a “ 1, ´1, 2, ´2, . . ..
1 #include <stdio.h>
2
3 int main(){
©Partha Bhowmick
Chapter 2. Variables and expressions 21
4 int a;
5
11 return 0;
12 }
16. rMulti-variable logical expressionss Compute and print the logical values of the following expres-
sions, where a, b, c are the integers given as input.
(!a) && (!b) && c
(a && b) || (!c)
1 #include <stdio.h>
2
3 int main(){
4 int a, b, c;
5
9 printf("Logical value of (!a) && (!b) && c = %d\n", (!a) && (!b) && c);
10 printf("Logical value of (a && b) || (!c) = %d\n", (a && b) || (!c));
11
12 return 0;
13 }
n
17. rSum of seriess Without using any loop, compute and print the value of i, where n is a positive
ř
i“1
integer given as input.
1 #include <stdio.h>
2
3 int main(){
4 int n;
5
10 return 0;
11 }
18. rNumber of digitss Read in a positive integer n. Assume that it has at most 4 digits. Without using
any conditional such as if-else or switch-case, print its number of digits. Also, print the expression
you have used to get the answer.
1 #include <stdio.h>
2
3 int main(){
©Partha Bhowmick
22 Chapter 2. Variables and expressions
4 int n;
5 printf("Enter the value of n: ");
6 scanf("%d", &n);
7 printf("Number of digits in n = %d\n", 1 + (n>=10) + (n>=100) + (n>=1000));
8 printf("Expression used: 1 + (n>=10) + (n>=100) + (n>=1000)\n");
9 return 0;
10 }
a && (b || c)
a && ((b || c)==0)
!(a && (b || c))
(a && (b || c)) == 0
(a && (b || c)) == 1
(!a) && ((!b) || c)
((a == 1) || ((b == 0) && (c == 1))) || ((a == 0) || ((b == 1) && (c == 0)))
((0 <= a) && (a >= 10) && (11 <= b) && (b <= 20) && (15 <= a+b) && (c >= 5))
2. rRight shifts Given two integers a and b as input, compute and print the value of a2 ` 4b without
X \ X \
using division. (Observe that 2 and 4 are the respective quotients obtained when a and b are divided
Xa\ Xb\
by 2 and 4 respectively.)
3. rInteger-to-real maps Compute and print the values of the following expressions in floating point
(rounded off to 3rd decimal place), where a, b, c are integers given as input. You can use the math
library.
ˆ ˙ ?1
a b c 2 3 2 3
? ? 2 5 5
a ` 2b ` 3c, ` ` , p1.25a ` 2.75a ` 5.625a qpb {p1.25 ` c qq, 2a ` 3b ` c3 .
2 2 3 4
As the values should be real, the computations should be in the real domain. For example, if a “ 3, b “
2, c “ 1, then the value of a2 ` 2b ` 3c would be 1.500 ` 1.000 ` 0.333 “ 2.833.
4. rLargest fractions Given as input six positive integers a, b, c, d, e, f , find a/the largest among ad , eb , fc ,
using only integer computations.
5. rSum of seriess Without using any loop, compute and print the values of the following sums, where
n is a positive integer given as input.
n
ÿ n
ÿ n
ÿ
i2 , i3 , pi ` 1qpi ` 2qpi ` 3q.
i“1 i“1 i“1
©Partha Bhowmick
3 | Conditionals
Conditionals or conditional expressions are basically expressions used in codes for taking required decisions.
They have two possible constructs: (i) if or if-else and (ii) switch-case. The if construct means if
some condition is true, then do something. The if-else construct means if some condition is true, then do
something; otherwise do whatever is mentioned after else. The if-else construct can be extended to build
a logical chain of if-else, but should be carefully coded. The two curly braces, i.e., { and }, are used to
fix the logic.
Complications in the coding logic are often handled using switch-case or a combination of if-else
and switch-case constructs. In the switch-case construct, out of multiple cases, every particular case is
handled based on the value of a single expression in the argument of switch. The value of that expression
is computed only once and it is compared with the value of each case one by one. If there is a match, then
the block of code associated with only that case is executed, rest are not. The break statement breaks out
of the entire switch block. The default statement is optional, and its code is executed only if there is no
match with any case in that switch block.
Examples
1. Suppose weekday is an integer in r0, 6s, where 0 represents Sunday, 1 represents Monday, and so on.
Suppose that on Sunday, everyone wants to enjoy a movie. Its construct will be:
if (!weekday)
printf("Go for a movie!\n");
Now, suppose that movies are restricted other than on Sunday. Then its construct will be:
if (weekday)
printf("Try to avoid movies!\n");
Now, suppose that movies are prescribed on Sunday but music is prescribed for everyday. Then its
construct will be:
if (!weekday)
printf("Go for a movie or listen to music!\n");
else
printf("Avoid movie and listen to music!\n");
2. To complicate the above example, suppose that you need to write a code that will suggest for seeing a
movie on Sunday only, playing some sports on Monday, Wednesday, and Friday, going to a restaurant
on Tuesday, and visiting the library on Thursday and Saturday. Since there are several cases, they are a
little difficult to code using the if-else construct, but quite easier using switch-case, as shown below.
switch (weekday){
case 0:{
printf("It’s Sunday! Go for a movie!\n");
break;
23
24 Chapter 3. Conditionals
};
case 1: case 3: case 5:{
printf("Go for sports!\n");
break;
};
case 2: {
printf("Enjoy your favorite food in some restaurant!\n");
break;
};
default:{ // all other cases
printf("Visit the library!\n");
break;
};
} // end switch
1. rLarger fractions Given as input four positive integers a, b, c, d, find a/the larger between a
c and d,
b
1 #include <stdio.h>
2
3 int main(){
4 int a, b, c, d;
5
14 return 0;
15 }
16
17 /* Examples:
18
2. rPrime digitss User supplies a positive integer having value less than 100. Find and print its prime
digits if any. For example, in 47, the prime digit is 7.
1 #include <stdio.h>
2
3 int main(){
4 int n, a, b, k = 0; // k = no. of primes
©Partha Bhowmick
Chapter 3. Conditionals 25
9 a = n/10;
10 b = n - 10*a;
11
12 printf("Prime digits:");
13
24 if(k>0)
25 printf(".\n");
26 else
27 printf("None.\n");
28
29 return 0;
30 }
1 #include<stdio.h>
2
3 int main(){
4 int a, b, c, p, q, r;
5 float x, y;
6
7 printf("Enter a, b, c: ");
8 scanf("%d%d%d", &a, &b, &c);
9 printf("Enter p, q, r: ");
10 scanf("%d%d%d", &p, &q, &r);
11
12 if(q*a == b*p)
13 printf("Lines are parallel.\n");
14 else{
15 x = (float)(-q*c+b*r)/(q*a-b*p);
16 y = (float)(-p*c+a*r)/(p*b-a*q);
17 printf("Point of intersection = (%0.3f, %0.3f)\n", x, y);
18 }
19
20 return 0;
21 }
©Partha Bhowmick
26 Chapter 3. Conditionals
4. rOne is sum of twos Read in three integers and print a message if any one of them is equal to the
sum of the other two.
1 #include <stdio.h>
2
3 int main() {
4 int a, b, c;
5
9 if (a == b + c) {
10 printf("a is equal to the sum of b and c.\n");
11 } else if (b == a + c) {
12 printf("b is equal to the sum of a and c.\n");
13 } else if (c == a + b) {
14 printf("c is equal to the sum of a and b.\n");
15 } else {
16 printf("None of the integers is equal to the sum of the other two.\n");
17 }
18
19 return 0;
20 }
5. rRoots of quadratic equations Read in the coefficients a, b, c of the quadratic equation ax2 `bx`c “
0, and print its roots nicely. For complex roots, print in x ` iy form.
1 #include <stdio.h>
2 #include <math.h>
3
4 int main() {
5 float a, b, c;
6 float discriminant, realPart, imaginaryPart, root1, root2;
7
8 // Read coefficients a, b, c
9 printf("Enter coefficients a, b, and c: ");
10 scanf("%f %f %f", &a, &b, &c);
11
©Partha Bhowmick
Chapter 3. Conditionals 27
35 return 0;
36 }
6. rOperation selections Create a simple calculator program that takes two numbers and an operator
(+, -, *, /, %) as input and performs the corresponding operation using a switch-case statement.
1 #include <stdio.h>
2
3 int main() {
4 char operator;
5 float num1, num2, result;
6
©Partha Bhowmick
28 Chapter 3. Conditionals
41 printf("Invalid operator!\n");
42 return 1;
43 }
44
7. rVowel or consonants Develop a program that takes a single character as input and determines
whether it is a vowel or a consonant using a switch-case statement.
1 #include <stdio.h>
2
3 int main() {
4 char ch;
5
9 switch (ch) {
10 case ’a’:
11 case ’e’:
12 case ’i’:
13 case ’o’:
14 case ’u’:
15 case ’A’:
16 case ’E’:
17 case ’I’:
18 case ’O’:
19 case ’U’:
20 printf("%c is a vowel.\n", ch);
21 break;
22 default:
23 printf("%c is a consonant.\n", ch);
24 }
25
26 return 0;
27 }
8. rDay of the weeks Write a program that takes the day of the week as an input (1 for Monday, 2 for
Tuesday, etc.). If the day is Saturday or Sunday, print Weekend. For other days, print the name of
the day. Additionally, check if the day is a special day (e.g., Wednesday) using if-else, and print an
appropriate message.
1 #include <stdio.h>
2
3 int main() {
4 int day;
5
9 switch (day) {
©Partha Bhowmick
Chapter 3. Conditionals 29
10 case 1:
11 printf("Monday\n");
12 break;
13 case 2:
14 printf("Tuesday\n");
15 break;
16 case 3:
17 printf("Wednesday\n");
18 break;
19 case 4:
20 printf("Thursday\n");
21 break;
22 case 5:
23 printf("Friday\n");
24 break;
25 case 6:
26 case 7:
27 printf("Weekend\n");
28 return 0;
29 default:
30 printf("Invalid day\n");
31 return 0;
32 }
33
41 return 0;
42 }
9. rMarks to grades Suppose that you have to print the grade of a student, with 90–100 marks get-
ting EX, 80–89 getting A, 70–79 getting B, 60–69 getting C, 50–59 getting D, 40–49 getting P, and less
than 40 getting F. Read in the marks of a student and print his/her grade. You should use switch-case.
1 #include <stdio.h>
2
3 int main() {
4 int marks;
5 char grade;
6
©Partha Bhowmick
30 Chapter 3. Conditionals
17 case 8:
18 grade = ’A’;
19 break;
20 case 7:
21 grade = ’B’;
22 break;
23 case 6:
24 grade = ’C’;
25 break;
26 case 5:
27 grade = ’D’;
28 break;
29 case 4:
30 grade = ’P’;
31 break;
32 default:
33 grade = ’F’;
34 }
35
43 return 0;
44 }
1. rLargest fractions Given as input six positive integers a, b, c, d, e, f , find a/the largest among ad , eb , fc ,
using only integer computations.
2. rLargest elements Given as input five numbers a, b, c, d, e, find a/the largest among them using at
most four comparisons. You can use an extra variable.
3. rTemperature alert systems Create a program that takes the current temperature as input and
provides a message based on the following conditions:
• Above 100˝ F: "Heat Alert!"
• 85˝ F to 100˝ F: "Warm Weather"
• 60˝ F to 84˝ F: "Pleasant Weather"
• 32˝ F to 59˝ F: "Cool Weather"
• Below 32˝ F: "Cold Alert!"
Use if-else to evaluate the temperature and display the corresponding message.
4. rTraffic light simulations Create a program that simulates a traffic light. The program should take a
character input (’r’ or ’R’ for Red, ’y’ or ’Y’ for Yellow, ’g’ or ’G’ for Green) and display a message
indicating whether to stop, slow down, or go. Use a switch-case to handle the different light colors.
©Partha Bhowmick
4 | Loops
?
Loops are needed
? ? to perform repeated tasks of same nature. For example, to compute the value of 1 ` 2 `
3 ` ¨ ¨ ¨ ` 99, we have to compute the square root of a number, 98 times, and so a loop will be useful. A
loop essentially executes a block of code as long as a specified expression is true. The specified expression is
treated as a Boolean condition.
Loops are of three types: while loop, do-while loop, and for loop. They are all equivalent in the sense
that one can be used in place of another, but sometimes one is a little more convenient than the others while
writing the code.
The general syntax of the while loop and the do-while loop are as follows. As mentioned above, the
expression written inside while(...) is treated as a Boolean condition. A loop iterates till the condition
is true.
? ? ?
The above two loops for the specific problem of computing the value of 1 ` 2 ` 3 ` ¨ ¨ ¨ ` 99 are
written below. Notice that the condition for either of these two loops is i < 100, which is just an expression
(as explained earlier in Section 2.5). The value of this expression is nonzero (i.e., true) if and only if i is
less than 100. In every iteration, the value of i is increased by unity. So, here the variable i acts as the
loop variable and determines how many times the loop will iterate. Check that in this example, the loop
iterates for 98 times; and when the value of i becomes 100, it terminates. This happens for both the while
loop and the do-while loop.
int i = 1; int i = 1;
double sum = 1.0; double sum = 1.0;
while (i < 100){ do{
i++; i++;
sum += sqrt((double)i); sum += sqrt((double)i);
} } while (i < 100);
31
32 Chapter 4. Loops
©Partha Bhowmick
Chapter 4. Loops 33
Examples: The following code finds the smallest number n such that n! exceeds 1000. See how it uses a
break statement.
int fact = 1, n = 1;
while(1){
fact = fact * n;
if (fact > 1000){
printf ("Factorial of %d exceeds 1000", n)
break; // breaks the while loop
}
i++ ;
}
The following code goes on adding positive integers until a 0 is encountered, ignoring all negative
numbers that appear in between. See how it uses break and continue statements.
#include <stdio.h>
int main(){
int i, j;
for (i = 10; i <= 20; i++){ // outer loop
for (j = 10; j <= 20; j++){ // inner loop
printf("%3d\t", i * j);
}
printf("\n");
}
return 0;
In the outer loop, the variable i iterates from 10 to 20, representing the rows of the multiplication table.
In the inner loop, for each iteration of the outer loop, the variable j iterates from 10 to 20, representing
©Partha Bhowmick
34 Chapter 4. Loops
the columns. After the multiplication, the product of i and j is calculated and printed, with each value
separated by a tab (\t) to format the table neatly. After each row is printed, the program moves to the next
line using \n. The output looks as follows.
100 110 120 130 140 150 160 170 180 190 200
110 121 132 143 154 165 176 187 198 209 220
120 132 144 156 168 180 192 204 216 228 240
130 143 156 169 182 195 208 221 234 247 260
140 154 168 182 196 210 224 238 252 266 280
150 165 180 195 210 225 240 255 270 285 300
160 176 192 208 224 240 256 272 288 304 320
170 187 204 221 238 255 272 289 306 323 340
180 198 216 234 252 270 288 306 324 342 360
190 209 228 247 266 285 304 323 342 361 380
200 220 240 260 280 300 320 340 360 380 400
©Partha Bhowmick
Chapter 4. Loops 35
1 #include <stdio.h>
2
3 int main(){
4
13 return 0;
14 }
See that in the expression ’a’+i, ’a’ is a character, whereas i is an integer. The operator + is used to
add the ASCII value (which is always an integer) of ’a’ with the value of i. Consequently, the value of
’a’+i is also an integer. The same holds for the expression ’A’+i as well. The overall output will be as
follows:
a: 97 b: 98 c: 99 d: 100 e: 101 f: 102 g: 103 h: 104 i: 105
j: 106 k: 107 l: 108 m: 109 n: 110 o: 111 p: 112 q: 113 r: 114
s: 115 t: 116 u: 117 v: 118 w: 119 x: 120 y: 121 z: 122
A: 65 B: 66 C: 67 D: 68 E: 69 F: 70 G: 71 H: 72 I: 73
J: 74 K: 75 L: 76 M: 77 N: 78 O: 79 P: 80 Q: 81 R: 82
S: 83 T: 84 U: 85 V: 86 W: 87 X: 88 Y: 89 Z: 90
2. rSums Given n real numbers from the keyboard, find their sum. User input is n and the numbers.
1 #include <stdio.h>
2
3 int main(){
4 int i, n;
5 float x, sum;
6
7 printf("Enter n: ");
8 scanf("%d", &n);
9
18 return 0;
19 }
©Partha Bhowmick
36 Chapter 4. Loops
3. rReading characterss Read in characters until the n character is typed. Count and print the number
of lowercase letters, the number of uppercase letters, and the number of digits entered.
1 #include <stdio.h>
2
3 int main() {
4 char ch;
5 int lower_count = 0, upper_count = 0, digit_count = 0;
6
21 return 0;
22 }
n
4. r5th-power sums Given a positive integer n, compute the value of k 5 , without using math.h.
ř
k“1
1 #include <stdio.h>
2
3 int main(){
4 int k, n;
5 long long int sum;
6
7 printf("Enter n: ");
8 scanf("%d", &n);
9
16 return 0;
17 }
5. rBit-lengths Given a positive integer n, determine the integer ` such that 2`´1 ď n ă 2` . Here, ` is
called the bit-length of n.
1 #include <stdio.h>
2
3 int main(){
4 int n, i=1, len=0;
5
©Partha Bhowmick
Chapter 4. Loops 37
9 while(i<=n){
10 i <<= 1; len++;
11 }
12 printf("Bit-length = %d\n", len);
13
14 return 0;
15 }
6. rDecimal to binary, 8 bitss Given an integer n P r0, 255s, print its 8-bit binary representation. You
can use at most 3 integer variables and no character variables.
1 #include <stdio.h>
2
3 int main(){
4 int n, i, j;
5
19 return 0;
20 }
7. rGCDs Given two positive integers a, b, compute their GCD. Use the fact that if a ď b, then
if a “ 0
"
b
gcdpa, bq “ (4.1)
gcdpb mod a, aq otherwise.
Since no function other than main() is allowed in this section, you have to do it iteratively using a loop.
1 #include <stdio.h>
2
3 int main(){
4 int a, b, c;
5 printf("\nEnter two positive integers: ");
6 scanf("%d%d", &a, &b);
7 while(a!=0){
8 c = a;
9 a = b%a;
10 b = c;
11 printf("a b c = %7d %7d %7d\n", a, b, c);
12 }
13 printf("GCD = %d\n\n", b);
14 return 0;
15 }
©Partha Bhowmick
38 Chapter 4. Loops
2 3
8. rex as a finite sums We know that in the infinite sum ex “ 1 ` x ` x2! ` x3! ` ¨ ¨ ¨ , the trailing terms
have negligible values. Given a positive value of x, compute the sum up to its nth term and return that
value as the approximate value of ex as soon as the nth term is found to be less than ε. Also print the
value of n. Needless to say, you should not use the math library.
3 #include <stdio.h>
4
5 int main(){
6 double x, epsilon, ex = 1.0, current = 1.0, previous = 0.0;
7 int n = 1;
8
9 printf("Enter x: ");
10 scanf("%lf", &x);
11 printf("Enter epsilon: ");
12 scanf("%lf", &epsilon);
13
3 #include <stdio.h>
4
5 int main(){
6 int a, b, p, q, r, s, t;
7 printf("Enter b: ");
8 scanf("%d", &b);
9
10 p = b, q = 2*b-1;
11 printf("%d/%d ", b, 2*b-1);
12
©Partha Bhowmick
Chapter 4. Loops 39
1 #include <stdio.h>
2
3 int main(){
4 const int SIZE = 5;
5 int row, col;
6 for (row = 0; row < SIZE; ++row){
7 for (col = 0; col < SIZE; ++col){
8 printf("* ");
9 }
10 printf("\n");
11 }
12 return 0;
13 }
Note that const indicates that the value of SIZE cannot be modified after it is initialized. It is a constant,
so trying to change its value later in the code will result in a compilation error.
The output is shown in Figure 4.1(a).
11. rPrint lower triangles Print the lower triangle of a 5 ˆ 5 square filled up with ’*’. The output is
shown in Figure 4.1(b).
1 #include <stdio.h>
2
3 int main(){
4 const int SIZE = 5;
5 int row, col;
6 for (row = 0; row < SIZE; ++row){
7 for (col = 0; col <= row; ++col){
8 printf("* ");
9 }
10 printf("\n");
11 }
12 return 0;
13 }
12. rPrint upper triangles Print the upper triangle of a 5 ˆ 5 square filled up with ’*’. The output is
shown in Figure 4.1(c).
1 #include <stdio.h>
2
3 int main(){
4 const int SIZE = 5;
©Partha Bhowmick
40 Chapter 4. Loops
* * * * * * * * * * *
* * * * * * * * * * *
* * * * * * * * * * *
* * * * * * * * * * *
* * * * * * * * * * *
(a) square (b) lower triangle (c) upper triangle
Figure 4.1: Output of the codes for printing a square, its lower triangle, and its upper triangle.
Use #define DIFF 0.00001 to terminate the summation when the sum up to nth term differs by less
than DIFF from the sum up to pn ´ 1qst term. Needless to say, you should not use the math library.
©Partha Bhowmick
5 | One-dimensional arrays
Suppose that you have lots of storybooks, poetry books, comic books, etc.,
and also have many other books on different subjects such as Physics, Chem-
istry, Biology, Mathematics, etc. While keeping them in a bookshelf, you will
naturally try to keep them in an organized way so that you can get any book
down from the shelf right away, whenever needed. The same idea is used
when you have to keep many elements in the computer memory. You have
to arrange them in an organized way in the memory so that any of them can
immediately be accessed when the code is running. For this arrangement, the
concept of data structure comes into use. One such data structure is array—it
is just analogous to your bookshelf!
41
42 Chapter 5. One-dimensional arrays
indexes 0 1 2 3 4
main memory (RAM) 7 ´2 6 3 6 main memory (RAM)
8D2C
8D30
8D34
8D38
8D3C
8D2D
8D2E
8D2F
8D31
8D32
8D33
8D35
8D36
8D37
8D39
8D3A
8D3B
8D3D
8D3E
8D3F
8D40
8D41
8D42
8D43
byte addresses
(in hexadecimal)
Figure 5.1: An array with 5 elements having values 7, ´2, 6, 3, 6. Each element is a 4-byte integer, so the
total space allocated in the memory for this array is 4 ˆ 5 “ 20 bytes. Its first and last byte have
the addresses 8D2C and 8D3F, respectively. The address of an element is basically the address
of its first byte (expressed as a hexadecimal number, a typical convention). So, the respective
addresses of the five elements here are 8D2C, 8D30, 8D34, 8D38, and 8D3C.
Second, the elements of an array occupy contiguous locations in the memory when the executable file
is executed. As a result, any element of the array can be accessed directly, just by specifying its index.
In particular, a[i] gives the element with the index i in a[]. The direct accessing is possible because the
address of the element with index i easily follows from the address of the element with index 0. The simple
reason is that all elements have the same data type and hence they all take equal amount of space (measured
in bytes) in the memory. Further, every byte in the memory has a unique address, and two contiguous bytes
have consecutive addresses. To see this, suppose that the amount of space for each element is k bytes. As
&a[0] is the address of the element with index 0, the indexes of the subsequent elements are &a[0]+k for
index 1, &a[0]+2*k for index 2, &a[0]+3*k for index 3, and so on. That is, the address of a[i] will be
As an example, see Figure 5.1. Here a[] is an integer array and its 1st element a[0] has the address 8D2C; so,
its 2nd element a[1] has the address 8D2C + 4 “ 8D30, 3rd element a[2] will have the address 8D2C + 2*4
“ 8D34, and so on. If b[] is an array of characters, then &b[i] “ &b[0] + i. If the 1st character of b[]
(i.e., b[0]) has the address AC8F, then its 2nd character b[1] will have the address AC8F + 1 “ AC90, its
3rd character b[2] will have the address AC8F + 2 “ AC91, and so on.
Third, the index need not be just a single variable but can also be an expression whose value is an integer
in the interval r0, n-1s, where n is the number of elements in the array. For example, in an array a[] with
100 elements, a[i+2*j] is a valid element with i and j as two integers, as long as the value of the expression
i+2*j lies in r0, 99s.
Another example could be a[b[i]], where the element b[i] of an array b[] acts as the index of an
element in the array a[]. Such kinds of indexing are sometimes required while writing codes for tricky
problems. For example, see the following code. It takes as input some integers in r0, 9s, stores them in an
array a[], and then prints them in increasing order, avoiding repetitions. It uses an additional array b[],
initialized with all zeros, to count the frequency of each distinct element stored in a[]. Since there will be
at most 10 distinct elements in a[], the size of b[] is set to 10. The trick is that b[a[i]] means how many
times an element a[i] appears in a[].
1 #include <stdio.h>
2
3 int main() {
4 int n, i, j;
5 printf("Enter the number of elements: ");
6 scanf("%d", &n);
7 int a[n], b[10];
8 for (i = 0; i < 10; i++)
9 b[i] = 0;
10
©Partha Bhowmick
Chapter 5. One-dimensional arrays 43
25 return 0;
26 }
27 /*
28 Enter the number of elements: 13
29 Enter the elements (0 to 9): 5 4 7 8 4 0 4 4 0 5 7 8 7
30 Sorted array: 0 4 5 7 8
31 */
type array_name[size];
where type specifies the type of elements (char, int, float, etc.) that will be stored in the array, array_name
denotes the name of the array, and size is the maximum number of elements that can be stored in the array.
Here are some examples:
In the above examples, all three arrays are declared to contain 5 elements each, and their values are initialized.
We can also declare them to contain more elements, say 10 each, but only the first five are initialized. Here
is how:
©Partha Bhowmick
44 Chapter 5. One-dimensional arrays
When you partially initialize an array in C, the uninitialized elements are automatically set to 0 for numeric
arrays and ‘\0’ (null character) for character arrays. The non-initialized as well as the initialized values
can be changed later if needed. Here’s what happens in the above cases:
int a[5], i;
for (i=0; i<5; i++){ // writing to a[]
scanf("%d", &a[i]);
}
int p;
for (i=0; i<5; i++){ // reading from a[]
p = a[i];
}
We cannot use the operator = to assign one array to another; i.e., even if a[] and b[] are two arrays of
same type and same size, then a = b; or a[] = b[]; cannot copy the elements of b[] to a[] (it will give
compilation error). For copying the elements of b[] to a[], we have to use a loop as follows:
int i;
for (i=0; i<n; i++){ // n = number of elements in a[] and in b[]
a[i] = b[i];
}
As a specific example, suppose that there are at most 100 students in a class. Now, consider the problem
of getting their marks and finding how many of them have marks above the average. Clearly, following are
there main tasks:
1. Read the marks as input and write them in an array.
2. Compute the total marks.
3. Count how many students meet the given criterion.
Clearly, Task 1 and Task 2 can be done in a single loop. But Task 3 needs an additional loop after that
because it can be done only after Task 2 is over. That is, it is impossible to write a code for this problem
using a single loop only. (Understand the importance of this observation!) The following code is written
based on this observation. Notice that for Task 1, we are writing into the array using the indexes, while for
Task 2 and Task 3, we are reading from the array using the indexes again. In either case, the integer i is
used as the index variable.
©Partha Bhowmick
Chapter 5. One-dimensional arrays 45
1 #include <stdio.h>
2 int main(){
3 int n, i, k;
4 float marks[100], total, avg;
5 printf("Enter the number of students: ");
6 scanf("%d", &n);
7 printf("Enter their marks: ");
8 for (i=0, total=0; i<n; i++){ // Task 1 and Task 2
9 scanf("%f", &marks[i]);
10 total = total + marks[i];
11 }
12 avg = total/n;
13 for (i=0, k=0; i<n; i++){ // Task 3
14 k += (marks[i] > avg) ? 1 : 0;
15 }
16 printf("Number of students above the average = %d\n", k);
17 }
3 #include <stdio.h>
4 #define SIZE 1000
5
6 int main(){
7 int a[SIZE], n, i, max;
8
9 printf("Enter n: ");
10 scanf("%d", &n);
11 printf("Enter the elements: ");
12
16 max = a[0];
17
©Partha Bhowmick
46 Chapter 5. One-dimensional arrays
19 if (max<a[i])
20 max = a[i];
21
3 #include <stdio.h>
4 #define SIZE 1000
5
6 int main(){
7 int a[SIZE], n, i, j, flag = 1;
8
9 printf("Enter n: ");
10 scanf("%d", &n);
11 printf("Enter the elements: ");
12
25 if(flag)
26 printf("Distinct.\n");
27
28 return 0;
29 }
3. rFibonacci sequences The Fibonacci sequence tf piq : i “ 0, 1, 2, . . .u is defined as
1 // Fibonacci sequence
2
3 #include <stdio.h>
4 #define SIZE 1000
5
6 int main(){
7 int a[SIZE], n, i;
8
©Partha Bhowmick
Chapter 5. One-dimensional arrays 47
9 printf("Enter n: ");
10 scanf("%d", &n);
11 a[0] = 0, a[1] = 1;
12
21 return 0;
22 }
4. rSelection Sort: positive elements, extra arrays Given a positive integer n as the first input, take
in as the next input n positive integers from the user and store them in an array A. Take another
array B of the same size and put the elements of A into B in non-decreasing order. For example, if
A “ r4, 2, 3, 2, 6, 4s, then B “ r2, 2, 3, 4, 4, 6s.
3 #include <stdio.h>
4 #define SIZE 1000
5
6 int main(){
7 int a[SIZE], b[SIZE], n, i, j, max;
8
9 printf("Enter n: ");
10 scanf("%d", &n);
11 printf("Enter the elements (all positive): ");
12
32 return 0;
33 }
5. rArray unions Given two arrays A and B containing m and n integer elements respectively, find the
©Partha Bhowmick
48 Chapter 5. One-dimensional arrays
elements in A Y B, store them in another array C, and print C. Assume that all elements of A are
distinct, and so also for B, although an element of A may be present in B.
1 // Array union
2
3 #include <stdio.h>
4 #define SIZE 1000
5
6 int main(){
7 int a[SIZE], b[SIZE], c[2*SIZE], m, n, i, j, k, flag;
8
9 printf("Enter m: ");
10 scanf("%d", &m);
11 printf("Enter the elements of a[]: ");
12 for(i=0; i<m; i++)
13 scanf("%d", &a[i]);
14
15 printf("Enter n: ");
16 scanf("%d", &n);
17 printf("Enter the elements of b[]: ");
18 for(i=0; i<n; i++)
19 scanf("%d", &b[i]);
20
38 printf("c[] = ");
39 for(i=0; i<k; i++)
40 printf("%d ", c[i]);
41 printf("\n");
42
43 return 0;
44 }
6. rClosest pair in 2Ds Given an integer n ě 2, followed by a sequence of n distinct points with real
coordinates, determine a pair of closest points. You can store the x-coordinates and the y-coordinates
in two arrays.
1 #include<stdio.h>
2 #include <float.h>
©Partha Bhowmick
Chapter 5. One-dimensional arrays 49
4 int main(){
5 float x[100], y[100]; // assuming that there are at most 100 points
6 int n, i, j, p, q;
7 float dcur, dmin; // we consider the squares of distances; need not use math library
8 dmin = FLT_MAX; // the maximum value of a float
9
©Partha Bhowmick
50 Chapter 5. One-dimensional arrays
compute the values of for k “ 0, 1, . . . , n, using the value of n as input. You should do it with a
` n˘
k
single array.
5. (Selection Sort: positive and distinct elements, extra array) Given a positive integer n as the
first input, take in as the next input n positive integers from the user and store them in an array A.
Take another array B of the same size and put the elements of A into B so that they are in increasing
order and all the elements of B are distinct. For example, if A “ r4, 2, 3, 2, 6, 4s, then B “ r2, 3, 4, 6s.
Since the size of B is same as that of A, you have to keep track of the number of elements in B.
6. (Selection Sort) Given a positive integer n as the first input, take in as the next input n integers
from the user and store them in an array A. Without using any extra array, rearrange the elements
in non-decreasing order. For example, if input is A “ r4, ´2, 3, 0, ´2, 6, 4s, then the output will be
A “ r´2, ´2, 0, 3, 4, 4, 6s.
7. (Array intersection) Given two arrays A and B containing m and n integer elements respectively,
find the elements in A X B, store them in another array C, and print C. Assume that all elements of A
are distinct, and so also for B.
8. (Maximum collinearity) Given an integer n ě 2, followed by a sequence of n distinct points with
integer coordinates, determine the maximum number of collinear points. You can store the x-coordinates
and the y-coordinates in two arrays.
©Partha Bhowmick
6 | Functions
A function definition has two parts: header and body (Figure 6.1). The header carries the function prototype
or declaration, which consists of:
1. return data type, i.e., data type of the variable whose value is returned by the function;
1A detailed list of C library functions can be seen at https://en.wikipedia.org/wiki/C_standard_library
51
52 Chapter 6. Functions
argument types
function name argument names
return
data type float dis(int a, int b){ header = protoype or delclaration
float x = a*a+b*b;
body = definition
return statement return sqrt((float)x);
}
Figure 6.1: Components of a user-defined function named dis. Notice that dis calls another function, sqrt,
which is defined in the math library.
function name
no argument
return
int main(){ header = protoype or delclaration
data type
int a, b;
printf("Enter a, b: ");
scanf("%d%d", &a, &b); body = definition
Figure 6.2: Calling the function dis from main(). Here, dis is the called function, and main() the caller.
©Partha Bhowmick
Chapter 6. Functions 53
function because the latter calls the former. If fact were placed after npr, a compilation error would occur,
as a called function must be defined before its caller if no prototypes are declared separately.
3 #include <stdio.h>
4
8 int main(){
9 int i, n;
10 printf("Enter n: ");
11 scanf ("%d", &n);
12 for (i=1; i<=n; i+=1)
13 printf ("%d choose %d = %d \n", i, n, npr(n, i));
14 }
15
3 #include <stdio.h>
4
16 int main(){
17 int i, n;
18 printf("Enter n: ");
19 scanf ("%d", &n);
20 for (i=1; i<=n; i+=1)
21 printf ("%d choose %d = %d \n", i, n, npr(n, i));
22 }
©Partha Bhowmick
54 Chapter 6. Functions
if n “ 1
"
1
n! “
n ¨ pn ´ 1q! otherwise.
We could make an equivalent code with the recursion written before the base condition, which would look
as follows.
Although both are correct, the latter is a bad coding style because the memory requirement of the recursion
stack will be more compared to the former. So, unless there is any compelling reason, base condition should
be written before recursion while writing a recursive function.
©Partha Bhowmick
Chapter 6. Functions 55
The variables declared inside a function are said to be its local variables. Called so because there is a
concept of global variables on the contrary, which are declared outside all functions, i.e., just after all
#include statements and before the main(). The local variables can be accessed only within the function
in which they are declared. Local variables cease to exist when the function terminates. Each execution of
the function uses a new set of local variables, and input arguments or parameters are also local in the same
sense.
For example, in Figure 6.1, x is a local variable of dis, whereas a and b are its two input parameters.
Know that the input parameters a and b of dis are physically different from the local variables a and b in
main() (Figure 6.2). Yes, although their names in dis are same with those in main(), they are physically
different! This is because they have different addresses in the memory. It is analogous to our very common
experience that two persons from two different families may have the same name!
The scope of a variable means the part of the program that can use the value of the variable. It is basically
the block in which it is defined. Recall that a block means the sequence of statements enclosed within two
matching curly brackets.
For a local variable, the scope the entire function in which it is defined, provided it is declared in the
very beginning of the body of the function. Two local variables of two functions can have the same name, but
they are actually different variables because the variable name works as its first name whereas its surname
is the function name.
Any global variable, since being declared outside all functions including main(), has its scope all over
the program by default. However, it scope will be hidden in a block if a local variable of the same name is
defined in that block. Use of global variables, unless there is a compelling reason, should be avoided.
Here is an example showing how a global variable A is declared and used by two different functions,
namely main() and myProc(). The value of A is printed twice: first from myProc() and then from main().
Since myProc() changes the value of A to 2 and main() reads that value later, in both cases, the printed
value will be 2.
1 #include <stdio.h>
2 int A; // This A is a global variable
3 void main(){
4 A = 1;
5 myProc();
6 printf("A = %d\n", A);
7 }
8
9 void myProc(){
10 A = 2;
11 printf("A = %d\n", A);
12 }
In the following code, note that the declaration int A = 2; in myProc() creates an integer variable
with the same name, A. This A is local to myProc(), and when it is printed, the output is 2. This does not
affect the value of the global variable A. Consequently, when A is printed from main(), the output is 1, which
is the value of the global variable A.
©Partha Bhowmick
56 Chapter 6. Functions
1 #include <stdio.h>
2 int A; // This A is a global variable
3 void main(){
4 A = 1;
5 myProc();
6 printf("A = %d\n", A);
7 }
8
9 void myProc(){
10 A = 2;
11 printf("A = %d\n", A);
12 }
This practice of declaring local and global variables with the same name should be avoided when writing
code.
©Partha Bhowmick
Chapter 6. Functions 57
the technique discussed in §5.2. Clearly, this address is address is same to both the caller and the called for
any element of the array, and it is also accessible to both of them. Hence, any change made to any element
inside the called function is eventually reflected in the calling function, once the called function ends. In the
following code, for example, the elements of a 5-element array are squared in the called function, and when
printed from the caller, the squared elements will be printed as desired.
int main(){
int a[] = {3, -2, 1, 2, 1};
doSqr(A, 5);
for(int i=0; i<5; i++)
printf("%d ", a[i]); // will print 9 4 1 4 1
return 1;
}
if n “ 1
"
1
Direct recursion: f pnq “
n ¨ f pn ´ 1q otherwise.
if n “ 1
"
1
Indirect recursion: gpnq “
n ¨ hpn ´ 1q otherwise.
if n “ 1
"
1
Indirect recursion: hpnq “
1 ` gpn ´ 1q otherwise.
An important property of recursion is that when the recursive function is called next time, it acts on
a smaller input, and so eventually the recursion reaches a/the base case. For example, in Figure 6.3, the
base case is for 1, and from that point the recursion wraps up, to get the values of fact(2), fact(3),
and fact(4), in that order. This ‘wrapping up’ is referred to as backtracking. Notice that the C function
fact(n) is basically the mathematical function f pnq mentioned above.
As evident from Figure 6.3, upon reaching the base case, that recursive call ends, and the program
control backtracks to the previous call. The previous recursive call may have some pending instructions, and
those pending instructions are all stored in the memory in a generic data structure called stack, which in
this context is particularly referred to as recursion stack. In the example of fact(4), the stack contains all
the pending instructions of fact(4), fact(3), and of fact(2) when it reaches fact(1). While a recursion
unfolds, the stack grows up, and when backtracking starts, it shrinks down (Figure 6.4).
The stack maintains all the records (i.e., pending instructions and associated data) of all the unfinished
recursive calls in an orderly manner. The last record is of the last recursive call, and while backtracking,
it is the last record which is first processed. For example, the record of fact(2) is first processed while
backtracking after reaching the base condition (Figure 6.4). These records are called activation records and
need to be stored in LIFO order (Last In, First Out), and so the data structure is stack. An activation
record of a function call contains several parts including its return address, arguments, and local variables.
©Partha Bhowmick
58 Chapter 6. Functions
fact(4) 4*6 = 24
1st recursion
if(4==1) return 1;
else return 4*fact(3); 3*2 = 6
2nd recursion
if(3==1) return 1;
else return 3*fact(2); 2*1 = 2
3rd recursion
if(2==1) return 1;
else return 2*fact(1); 1
Base case
if(1==1) return 1;
else return 1*fact(0);
Figure 6.3: Recursive steps after calling the function fact(4) from main().
#include <stdio.h>
#define PI 3.14159
int main() {
float radius, perimeter, area;
©Partha Bhowmick
Chapter 6. Functions 59
The #define directive in C not only allows you to define simple constants but also enables the creation
of macros with arguments, which are similar to functions. These macros can take one or more arguments,
and during preprocessing, the arguments are replaced with the values passed when the macro is invoked.
This capability allows you to create flexible and reusable code snippets.
In this example, the macro sqr takes one argument, x. When you use sqr in your code, the preprocessor
replaces it with the expression ((x)*(x)). Here is how you can use it:
is replaced with:
This substitution ensures that the macro works correctly, even if the argument n is an expression rather than
a simple variable. For example, if you write SQR(a+b), the macro expands to ((a+b)*(a + b)), ensuring
that the entire expression is squared.
You have to be careful while defining a macro. For example, if you write #define SQR(x) x*x, then
SQR(a+b) will result in a+b*a+b, which is incorrect.
As you understand now, macros with arguments have definite advantages in coding. First, they simplify
complex expressions by encapsulating them in a single, easy-to-use macro. Second, they are efficient because
they are expanded inline, avoiding the overhead of function calls. Third, they allow you to create reusable
code snippets that can be adapted to different inputs. Some typical use case for macros are given in Table 6.1.
Following is a program where the macro SWAP(a, b, type) is used.
©Partha Bhowmick
60 Chapter 6. Functions
// Calculate the distance between two points (x1, y1) and (x2, y2)
#define DIS(x1, y1, x2, y2) sqrt(((x2)-(x1)) * ((x2)-(x1)) + ((y2)-(y1)) * ((y2)-(y1)))
1 #include <stdio.h>
2
6 int main() {
7 // Declare and initialize variables
8 int x = 10, y = 20;
9 double p = 3.14, q = 2.71;
10 char c1 = ’A’, c2 = ’B’;
11
12 // Swap integers
13 printf("Before swapping: x = %d, y = %d\n", x, y);
14 SWAP(x, y, int);
15 printf("After swapping: x = %d, y = %d\n\n", x, y);
16
17 // Swap doubles
18 printf("Before swapping: p = %.2f, q = %.2f\n", p, q);
19 SWAP(p, q, double);
20 printf("After swapping: p = %.2f, q = %.2f\n\n", p, q);
21
22 // Swap characters
23 printf("Before swapping: c1 = %c, c2 = %c\n", c1, c2);
24 SWAP(c1, c2, char);
©Partha Bhowmick
Chapter 6. Functions 61
27 return 0;
28 }
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <time.h>
4
10 int main() {
11 int a, b;
12 int array[SIZE];
13
©Partha Bhowmick
62 Chapter 6. Functions
22
35 return 0;
36 }
Below is a modified version of the above code in which the seed is an integer r taken in from the user,
rather than using a time-dependent seed. Note that the number of elements is also taken from the user.
1 #include <stdio.h>
2 #include <stdlib.h>
3
6 int main() {
7 int a, b, r, n;
8
9 // Prompt user for the range [a, b], the seed value, and the number of elements
10 printf("Enter the lower bound (a): ");
11 scanf("%d", &a);
12 printf("Enter the upper bound (b): ");
13 scanf("%d", &b);
14 printf("Enter the seed value (r): ");
15 scanf("%d", &r);
16 printf("Enter the number of elements (n): ");
17 scanf("%d", &n);
18
22 // Fixed-size array
23 int arr[100];
24
©Partha Bhowmick
Chapter 6. Functions 63
43 return 0;
44 }
Here are the outputs for two different seeds provided by the user, while the interval [a,b] remains
unchanged. Notice how the outputs differ due to the variation in seeds.
This allows the program to dynamically adjust its behavior based on the provided inputs, making it more
versatile and interactive.
Here is a C program that takes numbers as command-line arguments and prints their square roots to
the terminal:
1 #include <stdio.h>
2 #include <stdlib.h> // Include stdlib.h for atof()
3 #include <math.h> // Include math.h for sqrt()
©Partha Bhowmick
64 Chapter 6. Functions
24 return 0;
25 }
Here is another C program where the input file contains some numbers, and the output file will store
their square roots:
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <math.h>
4
©Partha Bhowmick
Chapter 6. Functions 65
21 return 1;
22 }
23
24 // Read each number, calculate its square root, and write to the output file
25 while (fscanf(inputFile, "%lf", &num) != EOF) {
26 fprintf(outputFile, "Square root of %.2lf is %.4lf\n", num, sqrt(num));
27 }
28
33 return 0;
34 }
1 #include <stdio.h>
2 #include <math.h>
3
int main(){
14
15 int n;
16 printf("Enter a positive integer: ");
17 scanf("%d", &n);
18 for(int j=3; j<=n; j++)
19 if(checkPrime(j))
20 printf("%d is prime\n", j);
21 return 0;
22 }
2. n choose r: nr Write two functions of the following prototypes:
“ ` ˘‰
get the values of n!, r!, and pn ´ rq!. Scan a positive integer n from main() and print the values of nr
` ˘
for r P r0, ns, by calling the function ncr in a loop. For example, for n “ 5, it will print 1, 5, 10, 10, 5, 1.
©Partha Bhowmick
66 Chapter 6. Functions
1 #include <stdio.h>
2
6 int main(){
7 int i, n;
8 printf("Enter n: ");
9 scanf ("%d", &n);
10 for (i=0; i<=n; i+=1)
11 printf ("%d choose %d = %d \n", i, n, ncr(n, i));
12 }
13
3 #include <stdio.h>
4
9 int main(){
10 float a, b, c, x;
11 printf("\nEnter a, b, c, x: ");
12 scanf("%f%f%f%f", &a, &b, &c, &x);
13 printf("f = %f\n", f(a,b,c,x));
14 return 0;
15 }
4. rArithmetic and geometric meanss Write a function to compute and print the arithmetic mean and
the geometric mean of n real numbers, with n and an n-element array as arguments. The value of n and
the array elements will be supplied as input from main(). The math library can be used, but only for
the pow() function.
3 #include <stdio.h>
4 #include <math.h>
5 #define SIZE 1000
©Partha Bhowmick
Chapter 6. Functions 67
18 int main(){
19 int n, i;
20 float a[SIZE];
21
22 printf("Enter n: ");
23 scanf("%d", &n);
24 printf("Enter the elements: ");
25
29 computeAMGM(n, a);
30
31 return 0;
32 }
5. rMedians Write a function to compute and return the median of n integers, with n and an n-element
array as arguments. Scanning the value of n along with the array elements, and printing the me-
dian, should all be done from main(). Assume that n is odd and all elements are distinct. Then, exactly
2 elements of the array will be smaller that the median—a fact that can be used to write the function.
n´1
3 #include <stdio.h>
4 #define SIZE 1000
5
©Partha Bhowmick
68 Chapter 6. Functions
23 if (k==n/2){
24 m = a[i];
25 break;
26 }
27 }
28 return m;
29 }
30
31
32 int main(){
33 int a[SIZE], n, m;
34
35 n = readInput(a);
36 m = findMedian(a, n);
37 printf("Median = %d\n", m);
38
39 return 0;
40 }
6. rGCD function, recursives Write a recursive function of the prototype int gcd(int, int) to com-
pute the GCD of two numbers, using Eq. 4.1. Take in two positive integers m, n from main(), call
gcd(m,n) from main(), and print its returned value from main().
3 #include <stdio.h>
4
10 int main(){
11 int m, n;
12 printf("\nEnter two positive integers: ");
13 scanf("%d%d", &m, &n);
14 printf("GCD = %d\n", gcd(m,n));
15 return 0;
16 }
17
7. rGCD function, iteratives Write an iterative version of the GCD function using Eq. 4.1, keeping the
main() same as the recursive version.
1 //GCD function
2
3 #include <stdio.h>
4
©Partha Bhowmick
Chapter 6. Functions 69
12 return b;
13 }
14
15 int main(){
16 int m, n;
17 printf("\nEnter two positive integers: ");
18 scanf("%d%d", &m, &n);
19 printf("GCD = %d\n", gcd(m,n));
20 return 0;
21 }
22
8. rGenerate all possible permutations of an arrays Write a recursive function to generate all possi-
ble permutations of a random array. The seed, the number of elements, and the range of elements are
taken in as input from the user. The function should generate permutations by swapping each element
with the first element and then recursively permuting the remaining sub-array. This problem inherently
relies on recursion to explore all possible orderings of the array elements.
1 #include <stdio.h>
2 #include <stdlib.h>
3
34 int main() {
35 int n, seed, a, b;
36
37 // Take user input for the seed, number of elements, and the range [a, b]
©Partha Bhowmick
70 Chapter 6. Functions
65 return 0;
66 }
Here is a output of the above code:
Enter the seed: 1
Enter the number of elements: 3
Enter the range [a, b]: 1 9
Generated array: 2 8 1
Permutations:
2 8 1
2 1 8
8 2 1
8 1 2
1 8 2
1 2 8
1. rValues of a quadratic sequences Write a function to compute the value of x2 ` bx ` c with b and c
as positive integers and x as real, taken as arguments in that order. Scan their respective values from
main(), call that function from main() for every integer value of x ranging from ´10 to 10, and print
every returned value from main(). That is, the function will be called 21 times from main().
2. rFibonacci function, recursives Write a recursive function of the prototype int f(int) to compute
the nth Fibonacci term, f pnq, using Eq. 5.1. Take in a positive integer n from main(), call f(n) from
main(), and print its returned value from main().
©Partha Bhowmick
Chapter 6. Functions 71
3. rFibonacci function, iteratives Write an iterative version of the Fibonacci function using Eq. 5.1,
keeping the main() same as the recursive version.
4. rTwo-element sum as an element in anothers Read in two integers m and n. Assume that both
m and n are in r2, 100s. Take in m integers to an array a[] and n integers to an array b[]. Write a
function that can be called from main to check whether there are two elements in a[] that add up to a
single element in b[]. The arguments of that function should be a[], b[], m, and n.
©Partha Bhowmick