Coding Techniques Notes
Coding Techniques Notes
Efficiency- Precise control over computer resources which results into efficient
implementation complex algorithms is possible under C.
Problem-solving – In C, structured approaches to solving computational
problems can be effectively implemented through algorithms.
Foundation for advanced concepts – Learning more advanced programming
languages and concepts can be based on understanding C and algorithms.
Versatility- Different platforms and systems can apply algorithms developed in
C due to wide range applicability of C.
Performance optimization-C’s low level capabilities allow fine tuning of
algorithm.
Example:
Problem statement: Write a C program to calculate the factorial of a given
number.
Flow lines: Flow lines indicate the exact sequence in which instructions are
executed. Arrows represent the direction of flow of control and relationship
among different symbols of flowchart.
1.Draw a flowchart to input two numbers from the user and display the
largest of two numbers
1.4.Fundamental Algorithms
Problem
This means that memory cell or variable a contains the value 721, and memory
cell or variable b contains the value 463. Our task is to replace the contents of a
with 463, and the contents of b with 721. In other words we want to end up
with the configuration below:
To change the value of a variable we can use the assignment operator. Because
we want a to assume the value currently belonging to b, and b the value
belonging to a we could perhaps make the exchange with the following
assignments:
a := b (1)
b := b (2)
where ":=" is the assignment operator. In (1) ":=" causes the value stored in
memory cell b to be copied into memory cell a.
Let us work through these two steps to make sure they have the desired effect.
The assignment (1) has changed the value of a but has left the value of b
untouched. Checking with our target configuration we see that a has assumed
the value 463 as required. So far so good! We must also check on b. When the
assignment step (2) i.e. b:= a is made after executing step (1) we end up with:
In executing step (2), a is not changed while b takes on the value that currently
belongs to a. The configuration that we have ended up with does not represent
the solution we are seeking. The problem arises because in making the
assignment:
a := b
we have lost the value that originally belonged to a (i.e. 721 has been lost). It is
this value that we want b to finally assume. Our problem must therefore be
stated more carefully as:
What we have done with our present proposal is to make the assignment
In other words when we execute step (2) we are not using the value a that will
make things work correctly because a has already changed. To solve this
exchange problem we need to find a way of not destroying "the old value of a"
when we make the assignment
a := b
t := a;
a := b
We are better off than last time because now we still have the old value of a
stored in t. It is this value that we need for assignment to b. We can therefore
make the assignment
b := t
Rechecking with our target configuration we see that a and b have now been
interchanged as required.
Algorithm Description
Applications
Sorting algorithms
1.4.2. Counting
Problem
Given a set of n students' examination marks (in the range 0 to 100) make a
count of the number of students that passed the examination. A pass is awarded
for all marks of 50 and above.
Algorithm development
After each mark has been processed the current count reflects the number of
students that have passed in the marks list so far encountered. We must now
ask, how can the counting be achieved? From our example above we see that
every time we need to increase the count we build on the previous value. That
is
current_count = previous_count+1
When, for example, we arrive at mark 57, we have
previous_count = 3
Current count therefore becomes 4. Similarly when we get to the next mark
(i.e. 89) the current count of 4 must assume the role of previous_count. This
means that whenever a new current count is generated it must then assume the
role of previous_count before the next mark is considered. The two steps in this
process can be represented by
These two steps can be repeatedly applied to obtain the count required. In
conjunction with the conditional test and input of the next mark we execute
step (1), followed by step (2), followed by step (1), followed by step (2) and so
on.
Because of the way in which previous count is employed in step (1) we can
substitute the expression for previous_count in step (2) into step (1) to obtain
the simpler expression
The current count on the RHS (right-hand side) of the expression assumes the
role of previous count. As this statement involves an assignment rather than an
equality (which would be impossible) it is a valid computer statement. What it
describes is the fact that the new value of current count is obtained by adding 1
to the old value of current_count.
Viewing the mechanism in this way makes it clear that the existence of the
variable previous count in its own right is unnecessary. As a result we have a
simpler counting mechanism.The essential steps in our pass-counting algorithm
can therefore be summarized as:
Before any marks have been examined the count must have the value zero. To
complete the algorithm the input of the marks and the output of the number of
passes must be included. The detailed algorithm is then as described below.
Algorithm description
Applications:
All forms of counting.
Problem
Given a set of numbers, design an algorithm that adds these numbers and
returns the resultant sum. Assume n is greater than or equal to zero.
Algorithm development
One of the most fundamental things that we are likely to do with a computer is
to add a set of n numbers. When confronted with this problem in the absence of
a computer we simply write the numbers down one under the other and start
adding up the right-hand column. For example, consider the addition of 421,
583 and 714..
The assignment operator causes the value resulting from the evaluation of the
right-hand side of statement (1) to be placed in the memory cell allocated to the
variable s.
It would therefore seem reasonable that all constants in expression (1) could be
replaced by variables. We would then have
s := a + b + c (2)
Expression (2) adds any three numbers provided they have been previously
assigned as values or contents of a, b, and e respectively. Expression (2) as the
basis of a program for adding numbers is more general and more useful than
expression (1). It still has a serious deficiency - it can only add sets of three
numbers.
n
or equivalently s = Σ ai (4)
i=1
We could also write a computer program statement somewhat like equation (3)
to add our n numbers but this is not very practical because we want to be able
to change n (we may want to use the program to sum a different sized set of
numbers). We must therefore look for a better mechanism more in keeping with
the way a computer is naturally designed to do things. Several facts about
computers are relevant for our current problem. Firstly, computers are well
suited to do repetitive things. Secondly, the computer's adding device is
designed so that it can only add two numbers at a time. We might therefore ask
how we can formulate an algorithm for the addition of n numbers that makes
best use of these facts.
One way to do this that takes note of the fact that the computer adds two
numbers at a time is to start by adding the first two numbers a1 and a2. That is,
s := a1 + a2 (1)
s := s + a3 (2)
In a similar manner:
From step (2) onwards we are actually repeating the same process over and
over. The only difference is that values of a and s change with each step. For
general ith step we have
s := s+ai+1 (i)
This general step can be placed in a loop to iteratively generate the sum of n
numbers.
s:= s + a1 (1')
The step (1') will be correct provided s:= 0 before this step is executed. It
follows that all sums for n>=1 can be generated iteratively. The instance where
n = 0 is a special case which cannot be generated iteratively. The sum of zero
numbers is zero and so we can generate the first sum directly by the assignment
s:= 0
The core of the algorithm for summing n numbers therefore involves a special
step followed by a set of n iterative steps. That is,
Algorithm description
(b) compute current sum by adding the number read to the most
recent sum.
Applications
Problem
Algorithm development
and by definition
0! = 1
In formulating our design for this problem we need to keep in mind that the
computer's arithmetic unit can only multiply two numbers at a time.
0! = 1
1! = 1 x 1
2! = 1 x 2
3! = 1 x 2 x 3
4! = 1 x 2 x 3 x 4
.
.
.
We see that 4! contains all the factors of 3!. The only difference is the inclusion
of the number 4. We can generalize this by observing that n! can always be
obtained from (n - 1)! by simply multiplying it by n (for n >= 1) That is,
Using this definition we can write the first few factorials as:
1! = 1 x 0!
2! = 2 x 1!
3! = 3 x 2!
4! = 4 x 3! and so on
as:
From step (2) onwards we are actually repeating the same process over and
over. For the general (i+1)th step we have
p := p x i (i+1)
This general step can be placed in a loop to iteratively generate n!. This allows
us to take advantage of the fact that the computer's arithmetic unit can only
multiply two numbers at a time.
In many ways this problem is very much like the problem of summing a set of
n numbers. In the summation problem we performed a set of additions, whereas
in this problem we need to generate a set of products. It follows from the
general (i+1)th step that all factorials for n≥1 can be generated iteratively. The
instance where n = 0 is a special case which must be accounted for directly by
the assignment
The central part of the algorithm for computing n! therefore involves a special
initial step followed by n iterative steps.
Algorithm description
2. Set product p for 0! (special case). Also set product count to zero.
(b) compute the ith product p by multiplying i by the most recent product.
Problem
Algorithm development
1, 3, 5, 7, …
are required. We can easily generate this odd sequence by starting with 1 and
successively adding 2. Our other problem is to compute the general term
, which can be expressed as
The function we need to compute this will involve the following steps:
sign := – sign
This will generate alternating positive and negative terms. This can be
incorporated directly into our term expression. The initial conditions are
therefore
The ith term and summation which can be generated iteratively from their
predecessors are:
Clearly we can only evaluate sin (x) to a finite number of terms. An important
consideration here is the desired accuracy we require for sin (x). Because x is
in the range -1<=x<=1 we can see that the contribution from higher terms
quickly becomes very small. For example the 4th term (i.e. ) makes a
contribution of less than 0.0002. In circumstances like this a useful way to
bring about termination is to fix an acceptable error level (e.g. ) and
generate successive terms until the contribution of the current term is less than
the acceptable error. A detailed error analysis of the problem confirms that this
is an acceptable termination condition. Because the terms alternate in sign we
will have to use the absolute error term value for the termination test.
The overall strategy for our sine function algorithm can be summarized as
follows.
Algorithm description
1. Set up initial conditions for the first term that cannot be computed iteratively.
2. While the absolute value of current term is greater than the acceptable error
do
(a) identify the current ith term,
(c) add current term with the appropriate sign to the accumulated sum
for the sine function.
Since the sine expression involves the calculation of a single value it is best
implemented as a function.
Applications
Mathematical and statistical computations.
Problem
Generate and print the first n terms of the Fibonacci sequence where n≥1. The
first few terms are:
0, 1, 1, 2, 3, 5, 8, 13, ...
Each term beyond the first two is derived from the sum of its two nearest
predecessors.
Algorithm development
The last sentence of the problem statement suggests we may be able to use the
definition to generate consecutive terms (apart from the first two) iteratively.
Let us define:
c new term
When the new term c has been generated we have the third Fibonacci number.
To generate the fourth, or next Fibonacci number, we need to apply the same
definition again. Before we can make this next computation we need to make
some adjustments. The fourth Fibonacci number is derived from the sum of the
second and third Fibonacci numbers. With regard to the definition, the second
Fibonacci number has the role of the term before the preceding term and the
third Fibonacci number has the role of "the preceding term". Therefore, before
making the next (i.e. the fourth) computation we must ensure that:
(a) new term (i.e. the third) assumes the role of the preceding term.
(b) and what is currently the preceding term must assume the role of the term
before the preceding term.
That is,
After making step [5] we are in a position where we can use the definition to
generate the next Fibonacci number. A way to do this is to loop back to step
[3]. Further investigation of steps [3] → [5] indicates they can be placed in a
loop to iteratively generate Fibonacci numbers (for n > 2 ).
Algorithm description
(c) generate next Fibonacci number from most recent pair keeping ‘b’
relevant for next computation;
5. If n even then write out last two Fibonacci numbers else write out second last
Fibonacci number.
Applications
Problem
Design an algorithm that accepts a positive integer and reverses the order of its
digits.
Algorithm development
Input : 27953
Output : 35972
Although we might not know at this stage exactly how we are going to make
this reversal one thing is clear – we are going to need to access individual digits
of the input number. As a starting point we will concentrate on this aspect of
the procedure. The number 27953 is actually
We can get the number 2795 by integer division of the original number by 10
This chops off the 3 but does not allow us to save it. However, 3 is the
remainder that results from dividing 27953 by 10. To get this remainder we can
use the mod function. That is,
27953 mod 10 → 3
Our next major concern is to carry out the digit reversal. When we apply our
digit extraction procedure to the first two digits we acquire first the 3 and then
5. In the final output they appear as:
If the original number was 53 then we could obtain its reverse by first
extracting the 3, multiplying it by 10, and then adding 5 to give 35. That is,
3×10+5 → 35
The last three digits of the input number are 953. They appear in the "reversed"
number as 359. Therefore at the stage when we have the 35 and then extract the
9 we can obtain the sequence 359 by multiplying 35 by 10 and adding 9. That
is,
The last number obtained from the multiplication and addition process is the
"digit-reversed" integer we have been seeking. On closely examining the digit
extraction, and the reversal process, it is evident that they both involve a set of
steps that can be performed iteratively.
We must now find a mechanism for building up the "reversed" integer digit by
digit. Let us assume that the variable dreverse is to be used to build the
reversed integer. At each stage in building the reversed integer its previous
value is used in conjunction with the most recently extracted digit. Rewriting
the multiplication and addition process we have just described in terms of the
variable dreverse we get
The variable dreverse can be used on both sides of this expression. For the
value of dreverse to be correct (ie. dreverse = 3) after the first iteration it must
initially be zero. This initialization step for dreverse is also needed to ensure
that the algorithm functions correctly when the input number to be reversed is
0.
Algorithm description
(a) use the remainder function to extract the rightmost digit of the number
being reversed:
(c) use integer division by 10 to remove the rightmost digit from the number
being reversed.
Applications
Problem
Algorithm development
Because initially we probably have no firm ideas on the mechanism for base
conversion we will begin with some groundwork. We can start by trying to
come to terms with exactly what is a decimal number and an octal number. For
this exploration we can look at some specific examples.
The decimal (i.e. base 10) number 275 by its representation, is seen to consist
of:
The decimal system uses the ten digits 0.1.2.3..... 9 to represent numbers. The
actual position of each digit in a number determines its value. Similar
conventions apply for the octal (or base 8) number system. The octal system
uses only the eight digits 0.1.2.3..... 7 to represent numbers. In the octal system
the position of each digit determines its value in a similar (but different) way to
the decimal system. Taking a few steps ahead for the purposes of illustration it
can be shown that the octal representation of the decimal number 275 is 423.
The octal number consists of:
We now have the essentials for implementing our base conversion algorithm. It
involves an iterative process where successive octal digits are derived as
remainders from a sequence of quotients, each of which is in turn derived from
its predecessor by division by 8. More specifically starting with q := 93 we
have
To get both the quotient q and the remainder r at each step we will need to
employ both the integer division and remainder functions. For the general ith
step we will need
Algorithm description
1 Establish the newbase and initialize the quotient q to the decimal number to
be converted.
3. Repeatedly
(a) compute the next most significant digit (i.e. octal) from the current
quotient q as the remainder r after division by newbase.
(c) increment new digit count ndigit and storer in output array newrep,
(d) compute the next quotient q from its predecessor using integer division
by newbase until the quotient is zero.
Applications
Interpretation of stored computer data and instructions.
1. Problem Understanding:
○ Before you can write an algorithm, you need to fully understand
the problem you’re trying to solve. Ask yourself, "What exactly
needs to be done?" For example, if the task is to find the largest
number in a list, you need to understand what the input will look
like (a list of numbers) and what the output should be (the largest
number in that list).
2. Algorithm Design:
○ Once you understand the problem, you can start thinking about
how to solve it. This is where you outline the steps needed to
reach the solution. For example, if you’re finding the largest
number, your steps might include:
1. Start with the first number in the list.
2. Compare it with the next number.
3. If the next number is larger, remember it as the largest so
far.
4. Continue until you’ve checked all the numbers.
5. The largest number you’ve remembered is your answer.
3. Pseudocode and Flowcharting:
○ Before writing actual code, it’s helpful to write pseudocode,
which is like writing down the algorithm in plain language. It’s
not real code, but it helps you plan out what the code will do.
○ You can also draw a flowchart to visualize the steps. Flowcharts
use different shapes to represent different actions, like decision
points or processes. It’s like a map that shows how your
algorithm will work.
4. Implementation:
○ Now, you translate your algorithm into actual code using a
programming language like C. This is where you take your
pseudocode and turn it into commands that the computer can
execute. For example, if your algorithm is finding the largest
number, you’ll write code that performs the comparisons and
keeps track of the largest number.
5. Testing and Debugging:
○ After writing the code, you need to test it to make sure it works as
expected. Try running it with different inputs to see if it always
gives the correct output. If something goes wrong, this is where
debugging comes in—you’ll need to find and fix the errors in
your code.
6. Optimization:
○ Once your algorithm is working, you can look for ways to make
it better. Maybe you can write it in a way that makes it run faster
or use less memory. This step is about refining your algorithm to
make it as efficient as possible.
Example of an Algorithm
Problem: Let’s say you want to find the largest number out of three given
numbers.
Algorithm:
1. Start.
4. Compare b with c.
6. End.
This example shows how an algorithm breaks down the task of finding the
largest number into simple, logical steps that a computer can follow.
By following these steps in algorithm development, you can create a clear and
effective solution to any problem you want to solve with a computer program.
1. Modularity
By separating these tasks into different modules, you can work on them
independently. If there’s an issue with searching for books, you only need to
check the search module, not the entire program.
Applications:
Scalability refers to how well your software can handle growth. As more data
or users are added, a scalable program continues to perform well without
requiring major changes.
Applications:
3.Memory Management
Example: When you create a program that needs to store data temporarily, you
might allocate memory dynamically (e.g., using malloc() in C). After the data
is no longer needed, you must release that memory using free() to avoid
memory leaks.
Applications:
Error Handling involves writing code that anticipates and deals with potential
errors that could occur during the execution of a program. Good error handling
makes your program more reliable and user-friendly.
Example: Imagine you’re writing a program that reads a file. What if the file
doesn’t exist? Instead of crashing, the program should detect this error and
inform the user, maybe by displaying a message like "File not found."
Applications:
Applications of C Programming
By considering these design principles, you can develop robust, efficient, and
scalable software in C that not only meets current needs but can also adapt to
future challenges.
Unit – II: C PROGRAMMING FUNDAMENTALS
The following table lists down all the important preprocessor directives
Directive Description
1. #define MAX_ARRAY_LENGTH 20
2. #include <stdio.h>
3. #include "myheader.h"
4. #undef FILE_SIZE
5. #define FILE_SIZE 42
6. #ifndef MESSAGE
7. #define MESSAGE "You wish!"
8. #endif
9. #ifdef DEBUG
/* Your debugging statements here */
10. #endif
Example
‐2.0
0.0000234
‐0.22E‐5
2.3.1.2 Character Constant
• Character constants are the constant which use single quotation around characters.
2. Single Character Constant
• It contains a single character enclosed within a pair of single inverted commas both
pointing to the left.
• Eg: ‘s’, ‘M’, ‘3’, etc.
3. String Constant
• A string constant is a sequence of characters enclosed in double quotes, thecharacters
may be letters, numbers, special characters and blank spaces, etc.
• Eg: “Hello”, ”23”, “a”, etc.
Rules for Defining Constants
• It must have at least one digit.
• It can be either positive or negative.
• No commas or blank spaces are allowed.
• Decimal points are not allowed in integer constants, but allowed in real constants.
2.3.2 Variable
• Variables are memory location in computer's memory to store data.
• To indicate the memory location, each variable should be given a unique name called
identifier.
• A variable is an identifier that is used to represent some specified type of information
within a designated portion of the program.
Rules for naming the variables
• Variable name can be composed of letters (both uppercase and lowercase letters),
digits and underscore '_' only.
• The first letter of a variable should be either a letter or an underscore.
• No commas or blank spaces are allowed within a variable name.
• There is no rule for the length of length of a variable. However, the first 31 charactersof a
variable are discriminated by the compiler.
Variable Declaration
• Declaration of variable can be done in the declaration part of the program.
• The variables must be declared before they are used in the program.
Syntax
Data_type variable name;
Example
int a; char
m;float s;
Initializing Variables
• Value can be initialized in the valuable name using an assignment operator = .
Syntax
Data_type variable name = value; (or) variable name=value;
Example
Eg: int x=2; x=2;
Scope of the Variable
• Scope of the variable implies the availability of variables within the program.
• Variables have 2 types of scope.
o Local variables
o Global variables
Local Variables
• Local variables are defined inside a main function block (Or) inside a compound
statement of a function subprogram are called local variables.
Example
function()
{
int i, j;
}
2.3.2.1 Global / External Variables
• The variables that are declared before the function main() are called the global /
external variables.
Eg:
int a, b; // here a,ball is a global variables.
main()
{
……
function()
}
function()
{
…….}
switch( nextMove )
case NORTH:
y++;
break;
// etc.
The compiler will allow the use of ordinary integers with enumerated variables, e.g.
trump = 2; , but it is bad practice.
2.3.2.3 Keywords
• Keywords are the reserved words used by the compiler that have standard and fixed(or)
predefined meaning in ‘C’ Language.
• Those words cannot be changed by the user and they are the basic building blocks for
program statements.
• There are 32 keywords in C language. Some of the keywords are,
Keywords in C Language
auto double int struct do
break else Long switch default
case enum register typedef const
char extern return union if
continue for Signed, void goto
unsigned
float static sizeof short while
Purpose: Provides input/output functions for reading from and writing to streams such as
the console and files.
#include <stdio.h>
int main() {
char name[50];
return 0;
}
#include <stdlib.h>
int main() {
int *arr;
int size = 5;
free(arr);
return 0;
}
malloc: Allocates memory dynamically.
free: Releases dynamically allocated memory.
srand and rand: Seed and generate pseudo-random numbers.
3. math.h
1) #include <stdio.h>
#include <math.h>
int main() {
double x = 2.0;
double result;
return 0;
}
2) #include <stdio.h>
#include <math.h>
int main() {
double num = 16.0;
double sqrt_result = sqrt(num); // Square root
double pow_result = pow(2, 3); // Power function (2 raised to the power of 3)
double ceil_result = ceil(4.3); // Ceiling function (smallest integer not less than 4.3)
printf("Square root of %.1f = %.2f\n", num, sqrt_result);
printf("2^3 = %.1f\n", pow_result);
printf("Ceiling of 4.3 = %.1f\n", ceil_result);
return 0;
}
Purpose: Provides functions for manipulating arrays of characters (strings) and memory
manipulation functions.
#include <stdio.h>
#include <string.h>
int main() {
char str1[20] = "Hello";
char str2[20] = "World";
char str3[20];
// Copying str1 to str3
strcpy(str3, str1);
printf("str3 after strcpy: %s\n", str3);
#include <stdio.h>
#include <ctype.h>
int main() {
char ch = 'A';
if (isalpha(ch)) {
printf("%c is an alphabet character.\n", ch);
}
if (isdigit(ch)) {
printf("%c is a digit.\n", ch);
}
if (isupper(ch)) {
printf("%c is an uppercase letter.\n", ch);
}
if (islower(ch)) {
printf("%c is a lowercase letter.\n", ch);
}
return 0;
}
#include <stdio.h>
#include <time.h>
int main() {
time_t current_time;
struct tm *local_time;
char time_str[100];
• The example above defines two variables with the same storage class. auto can only be
used within functions, i.e. local variables.
2.5.2 register - Storage Class
register is used to define local variables that should be stored in a register instead of RAM.
This means that the variable has a maximum size equal to the register size (usually one
word) and can’t have the unary '&' operator applied to it (as it does not have a memory
location).
{
register int Miles;
}
Register should only be used for variables that require quick access - such as counters. It
should also be noted that defining 'register' goes not mean that the variable will be stored in
a register. It means that it MIGHT be stored in a register - depending on hardware and
implementation restrictions.
2.5.3 static - Storage Class
static is the default storage class for global variables. The two variables below (count and
road) both have a static storage class.
static int Count; int Road;
{
printf("%d\n", Road);
}
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.
static can also be defined within a function. If this is done the variable is initalized at run
time but is not reinitalized when the function is called. This inside a function static variable
retains its value during vairous calls.
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);
}
This will produce following result
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
2.5.4 Extern - Storage Class
extern is used to give a reference of a global variable that is visible to ALL the 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.
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 defined
variable or function.
File 1: main.c
int count=5;
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 extern keyword is being used to declare count in another file.
2.6 Expressions
An expression represents data item such as variables, constants and are interconnected with
operators as per the syntax of the language.
Syntax: variable=expression;
Eg: y=(a/b)+c; z=(a*b)-d;
Type Conversion
• It is a process of converting the type of an expression from one type to another type.
• Eg: x = (int)10.45
Example Program
#include<stdio.h>
#include<conio.h>
void main( )
{
int c;
clrscr( );
c=(int)10.45;
printf("\n Output is:%d",c);
getch( );
}
Output
Output is: 10
1. Primary Expressions:
2. Arithmetic Expressions:
int sum = a + b;
double area = radius * radius * 3.14159;
int quotient = x / y;
3. Relational Expressions:
Operators: Comparison operators such as ==, !=, <, >, <=, >=.
Examples:
if (x == y) {
printf("x is equal to y\n");
}
if (a < b) {
printf("a is less than b\n");
}
4. Logical Expressions:
5. Conditional Expressions:
6. Bitwise Expressions:
Operators: Bitwise operators such as & (AND), | (OR), ^ (XOR), ~ (NOT), << (left
shift), >> (right shift).
Examples:
7. Assignment Expressions:
Operators: Assignment operator = and compound assignment operators like +=, -=,
*=, /=, etc.
Examples:
x = 10;
y += 5;
2.6.2 Evaluation of Expressions
int a = 10, b = 5, c = 3;
int result = (a + b) * c - (a / b);
Output
0
Associativity of operators
2.7.2 Operators
• An operator is a symbol that specifies an operation to be performed on the operands.
Operand
• It is a data item on which operators perform operation.
• Eg: a+b
Here, a, bOperands + Operator
• Floating Point Arithmetic: It requires both operands are float type for arithmetic
operation.
Eg: a+b, a=6.5 b=3.5
a+b, 6.5+3.5 = 10
Sample Program 1:
#include<stdio.h> // Header File
#include<conio.h>
int a=5, b=10; //Global Declaration
void main( ) /* main is the starting of every c program */
{
int c; //Local Declaration
clrscr( );
printf(“ \n The sum of the two values:”);c
= a+b;
printf(“%d”,c);
getch( );
}
Output: The sum of the two values: 15
Sample Program 2:
#include<stdio.h>
#include<conio.h>
void main( )
{
int a=10, b=4, c;
float d=3, e;
clrscr( );
c = a/b;
printf(" \n Value of a/b is:%d",c);
e = a/d;
printf("\n Value of a/d is:%f",e);
getch( );
}
Output
Value of a/b is: 2
Value of a/d is: 3.333333
Relational Operator
• Relational operators are used to compare two or more operands. Operands may be
variables, constants or expression.
• If the relation is true, it returns value 1 and if the relation is false, it returns value 0.
o Relational operators are, <, >, <=, >=, ==, !=
Example Program
#include<stdio.h>
#include<conio.h>
void main()
{
int a,b;
clrscr()
;
printf(“\n Enter the Values of a and b:”);
scanf(“%d%d”,&a,&b);
printf(“\n The Result is”);
printf(“%d”, a<b);
printf(“%d”, a>b);
printf(“%d”, a<=b);
printf(“%d”, a>=b);
printf(“%d”, a==b);
printf(“%d”, a!=b);
getch();
}
Output
Enter the Values of a and b: 4 2
The Result is
0
1
0
1
0
1
Logical Operators
Logical operators are used to combine the results of two or more conditions.
Logical AND – This operator is used where a set of statements are to be executed, if two ormore
expressions are true.
Logical OR – This is used, if either of them is true from two or more condition, then set of
statements are executed.
Logical NOT – This operator reverses the value of the expression it operates on.
Sample Program
#include<stdio.h>
#include<conio.h>
void main()
{
int
c1.c2,c3;
clrscr();
printf(“Enter the values c1, c2, c3:”);
scanf(“%d%d%d”, &c1,&c2&c3);
if((c1<c2)&&(c1<c3))
printf(“c1 is less than c2 and c3”);if(!(c1<c2))
printf(“\n c1 is greater than c2”);
if((c1<c2)||((c1<c3))
printf(“c1 is less than c2 or c3 both”);getch();
}
Output
Enter the values c1, c2, c3: 9 6 3
C1 is greater than c2
Assignment Operator
• Assignment operators are used to assign a value or an expression or a value of a
variable to another variable.
• Syntax: variable=expression (or) value ;
• Example : x=10; x=a+b; x=y;
• Two types of assignment operator are,
Compound Assignment
Nested Assignment (or) Multiple Assignment
Compound Assignment
Multiple Assignments
• It is used to assign a single value or an expression to multiple variables.
• Syntax: var1=var2=…………..varn=single variable or expression;
Sample Program
#include<stdio.h>
#include<conio.h>
int b=10;
void main( )
{
int a=3, b=5;
clrscr( );
a+=b; // a= a+b
printf(" \n The sum of the two values:%d",a);
getch( );
}
Output:
The sum of the two values: 8
Increment and Decrement Operators
• These are the increment (++) and decrement (--) operators. Both of these are unary
operators.
• The ++ adds 1 to the operand and – subtracts 1 from the operand.
o ++x - Pre Increment (First increment and then return the value)
o --x - Pre Decrement (First decrement and then return the value)
o x++ - Post Increment (First return the value and then increment)
o x-- - Post Decrement (First return the value and then decrement)
Example
Let a=5 and b=10
a++; //a becomes 6
a‐‐; //a becomes 5
++a; //a becomes 6
‐‐a; //a becomes 5
Example Program
#include<stdio.h>
#include<conio.h>
void main()
{
int a=5;
clrscr();
printf(“Post Increment Value a++=%d\n”,a++);
printf(“Pre Increment Value ++a=%d\n”,++a);
printf(“Pre Decrement Value -- a=%d\n”,--a);
printf(“Post Decrement Value a--=%d\n”,a--);
getch();
}
Output:
Post Increment Value a++=5
Pre Increment Value ++a=7
Pre Decrement Value --a=6
Post Decrement Value a--=6
Operator Meaning
& Bitwise AND
| Bitwise OR
^ Bitwise XOR
<< Shift Left
>> Shift Right
~ One’s Complement
Example Program
#include<stdio.h>
#include<conio.h>
void main()
{
int a, b, c;
clrscr();
a=12;
b=25;
c=a&b;
printf(“Bitwise AND=%d”,c);
c=a/b;
printf(“Bitwise OR=%d”,c);
c=a^b;
printf(“Bitwise XOR=%d”,c);
c=~a;
printf(“One’s Complement=%d”,c);
getch();
}
Output:
Bitwise AND=8
Bitwise OR=29
Bitwise XOR=21
One’s Complement= 220
Special Operators
It consists of the following,
Operators Meaning
, Comma Operator
sizeof() Size of Operator
& and * Address Operator / Indirection Operator
. and Member Selection Operator
Comma Operator
• It is used to separate the statement elements such as variables, constants or expression,etc.
sizeof() Operator
• It is a unary operator which is used in finding the size of data type, constant, arrays,
structure etc.
Address Operator / Indirection Operator
• Address Operator (&) - This symbol is used to specify the address of the variable.
• Indirection Operator (*) - It is used to specify the value of the variable.
2.7.3 Associability
"associability" generally refers to the ability to associate or connect with others, often used
in interpersonal or social contexts rather than technical or mathematical ones.
Example Program 2
#include<stdio.h>
#include<conio.h>
void main()
{
clrscr();
char a;
printf(“Enter a Character:”);
a = getchar();
printf(“Answer=”);
putchar(c);
getch();
}
Output
Enter a Character: B Answer = B
Assignment Statements
Simple Assignments
The C-based languages use == as the equality relational operator to avoid confusionwith
their assignment operator.
The operator symbol for assignment:
1. = FORTRAN, BASI C, PL/I, C, C++, Java
2. := ALGOL, Pascal, Ada
Conditional Targets
If
Count1 =0;
Example:
Else
Compound Assignment Operators
The syntax of assignment operators that is the catenation of the desired binary
operator to the = operator.
sum += value; ⇔ sum = sum + value;
C-based languages include two special unary operators that are actually abbreviated
assignments.
They combine increment and decrement operations with assignments.
The operators ++ and -- can be used either in expression or to form stand- alone
single-operator assignment statements. They can appear as prefix operators:
sum = ++ count; ⇔count = count + 1; sum = count;
If the same operator is used as a postfix operator:
sum = count ++; ⇔sum = count; count = count + 1;
Assignment as an Expression:
This design treats the assignment operator much like any other binary operator,
except that it has the side effect of changing its left operand.
Ex:
while ((ch = getchar())!=EOF)
{...} // why ( ) around assignment?
The assignment statement must be parenthesized because the precedence of the
assignment operator is lower than that of the relational operators.
Disadvantage:
Another kind of expression side effect which leads to expressions that is difficult toread
and understand.
For example,
a = b + (c = d / b++) – 1
Denotes the instructions
Assign b to temp
Assign b + 1 to b
Assign d / temp to c
Assign b + c to temp
Assign temp – 1 to a
There is a loss of error detection in the C design of the assignment operationthat
frequently leads to program errors.
if (x = y) ...
instead of
if (x == y)
..
Example
#include<stdio.h>
#include<conio.h>
void main( )
{
int a;
clrscr();
printf("\n Enter the Number:");
scanf("%d",&a);
if(a>10)
{
printf("\n a is greater than 10");
}
getch( ); }
Output:
Enter the Number: 12
a is greater than 10
The if…else statement
• It is basically two way decision making statement used to control the flow of executionand
to carry out the logical test.
• It has two blocks if &else. If block is executed when the condition is true, else blockis
executed when the condition is false.
Syntax
if(condition)
{
true statements;
}
else
{
false statements;
}
Example
#include<stdio.h>
#include<conio.h>
void main( )
{
int a;
clrscr();
printf("\n Enter the Number:");
scanf("%d",&a);
if(a>10)
{
printf("\n a is greater than 10");
}
else
{
printf("\n a is less than 10");
}
getch( );
}
Output:
Enter the number: 2
A is less than 10
4
Enter Your Option: 1
6
The break statement
• It is used to terminate the loop.
• When a break statement is used inside any C loop, then the loop is terminated.
Syntax: break;
continue;
Break Continue
Break statement takes the control to the Continue statement takes the control to the
outside of the loop. beginning of the loop.
• The loop is defined as the block of statements which are repeatedly executed for certain
number of times.
• The loop in a program consists of two parts,
Body of the loop
Control Statement – Used to test the condition
They are three types of loop control statements
while loop
do-while loop
for loop
The while Loop
• The while loop is an entry controlled loop or top tested loop statement, means the
condition is evaluated first if it is true, and then the body of the loop is executed.
• It is a repetitive control structure, used to execute the statements within the body untilthe
condition becomes false.
Syntax
while(condition)
{
……………..
body of the loop;
……………..
}
Example Program
#include<stdio.h>
#include<conio.h>
void main()
{
int x=0;
while(x<10)
{
printf(“%d\n”,x);
x++;
}
getch();
}
Output
0 6
1 7
2 8
3 9
4
5
• The do…while loop is an exit controlled loop or bottom tested loop statement, means the
condition is evaluated last if it is true, and then the body of the loop is executed.
• Loop will be executed at least once even though the condition is false.
• It is also a repetitive control structure, used to execute the statements within the bodyuntil
the condition becomes false.
Syntax
do
{…………..
body of the loop;
…………..
}while(condition);
Example Program
#include<stdio.h>
#include<conio.h>
void main()
{
int
x=0;
do
{
printf(“%d\n”,x);
x++;
}
while(x<4);
getch();
}
Output
0
1
2
3
while do….while
It is an entry controlled loop or top It is an exit controlled loop or bottom
tested loop. tested loop.
First the condition is tested, if it is It executes the body once, after it
true then the block is executed until checks the condition, if it is true the
the condition becomes false. body is executed until the condition
becomes false.
Loop will not be executed if the Loop will be executed at least once
condition is false. even though the condition is false.
Type casting in C involves explicitly converting a variable from one data type to another. This
conversion is necessary when assigning or using variables of different types in expressions,
functions, or assignments where automatic type conversion (coercion) by the compiler may not
suffice or is not desired. Here's a detailed explanation of type casting in C:
Syntax
(type_name) expression
Where:
type_name is the target data type to which you want to convert the expression.
expression is the variable, constant, or expression that you want to convert.Examples
1. Basic Examples
(int) num_float casts the float variable num_float to an integer. This results in num_int being
assigned the value 10, truncating the decimal part.
int a = 10, b = 3;
float result;
result = (float) a / b;
(float) a casts a to a float before division. This ensures that the division result stored in result
(3.3333...) is a float value, not truncated due to integer division.
Loss of Precision: When casting from a larger type to a smaller type (e.g., double to float,
float to int), there may be loss of data or precision. For example, converting 10.5 to an int
results in 10, discarding the fractional part.
Range and Sign: When casting between signed and unsigned types, or when values exceed
the range of the target type, the behaviour can be implementation-defined or lead to
unexpected results. It's important to understand the ranges and behaviours of data types in C.
Pointer Type Casting: Type casting also applies to pointers in C, where you can cast one
pointer type to another, but this requires caution to ensure compatibility and proper
alignment in memory.
2.11 Function
• It is a set of instructions that are used to perform specified tasks which repeatedly
occurs in the main program.
• Functions are a sub-program that contains one or more statements and it performs some
task when called.
• Functions are classified into two types,
o Pre-defined Functions
o User-defined Functions
Pre-defined Functions
• The pre-defined functions or library functions are built-in functions.
• The user can use the functions, but cannot modify the function.
• Example: sqrt()
User-defined Functions
• The functions defined by the user for their requirement are called user-defined
functions.
• Whenever it is needed, the user can modify the function.
• Example: sum(a,b)
Advantages
• The length of the source program can be reduced by dividing into it into smaller
functions.
• It is easy to locate and debug an error.
• It avoids coding of repeated instructions.
How Function Works
• Once a function is called the control passes to the called function.
• The working of calling function is temporarily stopped.
• When the execution of called function is completed then the control returns back to the
calling function and execute the next statement.
Parameters
• It provides the data communication between the calling function and called
function.
• There are two types of parameters. They are,
o Actual Parameters
o Formal Parameters
Actual Parameters
• These are the parameters transferred from the calling function (main program) to the
called function.
Formal Parameters
• These are the parameters which are used in the called function.
Types of Variable
Local and Global Variables
There are two kinds of variables.
1. Local variable
2. Global variable
Local Variable
• The local variable is defined within the body of the function.
• These variables are defined local to that function only or block only, other
function cannot access these variables.
Example
value(int a, int b)
{
int c, d;
}
c and d are local variables.
Global Variable
• Global variables are defined outside the main() function.
• Multiple functions can use these variables.
Example
int m=5,n=10;
main() {
int a,b;
}
m and n are global variables.
Program to demonstrate local and global variables
#include<stdio.h>
#include<conio.h>
int A, B; //Global Variables
int Add()
{
return A + B;
}
int main()
{
int answer; // Local Variable
A=5;
B=7;
clrscr();
answer=Add();
printf(“%d\n”, answer);
getch();
return 0;
Output:
12
The return statement
• The return statement may or may not send back some values to the calling
function.
• Syntax:
return;(Or) return(expression);
Function Prototypes
Explain different function prototypes. (Or) Explain function with and without arguments
with examples for each. (Nov/Dec 2014)
• The functions are classified into the following types depending on whether the
arguments are present or not and whether the value is returned or not.
• A function prototype declaration consists of the function’s return type, name and
argument list.
• It is always terminated with semicolon.
• If the programmer makes mistake, the compiler generates an error message.
• The 4 types of function prototypes are,
Function with no arguments and no return values.
Function with arguments and no return values.
Function with arguments and with return values.
Function with no arguments and with return values.
Function with no arguments and no return values
• In this prototype, no data transfer take place between the calling function and the called
function.
• The function is only executed and nothing is obtained.
• ie., the called program does not receive any data from the calling program and does
not send back any value to the calling program.
• These functions act independently, i.e. they get input and display output in the same
block.
Syntax
• The dotted lines indicate that, there is only transfer of control but no data transfer.
Example Program
#include<stdio.h>
#include<conio.h>
void add(); //Function with No Argument
void main()
{
clrscr();
add(); // Calling Function
getch();
}
void add() //Called Function
{
int a = 35, b = 10; printf("Sum
is: %d",a+b);
}
Output
Sum is: 45
Function with arguments and no return values
• In this prototype, data transfer take place between the calling function and the
called function.
• It is a one way data communication, i.e. the called program receives data from calling
program but it does not return any value to the calling program.
Syntax
• The continuous line indicates data transfer and the dotted line indicates transfer of
control.
Example Program
#include <stdio.h>
#include<conio.h>
void add(int, int); // Function with Argument
void main()
{
int a = 55, b = 10;
clrscr();
add(a,b); // Calling Function
getch();
}
void add(int a, int b) // Called Function
{
printf("Sum is: %d",a+b);
}
Output:
Sum is: 65
Function with arguments and with return values
• In this prototype, data transfer take place between the calling function and the
called function as well as between called function and calling function.
• It is a two way data communication, i.e. the called program receives data from calling
program and it return some value to the calling program.
Syntax
Example Program
#include<stdio.h>
#include<conio.h>
int add(int, int); //Function with Argument
void main()
{
int a = 5, b = 10;
clrscr();
printf("Sum is: %d", add(a,b)); //Calling Function
getch();
}
int add(int a, int b) // Called Function
{
return a+b;
}
Output:
Sum is: 15
Function with no arguments and with return value
• In this prototype, data transfer take place between the called function and the
calling function.
• It is a one way data communication, i.e. the called program does not receives data
from calling program but it return some value to the calling program.
Syntax
Example Program
#include<stdio.h>
#include<conio.h>
int add(); //Function with No Argument
void main()
{
clrscr();
printf("Sum is: %d",add()); //Calling Function
getch();
}
int add() //Called Function
{
int a=8,b=2;
return a+b;
}
Output:
Sum is: 10
Elements of User-defined Function
• To write an efficient user-defined function, the programmer must familiar with
the following three elements.
Function Definition
Function Declaration
Function Call
Function Definition
• A function definition specifies the name of the function, the types and number of
parameters it expects to receive, and its return type.
• Syntax:
return-type function-name(parameters)
{
Body of the Function;
}
Function Declaration
• A function declaration tells the compiler about a function's name, return type, and
parameters.
• Syntax: return_type function name(parameters list);
Rules for declaring a function
• The list of parameter must be separated by comma.
• If the function does not return any value, then the return type void is must.
• If there are no parameters, simply place void in braces.
• The data type of actual and formal parameters must match.
Example
int max(int num1, int num2);
• Parameter names are not important in function declaration only their type is
required.
int max(int, int);
Function Call
• A function can be called by simply specifying the name of the function, return value
and parameters if presence.
Syntax
function name();
function name(parameter);
return value=function name(parameter);
Eg:
All C inbuilt functions which are declared in string.h header file are given below.
The source code for string.h header file is also given below for your reference.
String
Description
functions
strcat ( ) Concatenates str2 at the end of str1
strncat ( ) Appends a portion of string to another
strcpy ( ) Copies str2 into str1
strncpy ( ) Copies given number of characters of one string to another
strlen ( ) Gives the length of str1
Returns 0 if str1 is same as str2. Returns <0 if strl < str2. Returns >0 if str1 >
strcmp ( )
str2
Same as strcmp() function. But, this function negotiates case. “A” and “a” are
strcmpi ( )
treated as same.
strchr ( ) Returns pointer to first occurrence of char in str1
strrchr ( ) last occurrence of given character in a string is found
strstr ( ) Returns pointer to first occurrence of str2 in str1
strrstr ( ) Returns pointer to last occurrence of str2 in str1
strdup ( ) Duplicates the string
strlwr ( ) Converts string to lowercase
strupr ( ) Converts string to uppercase
strrev ( ) Reverses the given string
strset ( ) Sets all character in a string to given character
strnset ( ) It sets the portion of characters in a string to given character
strtok ( ) Tokenizing given string using delimiter
Function Description
This function returns the nearest integer which is less than or equal to the
floor ( )
argument passed to this function.
This function returns the nearest integer value of the float/double/long double
argument passed to this function. If decimal value is from “.1 to .5”, it returns
round ( ) integer value less than the argument. If decimal value is from “.6 to
.9”, it returns the integer value greater than the argument.
This function returns nearest integer value which is greater than or equal to the
ceil ( )
argument passed to this function.
sin ( ) This function is used to calculate sine value.
cos ( ) This function is used to calculate cosine.
cosh ( ) This function is used to calculate hyperbolic cosine.
exp ( ) This function is used to calculate the exponential “e” to the xth power.
tan ( ) This function is used to calculate tangent.
tanh ( ) This function is used to calculate hyperbolic tangent.
sinh ( ) This function is used to calculate hyperbolic sine.
for ex: sqrt(4) will return 2, sqrt(16) will return 4 and it will be same for all the numeric data.
## program: To display square root of natural number less than 10.
#include<stdio.h>
#include<conio.h>
#include<math.h> // for math function int
main()
{
float i,r;
for(i=1;i<=10;i++)
{
r=sqrt(i);
printf("%f n",r);
}
getch();
return 0;
}
Output
1.00
1.41
1.73
2.00
2.24
2.45
2.65
2.83
3.00
3.16
Function is good programming style in which we can write reusable code that can be
called whenever require.
Whenever we call a function then sequence of executable statements gets executed. We
can pass some of the information to the function for processing called argument /
parameter.
There are two ways that the parameters can be passed to a function. They are,
Call by Value (Pass by Value)
Call by Reference (Pass by Reference / Address / Pointers)
Call by Value
This method copies the values of actual parameters into the formal parameters of the
function.
ie., xerox copy of original parameter is created and passed to the called function.
Here, the changes to the formal parameter do not affect the actual parameter.
Example Program
#include<stdio.h>
#include<conoi.h>
void swap(int num1, int num2); //Function Definition
int main()
{
int n1=50, n2=70;
clrscr();
swap(n1, n2); // Calling Function
printf("\n Number 1: %d",n1);
printf("\n Number 2: %d",n2);
getch();
return(0);
}
void swap(int num1, int num2) // Called Function
{
int temp;
temp = num1;
num1 = num2;
num2 = temp;
}
Output
Number 1: 50
Number 2: 70
In the above example, n1 and n2 are the original values and xerox copy of these values
is passed to the function and is copied into formal parameter num1 and num2 variable
of same function respectively.
Call by Reference
It is another way of passing parameters to the function.
While passing parameter using call by address method, we are passing the actual
address of the variable to the called function
.Any changes to the formal parameter will affect the actual parameter.
Example Program
#include<stdio.h>
#include<conio.h>
void swap(int *num1, int *num2); //Function Definition
int main()
{
int n1=50, n2=70;
clrscr();
swap(&n1, &n2); //Calling Function
printf("\n Number 1: %d",n1);
printf("\n Number 2: %d",n2);
getch();
return(0);
}
void swap(int *num1, int *num2) //Called Function
{
int temp;
temp = *num1;
*num1 = *num2;
*num2 = temp;
}
Output:
Number 1: 70
Number 2: 50
In the above example, n1 and n2 are the original values and address of these values is
passed to the function and is copied into formal parameter num1 and num2 variable of
same function respectively
Difference between Call by Value and Call by Reference
Write a simple C program to understand input and output statements using pre-defined
functions.
#include <stdio.h>
int main() {
// Declare variables
int number;
float decimal;
char character;
char string[100];
return 0;
}
Output
Enter an integer: 10
Enter a floating-point number: 3.14
Enter a single character: A
Enter a string: HelloWorld
You entered:
Integer: 10
Floating-point number: 3.14
Character: A
String: HelloWorld
To read two numbers x and n , and compute the sum of geometric progression
1+x+x2+x3+⋯+xn
#include <stdio.h>
#include <math.h> // For the pow() function
int main() {
double x;
int n;
return 0;
}
Output:
#include <stdio.h>
int main() {
int num;
return 0;
}
Output
Enter a number: 121
121 is a palindrome.
#include <stdio.h>
int main() {
int num;
return 0;
}
Output
Enter a number: 28
The factors of 28 are: 1 2 4 7 14 28
Write a C program to find the frequency of each digit in a given number
#include <stdio.h>
#define DIGITS 10
int main() {
int num;
int frequency[DIGITS] = {0}; // Initialize an array to store frequency of digits
return 0;
}
Output:
To process large amount of data, we need a data structure known as Array. An array is a
collection of similar data elements. These data elements have the same data type. The elements of the
array are stored in consecutive memory locations and are referenced by an index also known as the
subscript. Subscript is an ordinary number which is used to identify an element of the array. Some
examples where the concept of an array can be used include:
An array must be declared before being used. Declaring an array means specifying three things
● Data Type : What kind of values it can store, for example int, char, float, double
● Name : To identify the array
● Size : The maximum number of values that the array can hold
type name[size];
The size of the array can be defined as a symbolic constant as shown in the following code.
#include <stdio.h>
#define N 100
main( )
{
int arr[N];
…….
}
C array indices start from 0. So for an array with N elements, the index of the last element is N-1.
1st 2nd 3rd 4th 5th 6th 7th 8th 9th 10th
element element element element element element element element element element
marks[0] marks[1] marks[2] marks[3] marks[4] marks[5] marks[6] marks[7] marks[8] marks[9]
For accessing an individual element of the array, the array subscript must be used.For example, to
access the fourth element of the array, we must write arr[3]. The subscript or index must be an integral
value or an expression that evaluates to an integral value. No single function that can operate on all the
elements of the array. To access all the elements of the array, we must use a loop. That is, we can access
all the elements of the array by varying the value of the subscript into the array. But note that the
subscript must be an integral value or an expression that evaluates to an integral value.
int i, marks[10];
for(i=0; i<10; i++)
marks[i] = -1;
Code to initialize each element of the array to -1
The code accesses every individual element of the array and sets its value to -1. In the for loop,
the first value of marks[0] is set to -1, the value of the index (i) is incremented and the next value, i.e.,
marks[1] is set to -1. The procedure is continued until all the 10 elements of the array is set to -1.
C knows where an individual element of the array is located in the memory. The array name is
a symbolic reference to the address of the first byte of the array. The array name is actually referring to
the first byte of the array. The subscript or the index represents the offset from the beginning of the
array to the element being referenced. With just the array name and the index, C can calculate the
address of any element in the array.
Since an array stores all its data elements in consecutive memory locations, storing just the
base address, i.e., the address of the first element in the array is sufficient. The address of other data
elements can simply be calculated using the base address. The formula for doing this calculation is
Here, A is the array, k is the index of the element for which we have to calculate the address, BA is the
base address of the array A, w is the word size of one element in memory (for eg, the size of int is 2),
and lower_bound is the index of the first element in the array.
Since an array stores all its data elements in consecutive memory locations, storing just the base
address, i.e., the address of the first element in the array is sufficient. The address of other data
elements can simply be calculated using the base address. The formula for doing this calculation is
Example:
Solution:
99 67 78 56 88 90 34 85
Marks [0] [1] [2] [3] [4] [5] [6] [7]
We know that storing an integer value requires 2 bytes, therefore , word size is 2 bytes.
Given an array float avg[]={99.0, 67.0, 78.0, 56.0, 88.0, 90.0, 34.0, 85.0}. Calculate the address of
avg[4] if base address=1000.
Solution:
99 67 78 56 88 90 34 85
avg [0] [1] [2] [3] [4] [5] [6] [7]
We know that storing a floating point number requires 4 bytes, therefore, word size is 4 bytes.
Length of the array is given by the number of elements stored in it. The general formula to
calculate the length of the array is:
Where upper_bound is the index of the last element and lower_bound is the index of the first element
in the array.
Example:
Solution:
Show the memory representation of the array and calculate its length.
2 5 3 1 7
Age[0] Age[1] Age[2] Age[3] Age[4]
Therefore, length=4 – 0 + 1 =5
To store values in the array, there are three ways – first, to initialize the array element at
the time of declaration; second , to input value for every individual element at the run time; third
to assign values to the individual elements. This is shown in fig
Elements of the array can also be initialized at the time of declaration as other variables. When an
array is initialized, we need to provide a value for every element in the array. Arrays are initialized by
writing,
type array_name[size]={list of values};
The values are written within curly brackets and every value is separated by a comma.It is a compiler
error to specify more number of values than the number of elements in the array. When we write,
While initializing the array at the time of declaration, the programmer may omit the size of the array.
For example,
Intmarks[]={98,97,90};
The above statement is absolutely legal.Here the compiler will allocate enough space for all initialized
elements.If the number of values provided is less than the number of elements in the array,the
un-assigned elements are filled with zeros.
90 45 67 85 78
[0] [1] [2] [3] [4]
90 45 0 0 0
[0] [1] [2] [3] [4]
90 45 72 81 63 54
[0] [1] [2] [3] [4] [5]
0 0 0 0 0 0
[0] [1] [2] [3] [4] [5]
An array can be filled by inputting values from the keyboard. In this method, a while/do-while or a for
loop is executed to input the value for each element of the array. For example
inti, marks[10];
for (i=0;i<10;i++)
scanf(“%d”, &marks[i]);
In the code, we start with the index I at 0 and input the value for the first element of the array.since the
array can have 10 elements, we must input values for elements whose index varies from 0 to 9.
Therefore, in the for loop, we test for condition (i<10) which means the number of elements in the
array.
To assign values to individual elements of the array by using the assignment operator. Any value that
evaluates to the data type of the array can be assigned to the individual array element. A simple
assignment statement can be written as:
marks [3]=100;
Here, 100 is assigned to the fourth element of the array which is specified as marks [3]
We cannot assign one array to another array, even if the two arrays have the same type and size. To
copy an array, you must copy the value of every element of the first array into the element of the
second array. The following code illustrates copy an array
int i, arr1[10],arr2[10];
arr[1]={0,1,2,3,4,5,6,7,8,9};
for(i=0;i<10;i++)
arr2[i]=arr1[i];
The code accesses each element of the first array and simultaneously assigns its value to the
corresponding element of the second array. Finally, the index value I is incremented to access the next
element in succession. Therefore, when this code is executed, arr2[0]=arr1[0], arr2[1]=arr1[1],
arrr2[2]=arr1[2], and so on.
We can also use a loop to assign a pattern of values to the array elements. For example, if we want to
fill an array with even integers starting from 0, then we will write the code as
int i, arr[10];
for(i=0;i<10;i++)
arr[i]=i*2;
3.2 TWO –DIMENSIONAL ARRAYS
A one-dimensional array is organized linearly and only in one direction. But at times, we need to store
data in the form of matrices or tables.Here the concept of one-dimensional array is extended to
incorporate two-dimensional data structures. A two –dimensional array is specified using two
subscripts where one subscript denotes row and the other denotes column. C considers the
two-dimensional array as an array of one-dimensional arrays. Fig shows a two –dimensional array
which can be viewed as an array of arrays.
First
Dimension
second dimension
Similar to one-dimensional arrays, two-dimensional arrays must be declared before being used. The
declaration statement tells the compiler the name of the array, the data type of each element in the
array, and the size of each dimension. A two –dimensional array is declared as
data_typearray_name[row_size][column_size];
Therefore, a two dimensional m x n data elements and each element is accessed using two subscripts, I
and j where i<=m and j<=n.
For example, if we want to store the marks obtained by 3 students in 5 different subjects, then we can
declare a two-dimensional array as
int marks[3][5];
A two- dimensional array called marks is declared that hasm(3) rows and n(5) columns. The first
element of the array is denoted by marks[0][0], the second element as marks[0][1], and so on.
Here,marks [0][0]stores the marks obtained by the first student in the first subject, marks[1][0] stores
the marks obtained by the second student in the first subject, and so on.
Rows
Column 0 Column 1 Column 2 Column 3 Column 4
columns
Fig shows a rectangular picture of a two-dimensional array, these elements will be actually stored
sequentially in memory. Since computer memory is basically one-dimensional, a multidimensional
array cannot be stored in memory as a grid.
There are two ways of storing a two- dimensional array in memory. The first way is row major order
and the second is column major order. Let us see how the elements of a 2D array are stored in row
major order. Here , the elements of the first row are stored before the elements of the second and third
row, i.e., the elements of the array are stored row by row where n elements of the first row will occupy
the first n locations.
(0, 0) (0, 1) (0, 2) (0, 3) (1, 0) (1, 1) (1, 2) (1, 3) (2, 0) (2, 1) (2, 2) (2, 3)
When we store the elements in a column major order, the elements of the first column are stored
before the elements of the second and third column, i.e., the elements of the array are stored column
by column where m elements of the first column will occupy the first m locations. This is illustrated in
fig.
(0, 0) (1,0) (2, 0) (3,0) (0, 1) (1, 1) (2, 1) (3, 1) (0, 2) (1, 2) (2, 2) (3, 2)
In one-dimensional arrays, we have seen that computer does not keep track of the address of every
element in the array. It stores only the address of the first element and calculates the addresses of other
elements from the base address. Same is the case with a two –dimensional array. Here also, the
computer stores the base address and the address of the other elements is calculated using the
following formula.
Address(A[I][J])= B_A=w{M(J-1)+(I-1)}, if the array elements are stored in column major order, and
Address(A[I][J])= B_A+w{n(I-1)+(J-1)}, if the array elements are stored in row major order.
Where, w is the word size, i.e., number of bytes required to store element, M is the number of rows,
Nis the number of columns, I and J are the subscripts of the array element, and B_A is the base
address.
Two –dimensional arrays can be used to implement the mathematical concept of matrices. In
mathematics, a matrix is a grid of numbers, arranged in rows and columns. Thus, using
two-dimensional arrays, we can perform the following operations on an mXn matrix.
Bi,j= Aj,i
Sum :Two matrices that are compatible with each other can be added together thereby storing the
result in the third matrix. Two matrices are said to be compatible when they have the same number of
rows and columns. Elements of the matrices can be added by writing:
Difference:Two matrices that are compatible with each other can be subtracted thereby storing the
result in the third matrix. Two matrices are said to be compatible when they have the same number of
rows and columns. Elements of the matrices can be subtracted by writing:
Product: Two matrices canbe multiplied with each other if the number of columns in the first matrix
is equal to the number of rows in the second matrix. Therefore, m X n matrix A can be multiplied with
a pXq matrix if n=p, Elements of the matrices can be multiplied by writing:
MULTIDIMENSIONAL ARRAYS
A multidimensional array in simple terms is an array of arrays. Like we have one index in a one
dimensional array, two indices in atwo-dimensional array, in the same way we have n indices in an n-
dimensional array or multidimensional array. Conversely, an n-dimensional array is specified using n
indices. An n –dimensional m1X m2 X m3X…mn array is a collectionm1*m2 * m3*…*mnelements. In a
multidimensional array, a particular element is specified by using n subscripts as A[I1 ] [I2] [I3]…[In],
where,
A multidimensional array can contain as many indices as needed and the requirement of the memory
increases with the number of indices used. However, practically speaking we will hardly use more
than three indices in any program. Figure 5.32 shows a three- dimensional array. The array has three
pages, four rows, and two columns.
Page 3
Q U
R V
S W
SECOND T X
DIMENSION
(COLUMNS)
I M
FIRST
DIMENSION J N
(ROWS)
K O
Page 2
L P
Page 1
A E
Operations on an Array:
While there are many operations that can be implemented and studied, we only need to be familiar
with the primary ones at this point. An array supports the following operations:
● Traversal
● Insertion
● Deletion
● Search
Other operations include sorting ascending, sorting descending, etc. Let's follow up on these
individually.
Traversal:
Visiting every element of an array once is known as traversing the array.
Why Traversal?
For use cases like:
Insertion:
An element can be inserted in an array at a specific position. For this operation to succeed, the array
must have enough capacity. Suppose we want to add an element 10 at index 2 in the
below-illustrated array, then the elements after index 1 must get shifted to their adjacent right to
make way for a new element.
When no position is specified, it’s best to insert the element at the end to avoid shifting, and this is
when we achieve the best runtime O(1).
Deletion:
An element at a specified position can be deleted, creating a void that needs to be fixed by shifting
all the elements to their adjacent left, as illustrated in the figure below.
We can also bring the last element of the array to fill the void if the relative ordering is not important.
:)
Searching:
Searching can be done by traversing the array until the element to be searched is found.O(n) There is
still a better method. As you may remember, we talked about binary search in some previous
tutorials. Don't forget to look it up if you missed it. We had analyzed both linear and binary search.
This search method is only applicable for sorted arrays. Therefore, for sorted arrays, the time taken
to search is much less than an unsorted array. O(logn)
Sorting:
Sorting means arranging an array in an orderly fashion (ascending or descending). We have different
algorithms to sort arrays.
3.4 Pointers
Pointer is a variable which contains the memory address of another variable. (Or) A pointer is a
variable whose value is the address of another variable.
The memory address is the location where program instructions and data are stored; pointers
can be used to access and manipulate data stored in the memory.
Example
a=10
a🡪 Variable
10🡪 Value
80F🡪 Address
● The variable that holds memory address is called pointer variables.
● A pointer variable is therefore nothing but a variable that contains an address, which is a
location of another variable.
● Value of pointer variable will be stored in another memory location.
Pointer Operator :
Operator Operator Name Purpose
* Value at Operator Gives Value stored at Particular address
Important Notes :
Output:
The address of n is 1002
The Value of n is 20
Features of Pointers
● It is more efficient in handling array and structure.
● It is used for saving memory space.
● It reduces the length and complexity of the program.
● It provides dynamic memory allocation.
Advantages of Pointers
● It is more compact and efficient code.
● It is used to achieve clarity and simplicity.
● It enables us to access the memory directly.
Example Program
#include<stdio.h>
#include<conio.h>
void main()
{
int x=5;
Output
The Value of x = 5
Syntax:data_type *pointer-name;
Eg:int *a;
● The ampersand (&) is an operator, which is used to access the address of a variable and assign
it to a pointer to initialize it.
Dereferencing of Pointer
● Once a pointer has been assigned the address of a variable. To access the value of variable,
pointer is dereferenced, using the indirection operator (*).
Example Program 1
#include<stdio.h>
#include<conio.h>
void main()
{
int x=5; int *a; a=&x;
Output
The Value of x = 5
The Value of x = 5
Example Program2
#include<stdio.h>
#include<conio.h>
void main()
int y=10;
int *a;
a=&y;
Output
The Value of y = 10
Null Pointer
Example
int *a,*b;
a=b=0;
Pointer to Pointer
Example:
int x=10,*a,**b;
a=&x;
b=&a;
Example Program
#include<stdio.h>
#include<conio.h>
void main()
{
int a=10;
int *b,**c;
b=&a;
c=&b;
Output
The Value of a = 10
Incrementing Pointer
Syntax:
Example
#include<stdio.h>
#include<conio.h>
void main()
int i, *ptr;
clrscr();
ptr = a;
printf("\n Address=%x",ptr);
printf("\t Value=%d",*ptr);
ptr++;
getch();
Output:
Decrementing Pointer
Syntax:
Data Type Older Address stored in pointer Next Address stored in pointer after
decrementing (ptr–)
Int 1000 0998
Float 1000 0996
Char 1000 0999
Example
#include<stdio.h>
#include<conio.h>
void main()
int i, *ptr;
clrscr();
ptr = a;
printf("\n Address=%x",ptr);
printf("\t Value=%d",*ptr);
ptr++;
getch();
Output:
Pointer Addition
● In C Programming we can add any integer number to Pointer variable. It is perfectly legal in c
programming to add integer to pointer variable.
Syntax:
int *ptr , n;
ptr = &n ;
ptr = ptr + 3;
Example
#include<stdio.h>
#include<conio.h>
void main()
int a = 5, b = 10;
clrscr();
x = &a, y = &b;
getch();
Output:
15
Pointer Subtraction
● In C Programming we can add any integer number to Pointer variable. It is perfectly legal in c
programming to add integer to pointer variable.
Syntax:
For Example,
int *ptr , n;
ptr = &n ;
ptr = ptr - 3;
Example
#include<stdio.h>
#include<conio.h>
void main()
int a = 5, b = 10;
clrscr();
x = &a, y = &b;
getch();
Output:
-5
Pointer Comparison
● Pointer comparison is valid only if the two pointers are pointing to same array.
● All Relational Operators can be used for comparing pointers of same type.
● All Equality and Inequality Operators can be used with all Pointer types.
● Pointers cannot be Divided or Multiplied.
Example
#include<stdio.h>
int main()
int *ptr1;
float *ptr2;
return(0);
Output:
● Arrays are closely related to pointers in C programming but the important difference between
them is that, a pointer variable can take different addresses as value whereas; in case of array it
is fixed.
Eg:inta[5]={1,2,3,4,5};
Explanation
● a[5] means the array ‘a’ has 5 elements and of integer data type.
● The base address (Assume 4000) of the array starts with 0th element of the array.
● The array is in integer type, the integer will have 2 bytes and hence the address of the next
address element is incremented by 2.
Example
#include<stdio.h>
int main()
char c[4];
int i;
for(i=0;i<4;++i) {
printf("Address of c[%d]=%x\n",i,&c[i]);
return 0;
Output:
Address of c[0]=28ff44
Address of c[1]=28ff45
Address of c[2]=28ff46
Address of c[3]=28ff47
intnum[5];
● In arrays, name of the array always points to the first element of an array.
● Here, address of first element of an array is &num[0].
● Also, num represents the address of the pointer where it is pointing. Hence, &num[0] is
equivalent to arr.
● Also, value inside the address &num[0] and address num are equal. Value in address &num[0]
is num[0] and value in address num is *num.
● Hence, num[0] is equivalent to *arr.
Similarly,
Example
// Program to find the sum of six numbers with arrays and pointers.
#include<stdio.h>
int main()
inti,class[6],sum=0;
printf("Enter 6 Numbers:\n");
for(i=0;i<6;++i){
printf("Sum=%d",sum);
return 0;
}
Output:
Enter 6 Numbers:
Sum=21
#include<stdio.h>
void main()
char *T;
int I,J,K;
char *ARRAY[5]={"SUNIL","ANIL","DILIP","JAY","BHARAT"};
clrscr();
for(I=0;I<5;I++)
printf("%s \t",ARRAY[I]);
printf("\n");
for(I=0;I<4;I++)
{
for(J=0;J<4-I;J++)
{ K=strcmp(ARRAY[J],ARRAY[J+1]);
if(K>0)
T=ARRAY[J];
ARRAY[J]=ARRAY[J+1];
ARRAY[J+1]=T;
} for(I=0;I<5;I++)
printf("%s \t",ARRAY[I]);
getch();
Output:
"SUNIL","ANIL","DILIP","JAY","BHARAT”
#include <stdio.h>
int main()
int num1=5,num2=10;
swap(&num1,&num2); /* address of num1 and num2 is passed to swap function*/
printf("Number 1 = %d\n",num1);
printf("Number 2 = %d",num2);
return 0;
void swap(int *a,int *b) /* pointer a and b points to address of num1 and num2 respectively */
int temp;
temp=*a;
*a=*b;
*b=temp;
Output:
Number 1 = 10
Number 2 = 5
Explanation
● The address of memory location num1 and num2 are passed to function and the pointers *a and
*b accept those values.
● So, the pointer a and b points to address of num1 and num2 respectively.
● When, the values of pointer are changed, the value in memory location also changed
correspondingly.
● Hence, change made to *a and *b was reflected in num1 and num2 in main
function.
Syntax
Example Program
#include<stdio.h>
main()
intarr[3][2] = {
{5, 100},
{10, 101},
{15, 102},
};
int a, b;
for(a=0;a<3;a++)
printf(“address of %d array=%u”,a,&arr[a]);
for(b=0;b<2;b++)
printf(“value =%d”,arr[a][b]);
Output
Address of 0 Array=4000
Value=5
Value=100
Address of 1 Array=4002
Value=10
Value=101
Address of 2 Array=4000
Value=15
Value=102
char *pointer_character;
3.6 STRINGS IN C
A String in C programming is a sequence of characters terminated with a null character ‘\0’. The C
String is stored as an array of characters. The difference between a character array and a C string is
that the string in C is terminated with a unique character ‘\0’.
Declaring a string in C is as simple as declaring a one-dimensional array. Below is the basic syntax for
declaring a string.
char string_name[size];
In the above syntax string_name is any name given to the string variable and size is used to define the
length of the string, i.e the number of characters strings will store.
There is an extra terminating character which is the Null character (‘\0’) used to indicate the
termination of a string that differs strings from normal character arrays.
C String Initialization
A string in C can be initialized in different ways. We will explain this with the help of an example.
Below are the examples to declare a string with the name str and initialize it with “GeeksforGeeks”.
We can initialize a C string in 4 different ways which are as follows:
String literals can be assigned without size. Here, the name of the string str acts as a pointer because it
is an array.
String literals can be assigned with a predefined size. But we should always account for one extra
space which will be assigned to the null character. If we want to store a string of size n then we should
always declare a string with a size equal to or greater than n+1.
We can also assign a string character by character. But we should remember to set the end character as
‘\0’ which is a null character.
We can assign character by character without size with the NULL character at the end. The size of the
string is determined by the compiler automatically.
Note: When a Sequence of characters enclosed in the double quotation marks is encountered by the
compiler, a null character ‘\0’ is appended at the end of the string by default.
C String Example
#include <stdio.h>
#include <string.h>
int main()
// print string
printf("%s\n", str);
int length = 0;
length = strlen(str);
return 0;
Output
Geeks
We can see in the above program that strings can be printed using normal printf statements just like we
print any other variable. Unlike arrays, we do not need to print a string, character by character.
Note: The C language does not provide an inbuilt data type for strings but it has an access specifier
“%s” which can be used to print and read strings directly.
The following example demonstrates how to take string input using scanf() function in C
#include<stdio.h>
int main()
// declaring string
char str[50];
// reading string
scanf("%s",str);
// print string
printf("%s",str);
return 0;
Input
GeeksforGeeks
Output
GeeksforGeeks
You can see in the above program that the string can also be read using a single scanf statement. Also,
you might be thinking that why we have not used the ‘&’ sign with the string name ‘str’ in scanf
statement! To understand this you will have to recall your knowledge of scanf.
We know that the ‘&’ sign is used to provide the address of the variable to the scanf() function to store
the value read in memory. As str[] is a character array so using str without braces ‘[‘ and ‘]’ will give
the base address of this string. That’s why we have not used ‘&’ in this case as we are already
providing the base address of the string to scanf.
// whitespaces
#include <stdio.h>
// driver code
int main()
char str[20];
scanf("%s", str);
return 0;
Input
Output
Geeks
Note: After declaration, if we want to assign some other text to the string, we have to assign it one by
one or use the built-in strcpy() function because the direct assignment of the string literal to character
array is only possible in declaration.
We can use multiple methods to read a string separated by spaces in C. The two of the common ones
are:
We can use the fgets() function to read a line of string and gets() to read characters from the standard
input (stdin) and store them as a C string until a newline character or the End-of-file (EOF) is reached.
// C program to illustrate
// fgets()
#include <stdio.h>
#define MAX 50
int main()
char str[MAX];
puts(str);
return 0;
Input
GeeksforGeeks
Output
String is:
GeeksforGeeks
// scanset characters
#include <stdio.h>
// driver code
int main()
char str[20];
scanf("%[^\n]s", str);
printf("%s", str);
return 0;
}
Input
Output
C String Length
The length of the string is the number of characters present in the string except for the NULL
character. We can easily find the length of the string using the loop to count the characters from the
start till the NULL character is found.
As strings are character arrays, we can pass strings to functions in the same way we pass an array to a
function. Below is a sample program to do this:
#include <stdio.h>
int main()
// to a different function
printStr(str);
return 0;
Output:
String is : GeeksforGeeks
Note: We can’t read a string value with spaces, we can use either gets() or fgets() in the C
programming language.
In Arrays, the variable name points to the address of the first element.
Similar to arrays, In C, we can create a character pointer to a string that points to the starting address
of the string which is the first character of the string. The string can be accessed with the help of
pointers as shown in the below example.
#include <stdio.h>
int main()
printf("%c", *ptr);
ptr++;
return 0;
}
Output
GeeksforGeeks
The C language comes bundled with <string.h> which contains some useful string-handling functions.
Some of them are as follows:
strlen(string_name)
strcpy(s1, s2)
strcmp(str1, str2)
Compares the first string with the second string. If strings are the same it returns 0.
strcat(s1, s2)
Concat s1 string with s2 string and the result is stored in the first string.
strlwr()
strupr()
strstr(s1, s2)
● Function is good programming style in which we can write reusable code that can be called
whenever require.
● Whenever we call a function then sequence of executable statements gets executed. We can
pass some of the information to the function for processing called argument / parameter.
● There are two ways that the parameters can be passed to a function. They are,
⮚ Call by Value (Pass by Value)
⮚ Call by Reference (Pass by Reference / Address / Pointers)
Call by Value
● This method copies the values of actual parameters into the formal parameters of the function.
ie.,xerox copy of original parameter is created and passed to the called function.
● Here, the changes to the formal parameter do not affect the actual parameter.
Example Program
#include<stdio.h>
#include<conio.h>
int main()
clrscr();
getch();
return(0);
int temp;
temp = num1;
num1 = num2;
num2 = temp;
}
Output:
Number 1: 50
Number 2: 70
● In the above example, n1 and n2 are the original values and xerox copy of these values is
passed to the function and is copied into formal parameter num1 and num2 variable of same
function respectively.
Example Program
#include<stdio.h>
#include<conio.h>
int main()
getch();
return(0);
int temp;
temp = *num1;
*num1 = *num2;
*num2 = temp;
Output:
Number 1: 70
Number 2: 50
● In the above example, n1 and n2 are the original values and address of these values is passed to
the function and is copied into formal parameter num1 and num2 variable of same function
respectively.
Difference between Call by Value and Call by Reference
Static Allocation:
When we declare a static or global variable, static allocation is done for the variable. Each static or
global variable is allocated a fixed size of memory space. The number of bytes reserved for the
variable cannot change during execution of the program. Till now we have been using this technique
to define variables, arrays and pointers.
Automatic Allocation
When we declare an automatic variable such as a function argument or a local variable, automatic
memory allocation is done. The space for an automatic variable is allocated when the compound
statement containing the declaration is entered, and is freed when it exits from a compound statement.
Dynamic Allocation:
A third important kind of memory allocation is known as Dynamic allocation. In the following
sections we will read about dynamic memory allocation through pointers.
Till now whenever we needed an array we had declared a static array of fixed size, say
intarr[100];
When this statement is executed, consecutive space for 100 integers is allocated. It is uncommon that
we may be using only 10% or 20% of the allocated space thereby wasting rest of the space. To
overcome this problem and to utilize the memory efficiently C language provides a mechanism of
dynamically allocating memory so that only the amount of memory that is actually required is
reserved. We reserve space only at the run time for the variables that are actually required. Dynamic
memory allocation gives best performance in situations in which we do not know memory
requirements in advance.
C provides four library routines to automatically allocate memory at the run time.
Function Task
Malloc( Allocates memory and returns a pointer to the first byte of
) allocated space
Calloc() Allocates space for an array of elements and initialize them
to zero. Like malloc(), calloc() also returns a pointer to the
memory
free() Frees previously allocated memory
realloc() Alters the size of previously allocated memory
When we have to dynamically allocate memory for variables in our programs then pointers are the
only way to go. when we use malloc() for dynamic memory allocation, then you need to manage the
memory allocated for variables yourself.
Memory Allocation Process
In computer science, the free memory region is called the heap. The size of heap is not constant as it
keeps changing when the program is executed. In the course of program execution, some new
variables are created and some variables cease to exist when the block in which they were declared is
existed. For this reason it is not uncommon to encounter memory overflow problems during dynamic
allocation process. When an overflow condition occurs, the memory allocation functions mentioned
above will return a null pointer.
Let us see how memory is allocated using the malloc(). malloc is declared in <stdlib.h>, so we include
this header file in any program that calls malloc. The malloc function reserves a block of memory of
specified size and returns a pointer of type void. This means that we can assign it to any type of
pointer. The general syntax of the malloc() is
whereptr is a pointer of type cast-type. The malloc() returns a pointer to an area of memory with size
byte-size. For example,
arr=(int*)malloc(10*sizeof(int));
This statement is used to dynamically allocate memory equivalent to 10 times the area of int byes. On
successful execution of the statement the space is reserved and the address of the first byte of memory
allocated is assigned to the pointer arr of type int.
A function pointer, also called a subroutine pointer or procedure pointer, is a pointer referencing
executable code, rather than data. Dereferencing the function pointer yields the referenced function,
which can be invoked and passed arguments just as in a normal function call. Such an invocation is
also known as an "indirect" call, because the function is being invoked indirectly through a variable
instead of directly through a fixed identifier or address.
Function pointers allow different code to be executed at runtime. They can also be passed to a function
to enable callbacks.
Function pointers are supported by third-generation programming languages (such as PL/I, COBOL,
Fortran, dBASE dBL, and C) and object-oriented programming languages (such as C++, C#, and D).
Example
func1 takes one double-precision (double) parameter and returns another double, and is assigned to a
function which converts centimeters to inches.
func2 takes a pointer to a constant character array as well as an integer and returns a pointer to a
character, and is assigned to a C string handling function which returns a pointer to the first occurrence
of a given character in a character array.
return cm / 2.54;
int main(void) {
return 0;
}
The next program uses a function pointer to invoke one of two functions (sin or cos) indirectly from
another function (compute_sum, computing an approximation of the function's Riemann integration).
The program operates by having function main call function compute_sum twice, passing it a pointer
to the library function sin the first time, and a pointer to function cos the second time. Function
compute_sum in turn invokes one of the two functions indirectly by dereferencing its function pointer
argument funcp multiple times, adding together the values that the invoked function returns and
returning the resulting sum. The two sums are written to the standard output by main.
#include <math.h>
#include <stdio.h>
int i;
double y = funcp(x);
sum += y;
double square(double x) {
return x * x;
}
int main(void) {
double sum;
return 0;
}
TWO MARK QUESTIONS
1. What is Pointer? (Or) Define Pointer. (Or) What is the use of Pointers? (Jan 2014)
The memory address is the location where program instructions and data are stored; pointers can be
used to access and manipulate data stored in the memory.
Asterisk (*) indirection operator is used along with pointer variable while dereferencing the pointer
variable.
When used with pointer variable, it refers to variable being pointed to; this is called as Dereferencing
of Pointers.
8. What is the difference between the indirection and address operators? (Or) What is an
address operator and indirection operator? (Nov / Dec 2014) (Nov / Dec 2015)
The indirection operator (*) returns the value of the variable stored in a pointer.
The address operator (&) returns the memory address of the variable.
A null pointer can never point to a valid data. For checking a pointer, if it is assigned to 0, then it is a
null pointer and is not valid.
A character pointer can also be used to access character arrays and string constants in the same way as
accessing numeric arrays using their respective pointer variable.
The compiler treats the subscripts as a relative offset from the beginning of the array.
When a pointer variable is set to the start of an array and is incremented to find the next element,
absolute addressing is being implemented.
Example:
int x=10,*a,**b; a=&x;b=&a;
Library routines known as "memory management functions" are used for allocating and freeing
memory during execution of a program.
14. What are the various dynamic memory allocation functions? (April / May 2017)
realloac() - Used to modify the size of the previously allocated memory space.
15. Difference between Call by Value and Call by Reference. (Or) What is the difference between
pass by value and pass by reference? (May/June 2014)
Call by Value
This method copies the values of actual parameters into the formal parameters of the function.
Here, the changes to the formal parameter do not affect the actual parameter.
Call by Reference
This method copies the addresses of actual parameters into the formal parameters of the function.
Any changes to the formal parameter will affect the actual parameter.
Pointers arithmetic is done by adding, subtracting, comparing, incrementing and decrementing the
values assigned to the pointer variables.
UNIT-4 COLLECTIVE DATA TYPES AND FILE HANDLING
4.1 Structure and Union
Structure
common name
Structure Declaration
The structure can be declared with the keyword struct following the name and
opening braces with data elements of different types, then closing brace with
semicolon.
Syntax
struct structure_name
{
structure element 1;
structure element 2;
…………………….
…………………….
structure element n;
};
struct structure_name v1,v2……vn;
where v1,v2…vn are called as structure variables.
Example
struct Person {
char name[50];
int age;
float salary;
};
Rules for Declaring a Structure
• A structure must end with a semicolon.
• Usually a structure appears at the top of the source program.
• Each structure element must be terminated.
• The members of the structure can be accessed using the structure variables
After declaring the structure type, variables and members, the member of the
structure can be accessed by using the structure variable along with the dot (.)
operator.
Example
struct std
{
int no;
char name[15]; int marks;
};
struct std s;
We can access the structure members from the above example by,
Example 1
struct
{
int sno; float avg;
This assigns the value 39 to std.sno and 39.11 to std.avg. There is a one-to-one
correspondence between the members and their initializing values.
Example 2
struct std
{
int sno; float avg;
main()
{
struct std person1 = {39, 39.11};
struct std person2 = {17, 17.25};
}
C language does not permit the initialization of individual structure member
within the template. The initialization must be done only in the declaration of the
actual variables.
enclosed brackets.
• The uninitialized data members can be initialized by default with zero (0)
Syntax
Array Structure
An array is a Structure is a
collection of similar collection of different
data items of same data items of different
type. type.
{
int regno;
char name[10]; int m1;
};
struct stud s; void main() { float total,avg;
avg=total/3;
printf("\n The student Details are:");
printf("\n %d\t%s\t%f\t%f",s.regno,s.name,total,avg);
}
Output:
Enter the student regno, name, m1, m2, m3:
100
Mani 87
98
78
The student Details are:
100 Mani 263.000000 87.666664
Example
Student Mark Details using Structure
Write a C program to create a mark sheet for students using structure.
#include<stdio.h>
#include<conio.h>
struct stud {
int regno;
char name[10],grade; int m1,m2,m3;
float avg,tot;
} s[10];
void main() { int i,n;
for(i=0;i<n;i++) {
printf("\n Enter the student regno,name,m1,m2,m3:");
scanf("%d%s%d%d%d",&s[i].regno,&s[i].name,&s[i].m1,&s[i].m2,&s[i].m3);
s[i].tot=s[i].m1+s[i].m2+s[i].m3;
else { if(s[i].avg>=75)
s[i].grade='D';
else if(s[i].avg>=60)
s[i].grade='A';
else if(s[i].avg>=50) s[i].grade='B';
printf("\n%d\t%s\t%f\t%f\t%c",s[i].regno,s[i].name,s[i].tot,s[i].avg,s[i].grade);
getch();
Output
Enter the no. of students: b2
Enter the student regno, name, m1, m2, m3: 101 Babu
89
98
78
Enter the student regno, name, m1, m2, m3: 102 Mani
59
68
76
Nested Structure
● Nested structure in C is nothing but structure within structure.
{
int college_id;
char college_name[50];
};
struct student_detail
{
int id;
Output:
Union
Unions are similar to structures but all members share the same memory location.
Only one member can contain a value at any time.
Union provides an efficient way of reusing the memory location, as only one of
its members can be accessed at a time
Union Declaration
union union_name {
datatype member1;
datatype member2;
...
};
We need to define a variable of the union type to start using union members.
There are two methods using which we can define a union variable.
1. With Union Declaration
2. After Union Declaration
union union_name {
datatype member1;
datatype member2;
...
Example of Union
#include <stdio.h>
// driver code
int main()
{
// defining a union variable
union un var1;
return 0;
}
Output
4.2 Enumeration
Definition
Syntax
By default, const1 is 0,const2 is 1 and so on. You can change default values of
enum elements during declaration
When you define an enum type, the blueprint for the variable is created. Here's
how you can create variables
of enum types.
enum boolean {false, true};
enum boolean check; // declaring an enum variable
int main()
{
// creating today variable of enum week type
enum week today;
today = Wednesday;
printf("Day %d",today+1);
return 0;
}
Output
Day 4
Typedef
✔ typedef is a keyword used in C language to assign alternative names to
existing datatypes.
✔ Its mostly used with user defined datatypes, when names of the
datatypes become slightly complicated to use in programs.
Application of typedef
✔ typedef can be used to give a name to user defined data type as well.
✔ Lets see its use with structures.
Example
typedef struct
} type_name;
Example of Structure definition using typedef
#include<stdio.h>
#include<string.h>
}emp;
void main( )
emp e1;
scanf("%s", e1.name);
scanf("%d", &e1.salary);
In C, structures and pointers are fundamental concepts that can be used together
to manage and manipulate complex data efficiently. Understanding how to use
pointers with structures can help you create more dynamic and flexible programs.
Structures in C
A structure (or struct) is a user-defined data type that allows you to group
different types of data under a single name. Here’s a basic example:
#include <stdio.h>
typedef struct {
int id;
char name[50];
float score;
} Student;
int main() {
Student student1;
student1.id = 1;
student1.score = 95.5;
Output:
ID: 1
Name: Alice
Score: 95.50
Pointers to Structures
#include <stdlib.h>
#include <string.h>
typedef struct {
int id;
char name[50];
float score;
} Student;
// Function to create a new student dynamically
if (newStudent == NULL) {
exit(EXIT_FAILURE);
newStudent->id = id;
newStudent->name[sizeof(newStudent->name) - 1] = '\0';
// Ensure null-termination
newStudent->score = score;
return newStudent;
int main() {
printStudent(student1);
free(student1);
return 0;
Output
ID: 1
Name: Alice
Score: 95.50
Explanation:
1. Structure Definition:
o typedef struct is used to define a Student structure with id, name, and
score fields.
2. Dynamic Memory Allocation:
o malloc(sizeof(Student)) allocates memory for a Student structure.
o createStudent function initializes the fields of the structure and returns a
pointer to it.
3. Pointer Access:
o The -> operator is used to access fields of the structure through a pointer.
o printStudent function takes a const Student* pointer and prints the
structure's fields.
4. Memory Management:
o After using malloc to allocate memory, it's crucial to free the allocated
memory to avoid memory leaks.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct {
int id;
char name[50];
float score;
} Student;
int main() {
size_t numStudents = 3;
if (students == NULL) {
exit(EXIT_FAILURE);
}
// Initialize the students
printStudentArray(students, numStudents);
free(students);
return 0;
Output
Explanation:
1. Structure Definition:
o typedef struct is used to define a Student structure with id, name, and
score fields.
2. Dynamic Memory Allocation:
o malloc(sizeof(Student)) allocates memory for a Student structure.
o createStudent function initializes the fields of the structure and returns a
pointer to it.
3. Pointer Access:
o The -> operator is used to access fields of the structure through a pointer.
o printStudent function takes a const Student* pointer and prints the
structure's fields.
4. Memory Management:
o After using malloc to allocate memory, it's crucial to free the allocated
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct {
int id;
char name[50];
float score;
} Student;
// Function to create an array of students dynamically
int main() {
size_t numStudents = 3;
if (students == NULL) {
exit(EXIT_FAILURE);
}
// Initialize the students
printStudentArray(students, numStudents);
free(students);
return 0;
Output
Initializing Structures
Accessing structure member through pointer using dynamic memory
allocation
To access structure member using pointers, memory can be allocated
dynamically using malloc() function defined under "stdlib.h" header file.
#include <stdio.h>
#include <stdlib.h>
struct person {
int age;
float weight; char name[30];
};
int main()
{
struct person *ptr; int i, num;
return 0;
}
Output
Enter number of persons: 2
Enter name, age and weight of the person respectively: Adam
2
3.2
Enter name, age and weight of the person respectively: Eve
6
2.3
Displaying Information: Adam 2 3.20
Eve 6 2.30
Introduction to Files:
unit.
attributes of a file.
● Files are not only used for storing the data, programs are also stored
in files.
How is a file stored?
If you have to enter a large number of data, it will take a lot of time to enter them all.
owever, if you have a file containing all the data, you can easily access the contents of
H
the file using few commands in C.
You can easily move your data from one computer to another without any changes.
Types of Files
⮚ Binary :can contain non-ASCII characters Image, audio, video, executable, etc.
Sequential access:
I n computer science, sequential access means that a group of elements (such as data in a
memory array or a disk file or on magnetic tape data storage) is accessed in a
predetermined, ordered sequence.
Example: JIO
equential access is sometimes the only way of accessing the data, for example if it is on
S
a tape.
It may also be the access method of choice, for example if all that is wanted is to process
a sequence of data elements in order.[1]
I n spatial dimension, request size, strided distance, backward accesses, re-accesses can
affect sequentiality.
For temporal sequentiality, characteristics such as multi-stream and inter-arrival time
threshold has impact on the definition of sequentiality.
I n data structures, a data structure is said to have sequential access if one can only visit
the values it contains in one particular order.
s a result, many algorithms such as quicksort and binary search degenerate into bad
A
algorithms that are even less efficient than their naive alternatives; these algorithms are
impractical without random access.
n the other hand, some algorithms, typically those that do not have index, require only
O
sequential access, such as mergesort, and face no penalty.
Random-Access File
✔ Individual records of a random-access file are normally fixed in length and may
be accessed directly (and thus quickly) without searching through other records.
✔ Example: facebook
✔ Data stored previously can also be updated or deleted without rewriting the entire
file.
1. fseek()
2. ftell()
3. rewind()
fseek():
This function is used for seeking the pointer position in the file at the specified byte.
Where
file pointer It is the pointer which points to the file.
displacement ---- It is positive or negative.This is the number of bytes which are skipped
backward (if negative) or forward( if positive) from the current position.This is attached
with L because this is a long integer.
Pointer position:
This sets the pointer position in the file.
0 Beginning of file.
1 Current position
2 End of file
EX:
1) fseek( p,10L,0)
0 means pointer position is on beginning of the file,from this statement pointer position is
skipped 10 bytes from the beginning of the file.
2) fseek( p,5L,1)
1 means current position of the pointer position.From this statement pointer position is
skipped 5 bytes forward from the current position.
3) fseek(p,-5L,1)
From this statement pointer position is skipped 5 bytes backward from the current
position.
ftell()
This function returns the value of the current pointer position in the file.The value is
count from the beginning of the file.
Syntax: ftell(fptr);
Write a program to read last ‘n’ characters of the file using appropriate file
functions(Here we need fseek() and fgetc()).
#include<stdio.h
>
#include<conio.h>
void main()
FILE *fp;
char ch;
clrscr();
fp=fopen("file1.c", "r");
if(fp==NULL)
else
scanf("%d",&n);
fseek(fp,-n,2);
while((ch=fgetc(fp))!=EOF)
{
printf(“%c\t”, ch);
fclose(fp);
getch();
printf("Group Size = %d\n num1 = %-12d num2 = %-18d num3 = %-24d num4 = %-
30d %d\n", gsize, num1, num2, num3, num4, sum);
}
fclose(inFile);
}
Output
i = 2 number = 2 Sum = 3
Average = 1.50
Group Size = 3
i = 1 number = 1 Sum = 1
i = 2 number = 2 Sum = 3
i = 3 number = 3 Sum = 6
Average = 2.00
Group Size = 4
i = 1 number = 1 Sum = 1
i = 2 number = 2 Sum = 3
i = 3 number = 3 Sum = 6
i = 4 number = 4 Sum = 10
Average = 2.50
–Use fstreamobject
–"Or" file
-open modes together
fstream inOutCredit( "credit.dat", ios::in | ios::out );
4.7 File Handling
4.7.1 Opening and Closing of a File
Open a File in C
For opening a file in C, the fopen() function is used with the filename or file path along
with the required access modes.
Syntax of fopen()
● file_name: name of the file when present in the same directory as the source file.
Otherwise, full path.
● access_mode: Specifies for what operation the file is being opened.
Return Value
File opening modes or access modes specify the allowed operations on the file to be
opened. They are passed as an argument to the fopen() function. Some of the commonly
used file access modes are listed below:
Example of Opening a File
int main()
{
// file pointer variable to store the value returned by
// fopen
FILE* fptr;
Create a File in C
The fopen() function can not only open a file but also can create a file if it does not exist
already. For that, we have to use the modes that allow the creation of a file if not found
such as w, w+, wb, wb+, a, a+, ab, and ab+.
Example:
FILE *fptr;
fptr = fopen("filename.txt", "w");
Example of Opening a File
int main()
{
// file pointer
FILE* fptr;
return 0;
}
Output
The file is created Successfully.
Closing a File
The fclose() function is used to close the file. After successful file operations, you must
always close a file to remove it from the memory.
Syntax of fclose()
Example 1: Program to Create a File, Write in it, And Close the File
return 0;
}
Output
The file is now opened.
Data successfully written in file GfgTest.c
The file is now closed.
For reading and writing to a text file, we use the functions fprintf() and fscanf().
They are just the file versions of printf() and scanf(). The only difference is that fprintf()
and fscanf() expects a pointer to the structure FILE.
int main()
{
int num;
FILE *fptr;
if(fptr == NULL)
{
printf("Error!");
exit(1);
}
printf("Enter num: ");
scanf("%d",&num);
fprintf(fptr,"%d",num);
fclose(fptr);
return 0;
}
This program takes a number from the user and stores in the file program.txt.
After you compile and run this program, you can see a text file program.txt created in C
drive of your computer. When you open the file, you can see the integer you entered.
#include <stdio.h>
#include <stdlib.h>
int main()
{
int num;
FILE *fptr;
fscanf(fptr,"%d", &num);
This program reads the integer present in the program.txt file and prints it onto the
screen.
If you successfully created the file from Example 1, running this program will get you the
integer you entered.
Other functions like fgetchar(), fputc() etc. can be used in a similar way.
Handling binary files in C involves using file operations functions provided by the
standard library. Here's a basic overview of how to work with binary files in C:
1. Opening a Binary File: Use fopen() with the "rb" mode for reading or "wb" mode
for writing. For both reading and writing, you can use "r+b" or "w+b" modes.
2. Reading from a Binary File: Use fread() to read data from a file into a buffer.
3. Writing to a Binary File: Use fwrite() to write data from a buffer to a file.
4. Closing a File: Use fclose() to close the file when done.
5. Error Handling: Always check if file operations succeed by checking return
values and using perror() or strerror() for error descriptions.
Here's a simple example program that demonstrates these concepts. This program writes
an array of integers to a binary file and then reads the data back:
#include <stdio.h>
#include <stdlib.h>
// Define a structure to write/read to/from the binary file
typedef struct {
int id;
char name[50];
float score;
} Student;
size_t num_students;
// Read the number of students first
fread(&num_students, sizeof(size_t), 1, file);
int main() {
// Example student data
Student students[] = {
{1, "Alice", 95.5},
{2, "Bob", 88.0},
{3, "Charlie", 76.2}
};
size_t num_students = sizeof(students) / sizeof(students[0]);
// Read the student data from the binary file and display it
readBinaryFile("students.dat");
return EXIT_SUCCESS;
}
Output
Student Data Read from File:
ID: 1, Name: Alice, Score: 95.50
ID: 2, Name: Bob, Score: 88.00
ID: 3, Name: Charlie, Score: 76.20
Explanation:
1. Writing Data:
o fopen("data.bin", "wb") opens the file for writing in binary mode.
o fwrite(data, 1, dataSize, writeFile) writes the entire array to the file.
o fclose(writeFile) closes the file after writing.
2. Reading Data:
o fopen("data.bin", "rb") opens the file for reading in binary mode.
o fread(readData, 1, dataSize, readFile) reads the content of the file into
a buffer.
o fclose(readFile) closes the file after reading.
3. Error Handling:
o perror() is used to print a description of the error if an operation fails.
This basic example covers the essentials of handling binary files in C. Depending on
your application, you might need to handle more complex scenarios, such as dynamic
memory allocation, more complex data structures, or file position management.
UNIT-V ADVANCED CONCEPTS AND APPLICATION
DEVELOPMENT
5.1 Bit Fields
Certainly! Let’s explore bit fields in C. These nifty constructs allow you to use
memory efficiently when you know that the value of a field or group of fields will
never exceed a certain limit or is within a small range. We’ll cover the basics, provide
some notes, and include a simple program to illustrate their usage.
struct DateWithBitField {
int month : 4; // Month has values between 0 and 15, so 4 bits are sufficient.
};
Interesting Fact:
If you use signed integers for bit fields and the value exceeds the allocated bits,
something intriguing can happen. For example:
struct Date {
int d : 5;
int m : 4;
int y;
};
The output might be negative due to how signed integers represent values.
void main() {
struct Date dt = { 31, 12, 2014 };
printf("Date: %d/%d/%d\n", dt.day, dt.month, dt.year);
}
Output:
Date: 31/12/2014
Remember, bit fields are like tiny compartments within a structure—each carefully
sized to hold just what’s needed!
5.2 typedef
typedef in C is keyword allows you to create aliases for existing data types, making
your code more readable and flexible
What is Typedef?
o typedef is used to assign alternative names (aliases) to existing data types.
o It’s especially useful for user-defined data types or when existing type names
become cumbersome.
#include <stdio.h>
#include <string.h>
typedef struct {
char name[50];
int age;
} Person;
void main() {
Person p1;
strcpy(p1.name, "John");
p1.age = 30;
printf("Name: %s, Age: %d\n", p1.name, p1.age);
}
}
o IntArray is an alias for an array of 5 integers.
return 0;
}
Output:
Square of 5 is 25
#include <stdio.h>
#define MAX(a, b) ((a) > (b) ? (a) : (b))
void main() {
int x = 10, y = 20;
printf("Max of %d and %d is %d\n", x, y, MAX(x, y));
}
Output:
Max of 10 and 20 is 20
Note:
o Be cautious with macro functions—they don’t have type checking.
o Parentheses are crucial to avoid unexpected behavior.
by programmers.
They allow you to organize your code, improve modularity, and reuse functions across
different programs.
Let’s create a custom library with a function to calculate the square of a number:
// mylibrary.h
#ifndef MYLIBRARY_H
#define MYLIBRARY_H
#endif
// mylibrary.c
#include "mylibrary.h"
}
// main.c
#include <stdio.h>
#include "mylibrary.h"
int main() {
double x = 5.0;
printf("Square of %.2f is %.2f\n", x, square(x));
return 0;
}
Output:
Square of 5.00 is 25.00
Note:
• Always include header guards (#ifndef, #define, and #endif) in your header
files to prevent multiple inclusion.
• You can create more complex libraries with additional functions.
Let’s create a function that calculates the average of a variable number of integers:
#include <stdio.h>
#include <stdarg.h>
int main() {
printf("Average of 2, 3, 4, 5 = %.6f\n", average(4, 2, 3, 4, 5));
printf("Average of 5, 10, 15 = %.6f\n", average(3, 5, 10, 15));
return 0;
}
Output:
Average of 2, 3, 4, 5 = 3.500000
Average of 5, 10, 15 = 10.000000
Note:
• The function average() has been called twice, each time specifying the total
number of variable arguments.
• Only ellipses (...) are used to pass the variable number of arguments.Remember,
variable arguments are like a flexible toolbox—you can use them to handle different
scenarios!
Example Usage:
#include <stdio.h>
int main(int argc, char* argv[]) {
printf("You have entered %d arguments:\n", argc);
for (int i = 0; i < argc; i++) {
printf("%s\n", argv[i]);
}
return 0;
}
Explanation:
The program above prints the total number of arguments (argc) and lists each
argument.
argv[0] contains the program name itself.
The remaining elements (argv[1] to argv[argc-1]) hold the actual command-line
arguments.
Example : Suppose you compile the program and run it with the following command:
$ gcc myprogram.c -o myprogram
$ ./myprogram hello world 123
Output:
You have entered 4 arguments:
./myprogram
hello
world
123
To find the sum of n numbers whose values are given as command line
parameters?
#include <stdio.h>
#include <stdlib.h>
Recursive functions are like mirrors reflecting themselves—each call creates a smaller
version of the same problem until a base case is reached.
• Base Case: The condition that stops the recursion (otherwise, we’d go forever!).
• Recursive Case: The part where the function calls itself with a modified
argument.
Let’s calculate the sum of the first N natural numbers using recursion:
#include <stdio.h>
int sum(int n) {
if (n == 0) {
return 0; // Base case: sum of 0 numbers is 0
} else {
return n + sum(n - 1); // Recursive case
}
}
void main() {
int number = 5;
printf("Sum of first %d natural numbers = %d\n", number, sum(number));
}
Output:
Sum of first 5 natural numbers = 15
Note:
• In the sum() function, we check if n is 0 (base case) or not.
• If not, we add n to the sum of the first n-1 natural numbers (recursive case).
OUTPUT:
Modular programming in C allows you to break down a large program into smaller,
manageable modules or functions. By doing so, you can improve code organization,
maintainability, and reusability
Program Structure:
main.c:
#include <stdio.h>
#include "average.h"
int main() {
int numbers[] = { 10, 20, 30, 40, 50 };
int count = sizeof(numbers) / sizeof(numbers[0]);
double avg = calculate_average(numbers, count);
printf("Average: %.2f\n", avg);
return 0;
}
average.c:
#include "average.h"
double calculate_average(int arr[], int n) {
double sum = 0.0;
for (int i = 0; i < n; i++) {
sum += arr[i];
}
return sum / n;
}
average.h:
#ifndef AVERAGE_H
#define AVERAGE_H
double calculate_average(int arr[], int n);
#endif
Output:
Average: 30.00
#include <stdio.h>
void main() {
printf("Hello, World!\n");
}
Here’s what’s happening in this program:
1. We include the standard input/output library (<stdio.h>), which provides
functions like printf.
2. The main() function is the entry point of our program.
3. Inside main(), we use printf to display the message “Hello, World!” followed by
a newline (\n).
4. Finally, we return 0 to indicate successful execution.
Compile and run this program, and you’ll see the output:
Hello, World!
Understanding the Output
● The printf function is used to print text to the console. In this case, it displays
our friendly greeting.
● The \n character represents a newline, so the cursor moves to the next line after
printing “Hello, World!”.
Going Beyond: Creating Your Own Functions
Now, let’s take a step further and create a custom function. Imagine we want to
calculate the factorial of a given positive integer. We can encapsulate this logic in a
separate function:
#include <stdio.h>
// Function to calculate factorial
unsigned long long factorial(int n) {
if (n == 0 || n == 1)
return 1;
else
return n * factorial(n - 1);
}
int main() {
int num = 5;
printf("Factorial of %d is %llu\n", num, factorial(num));
return 0;
}
Here’s what’s happening now:
1. We define a custom function called factorial that takes an integer argument (n).
2. Inside the function, we use recursion to calculate the factorial.
3. In main(), we call this function with num = 5 and display the result.
Compile and run this program, and you’ll see the output:
Factorial of 5 is 120
We’ll create a header file (.h) and a source file (.c) to achieve this. Here’s an improved
version of the calculator:
1. Calculator.h (Header File):
// Calculator.h
#ifndef CALCULATOR_H
#define CALCULATOR_H
// Function prototypes
double add(double a, double b);
double subtract(double a, double b);
double multiply(double a, double b);
double divide(double a, double b);
#endif // CALCULATOR_H
2. Calculator.c (Source File):
// Calculator.c
#include "Calculator.h"
3. Main Program:
#include <stdio.h>
#include "Calculator.h"
int main() {
double num1, num2;
char operator;
switch (operator) {
case '+':
printf("Result: %.2lf\n", add(num1, num2));
break;
case '-':
printf("Result: %.2lf\n", subtract(num1, num2));
break;
case '*':
printf("Result: %.2lf\n", multiply(num1, num2));
break;
case '/':
printf("Result: %.2lf\n", divide(num1, num2));
break;
default:
printf("Invalid operator!\n");
}
return 0;
}
OUTPUT :
Enter an operator (+, -, *, /): +
Enter two numbers: 5.5 3.2
Result: 8.70