Professional Documents
Culture Documents
MSC Computer Science: Karnataka State Open University
MSC Computer Science: Karnataka State Open University
Mukthagangotri, Mysore-570006
Advanced C Programming
Editorial Committee
Dr. D M Mahesha MCA.,PhD Chairman
BOS Chairman,
Assistant Professor & Programme co-ordinator(PG)
DoS&R in Computer Science,
Karnataka State Open University, Mysuru-570 006.
Printed and Published on behalf of Karnataka State Open University, Mysore-570 006 by
the Registrar (Administration)-2022
TABLE OF CONTENTS
UNIT- 1 1-12
Functions
BLOCK 1I
Preface
The programming language is certainly the essential language to this modern world. It is
evolved profoundly over the past few decades. Program developers can often get confused with
a wide variety of programming languages, deciding which one to opt for learning However
some valuable reason to learn programming in C. The C programming language massively
used in the scientific computing society regardless of popularity of high level luggage’s. Aside
from changes in programming language and presentation, additional sections have been
included. Some frequently asked questions and common programming errors are listed at the
end of the chapter. Only a subset of the ANSI C language is tackled here. Specifically, it is
assumed that the student will be working under the Linux environment and programming using
GNU C (which supports ANSI C) or the Borland Turbo C/C++ compiler under the Windows
environment. Coding standards to be followed,
May you learn a lot from the study of this manual, and may the knowledge that you have gained
be used for the common good of all people.
1.0 OBJECTIVES
1
1.1 INTRODUCTION
Function in C programming is a reusable block of code that makes a program easier to
understand, test and can be easily modified without changing the calling program. The
Function in C which can divide the code and modularize the program for better and effective
results. In short, the functions are defined as larger program is divided into various
subprograms which are called as functions. The function is divided into two types library
function and user-defined function.
1.2 FUNCTIONS
A function is a block of statements that performs a specific task. Let’s say we are writing a C
program and we want to perform a same task in that program more than once. In such case
we have two options:
a) We can use the same set of statements every time to perform the task
b) We can create a function to perform that task, and just call it every time you need to
perform that task.
Select Option (b) is a good practice and a good programmer always uses functions while
writing code in C.
The below are the following reasons to why functions are used
Improve the readability of code.
Improves the reusability of the code, same function can be used in any
program rather than writing the same code from scratch.
Debugging of the code would be easier if you use functions, as errors are easy
to be traced.
Reduces the size of the code, duplicate set of statements are replaced by
function calls.
Types of Functions:
2
already defined in header files in C library (files with .h extensions are called header files
such as stdio.h), so we just call them whenever there is a need to use them.
For example, printf() function is defined in <stdio.h> header file so in order to use
the printf() function, we need to include the <stdio.h> header file in our program
using #include <stdio.h>.
The functions which are created by user are known as user defined function. Another way the
user defined function is defined as we create in a program is known as user defined functions
return_type: The Return type can be of any data type such as int, float, double, char, void
and short etc.
3
return_type addition(argument list)
This addition function adds two integer variables, which means we need two integer variable
as input, let’s provide two integer parameters in the function signature. The function
signature would be –
return_type add(int num1, int num2)
The sum of two integers result would be integer only. Hence function should return an
integer value – I got my return type – It would be integer –
int add(int num1, int num2);
So we got your function prototype or signature. Now we can implement the logic in C
program shown below:
The example shows the how to call function in a program
Consider the following C program
Example1: Creating a user defined function addition()
#include<stdio.h>
#include<conio.h>
void main(){
int num1, num2, result ;
int addition(int,int) ; // function declaration
clrscr() ;
printf("Enter two integer numbers : ") ;
scanf("%d%d", &num1, &num2);
result = addition(num1, num2) ; // function call
printf("SUM of two integers= %d", result);
getch() ;
}
int addition(int num1, int num2) // function definition
{
return num1+num2 ;
}
In C user defined function must be declared and implemented. Whenever we make function
4
call the function definition gets executed. For example, consider the following program in
which we create a fucntion called addition with two paramenters and a return value.
The above example program describes, the function declaration statement "int
addition(int,int)" tells the compiler that there is a function with name addition which takes
two integer values as parameters and returns an integer value. The function call statement
takes the execution control to the addition() definition along with values of num1 and num2.
Then function definition executes the code written inside it and comes back to the function
call along with return value.
Functions with no arguments and no return value:The following syntax describes how to
write a function which neither takes any arguments nor returns any value.
5
void functionName() //Return type in the function header should be 'void' and do not give
any arguments within the parenthesis.
{
........
........
return; //Need not return any value
}
include <stdio.h>
void modify() //function definition
{
int a;
printf("Enter a value:");
scanf("%d",&m);
m=m+10;
printf("The modified value is %d",m);
6
return;
}
int main()
{
modify(); //function call
getch();
return 0;
}
output: if m=1
The modified value is 11.
returnType functionName() //Identify type of value will be returned by the function and
accordingly it specify the return type and empty
{
parenthesis since there is no argument
....
....
return value;
}
7
X = functionName //As the function is going to return the modified Value, call the function
like this.
Example: The previous program is modified such that the value of 'a' is read in the user-
defined function and the changed value is returned to the main(), where it gets printed.
include <stdio.h>
void modify()
{
int a;
printf("Enter a value:" )
scanf("%d",&m);
m=m+10;
return m;
}
int main()
{
int a;
a=modify();
printf("The modified value is %d",a);
getch();
return 0;
}
Assume m=1. When `m=m+10' is executed m=11. Here the modified value (11) is returned to
the place where the function was called. 11 is returned as a=11. If x is printed, 11 will be the
output.
8
Functions with arguments and no return values
Functions with arguments and no return values: Function with arguments can perform
much better than function with no argument function type. This type of function will be
accept data from calling function. In other words, we send data to the called function from
calling function but we cannot send result data back to the calling function. Rather, it displays
the result on the terminal. But we can control the output of function by providing various
values as arguments.
Example: In the program, read the value of 'm' in main(), pass it to modify() and print the
changed value of 'm' in modify() function itself.
include <stdio.h>
void modify(int x) // function takes the argument x and since it does not return
anything, specify 'void'
9
{
a = a + 10;
printf(" Modified value is %d", a);
return;
}
int main()
{
int m;
printf("Enter the value:");
scanf("%d",&m);
modify(m); // pass the argument 'a' to the function
getch();
return 0;
}
m's value is read in the main function and that value is passed to the modify() function. m's
value is assigned to the formal argument 'a'. Then 'a' value is changed and printed in the
modify() function itself.
10
....
return value;
}
Example: In the above program, read the value of 'a' in main(), pass it to modify() and return
the changed value of 'a' to main() and print the changed value in main().
include <stdio.h>
void modify(int x) // function takes the argument x and since it does not return anything,
specify 'void'
{
m = m + 10;
return m;
}
int main()
{
int a;
printf("Enter the value:");
scanf("%d",&a);
printf(" Modified value is %d", modify(a)); // pass the argument 'a' to the function
getch();
return 0;
11
}
Points to be Remembered
The parameters specified in calling function are said to be Actual Parameters.
The parameters declared in called function are said to be Formal Parameters.
The value of actual parameters is always copied into formal parameters.
1.5 SUMMARY
At the end of this unit you have learnt about functions, how to define and declare functions,
what are the functions different data types. In this unit we have also discussed about the
library functions and user defined functions. Finally you learnt different types of functions.
1.6 KEYWORDS
Function call, prototype, library function, used defined function.
1.7 QUESTIONS
1. Discuss function in c.
2. Describe user-defined function.
3. Briefly explain different types of functions.
4. Explain how to access and declare pointer in c.
1.8 REFERENCES
12
UNIT 2: RECURSION AND STORAGE CLASSES
Structure
2.0 Objectives
2.1 Introduction
2.2 Recursion
2.3 Storage classes
2.4 Nesting of function
2.5 Summary
2.6 Key words
2.7 Questions
2.8 References
2.0 OBJECTIVES
13
2.1 INTRODUCTION
A storage class defines the scope (visibility) and life-time of variables and/or functions
within a C Program. They precede the type that they modify. We have four different storage
classes in a C program –auto, register, static and extern.
2.2 RECURSION
Recursive Functions in C
In C programming language, always function calls can be made from the main() function,
other functions or from the same function itself. The recursive function is defined by: The
function call by itself is called recursion function
While using the recursive functions we should be used very carefully because, when a
function called by itself it enters into the infinite loop. If the function enters into the infinite
loop, the function execution never gets completed. We always should define the condition to
exit from the function call so that the recursive function gets terminated.
Whenever a function is called by itself, the first call should remains under execution till the
last call gets invoked. Every time when a function call is invoked, the function returns the
execution control to the previous function call.
Example Program
#include<stdio.h>
#include<conio.h>
14
scanf("%d", &x) ;
fact = factorial( x ) ;
printf("\nFactorial of %d is %d\n", x, fact) ;
return 0;
}
int factorial( int x )
{
int temp ;
if( x == 0)
return 1 ;
else
temp = x * factorial( x-1 ) ; // recursive function call
return temp ;
}
Output:
In the above given example, the factorial() function call is initiated from main() function
with the value 3. The function calls factorial(2), factorial(1) and factorial(0) are called
recursively inside the factorial() function. In this program execution process, till the
execution of function calls factorial(2), factorial(1) and factorial(0) gets completed the
function call factorial(3) remains under execution. Similarly till the execution of function
calls factorial(1) and factorial(0) gets completed the function call factorial(2) remains under
execution. In the same way till the execution of function call factorial(0) gets completed the
function call factorial(1) remains under execution. The complete execution process of the
above program is shown in the following figure...
15
16
2.3 STORAGE CLASSES
In C language, storage classes are described by the features of variables and functions like
visibility and scope of q variable or function.
The storage classes in C language classified into four types namely
Automatic variables
External variables
Static variables
Register variables
Automatic variable(auto)
Auto storage class will be the default storage class for all the local variables. variables are
created when function is called. When the execution of function is completed, variables are
automatically destroyed. They are also called as local variables because they are local to a
function. By default, they are assigned the garbage value by the compiler.
17
External variables (extern)
External variables are also called as global variables. These variables are defined outside the
function. These variables are available globally throughout the function execution. The value
of global variables can also be modified by the functions.
Scope − They are not bound by any function. They are everywhere in the program i.e. global.
Default value − Default initialized value of global variables are Zero.
Lifetime − Till the end of the execution of the program.
Here is an example of extern variable in C language,
Example
#include <stdio.h>
extern int x = 32;
int b = 8;
int main() {
auto int a = 28;
extern int b;
printf("The value of auto variable is: %d\n", a);
printf("The value of extern variables x and b is: %d,%d\n",x,b);
x = 15;
printf("The value of modified extern variable x is : %d\n",x);
return 0;
} The value of auto variable is : 28
The value of extern variables x and b is: 32,8
The value of modified extern variable x is: 15
18
#include <stdio.h>
int main()
{
auto int x = -28;
static int y = 8;
printf("The value of auto variable : %d\n", x);
printf("The value of static variable b : %d\n",y);
if(x!=0)
printf("The sum of static variable and auto variable : %d\n",(y+x));
return 0;
}
The value of auto variable : -28
The value of static variable b : 8
The sum of static variable and auto variable : -20
19
The sum of auto and register variable : 18
In some applications, we have seen that some functions are declared inside another function.
This is sometimes called as nested function, but actually this is not the nested function. This
is called as the lexical scoping. Lexical scoping is not valid in C because the compiler will be
unable to reach correct memory location of inner function.
Nested function definitions can access only global variables. They cannot access local
variables of surrounding blocks. In C there are two nested scopes the global and the local. So
nested function has some limited use. If we need to create nested function like below, it will
generate error.
Example
#include <stdio.h>
main(void) {
printf("Welcome");
int my_fun() {
printf("my world");
int my_fun2() {
printf("Hello");
my_fun2();
Output
20
But an extension of GNU C compiler allows declaration of the nested function. For this we
have to put auto keyword before the declaration of nested function.
Example
#include <stdio.h>
main(void) {
my_fun();
printf("Welcome\n");
int my_fun() {
printf("My world\n");
printf("hello");
Output
My world
Welcome
hello
2.5 SUMMARY
In this unit we have discussed in detail about the recursion. This unit also covered in detail about
variables and storage classes such as automatic, external (global), register and static variable
and storage class with an example. At the end of this unit discussed about nesting of
functions.
2.6 KEYWORDS
Auto, extern, register, static, recursion
2.7 QUESTIONS
1. Explain with an example about storage classes in C.
2. With an example show how efficiently you can utilize available storage class in C?
21
3. Describe the recursion in detail.
4. Discuss nesting of functions.
2.8 REFERENCE
The C Programming Language (Ansi C Version) by Brian W. Kernighan, Dennis M.
Ritchie
Expert C Programming: Deep C Secrets by Peter Van, Der Linden
5. http://www.cprogrammingexpert.com/C/Tutorial
Simplifying C (First Edition 2010) Publication: Dreamtech by Harshal Arolkar and
Sonal Jain
Programming in ANSI C (Fifth Edition 2011) Publication: Mc Graw Hill by
Balagurusamy
Programming in C (First Edition 2011) Publication: Oxford Higher Education by
Reema Thareja
22
UNIT 3 – STRUCTURES AND UNIONS
Structure
3.0 Objectives
3.1 Introduction
3.2 Structure
3.3 Arrays v/s structures
3.4 Accessing structure members
3.5 Nested structures
3.6 Unions
3.7 Summary
3.8 Key words
3.9 Questions
3.10 References
3.0 OBJECTIVES
3.1 INTRODUCTION
The C programming language has many built-in data types. It allows users to create their own
custom data types. Both the structure and union are user-defined data types in C
programming that can hold any data type. Structure and union seem to perform most similar
functions, there are few differences between them. Structures allocate enough space to store
all their members, but unions can only hold one member value at a time.
3.2 STRUCTURE
23
Basic of Structures
Structures are defined as constructed data type supported by C, a mechanism for packing data
of different types. A structure is a very good tool for handling a group of logically related
data items. For example, it can be used to represent a set of attributes, such as stud_name,
roll_num and marks. The structure concept is analogous to that of a ‘record’ in many other
languages.
Structures are more helpful to organize complex data in a more meaningful way. It is a more
powerful concept that we may often need to use in our program design.
Defining a Structure
Let us use an example to illustrate the process of structure definition and the creation of
structure variables. Consider an employee database consisting of employee name, id, and
salary. We can define a structure to hold this information as follows:
struct employee
{
char name[30]; varchar Id[25]; int salary;
};
The keyword struct declares a structure to hold the details of three data fields, employee
name, id, and salary. The fields in struct employee are called structure elements or members.
Each member will be belong to a different type of data. employee is the name of the structure
and is called the structure tag. The tag name should be used subsequently to declare variables
that have the tag’s structure.
24
};
25
Output:
struct company_employee {
char *emp_name;
int emp_id;
26
int salary;
};
struct company_employee, employee1 , employee 2, employee 3;
In structure we can access and assign values to the members in a number of ways. The
members of structure should be linked to the structure variables in order to make them
meaningful members. For example, the word only ‘title’ has no meaning whereas the phrase
‘title of book3’ has a meaning. The link between a member and a variable is accomplished
using the member operator ‘.’ Which is also known as ‘dot operator’ or ‘period operator’?
For example,
book1.price is the variable representing the price of book1 and can be treated like any other
ordinary variable? Here is how we would assign values to the members of book1:
strcpy(book1.title,”C Programming”);
strcpy(book1.author, “Balaguruswamy”);
book1.pages = 350;
book1.price = 400;
We can also use scanf to give the values through the keyboard.
scanf(“%s\n”,book1.title);
scanf(“%d\n”,&book1.pages);
are valid input statements.
Structure Initialization
Like any other data type, a structure variable can be initialized at compile time.
struct st_record
{
int weight; float height;
} student1 = {6-,180.75};
void main()
{
struct st_record student2 = {53, 170.60};
}
27
The C language does not permit the initialization of individual structure members within the
template. The initialization would be done only in the declaration of the actual variable.
Note that the compile-time initialization of a structure variable must have the following
elements:
1. Keyword struct
2. Structure tag name
3. Name of the variable to be declared
4. Assignment operator =
5. A set of values for the members of the structure variable, separated by commas and
enclosed in braces
6. Terminating semicolon
Arrays of Structures
We use structures to be describing the format of a number of related variables. For example,
in analyzing the marks obtained by a class of students, we will use a template to describe
student name and marks obtained in various subjects and then declare all the students as
structure variables. In such cases, we may declare an array of structures, each element of the
array representing a structure variable. for example,
28
It defines an array called student, that consists of 100 elements. Each element is defined to
be of the type struct class. Consider the following declaration:
struct marks
{
int sub1; int sub2; int sub3;
};
void main()
{
struct marks student[3]={{45,66,81},{75,53,72},{80,36,71}};
This declares the student as an array of three elements student[0], student[1] and student[2]
and initializes their members as follows:
student[0].sub1=45; student[0].sub2=66;
………..
………..
student[2].sub3=72;
Note that the array is declared just as it should have been with any other array. The student is
an array, we use the usual array-accessing methods to access individual elements and then the
member operator to access members. The each element of student array is a structure variable
with three members.
Any array of structures is stored inside the memory in the same way as a multi- dimensional
array. The array student actually looks as show in below figure.
Arrays within Structures
C permits the use of arrays as structure members. We have already used arrays of characters
inside a structure. Similarly, we can use single-or multi-dimensional arrays of type int or
float. For example, the following structure declaration is valid:
struct marks
{
int number; float sub[3];
} student[2];
29
Here, the member subject contains three elements, sub[0], sub[1] and sub[2]. These elements
can be accessed using appropriate subscripts. For example, the name
student[1].subj[2];
would refer to the marks obtained in the third subject by the second student.
struct address
{
char society[100]; char area[100]; char city[50];
int pincode;
};
struct student
{
int rollno;
char name[50];
struct address add; // Structure inside structure
};
In above example we have defined one structure having member variable society, area, city,
and pincode number. Then we have defined another structure having member variable roll
number, name, and structure variable of structure address.
We can also define above structure by following way. Any method is valid for C program.
struct student
{
int rollno;
char name[50];
30
// Structure address defined inside the structure struct address
{
char society[100]; char area[100]; char city[50];
int pincode;
} add;
};
void main( )
{
struct student s;
printf(“Enter student detail\n”); scanf(“%d”, &s.rollno); gets(s.name);
31
// Function declaration void print(struct student); void main( )
{
struct student s;
printf(“Enter Roll Num. and Student name : “); scanf(“%d”,&s.rollno);
gets(s.name);
// Call a function
print(s);
}
// Function definition
void print(struct student s) { print(“Roll No. = %d\n”,s.rollno); printf(“Name =
%s\n”,s.name);
}
In above example we have defined one structure template for the student, which contain roll
number and name as structure member. We have used one function print() to print the
member of structure and we have passed that variable as argument inside function.
RETURNING STRUCTURE VARIABLE FROM FUNCTION
As like passing the structure variable inside structure we can return structure variable from
function. But it is supported only when our compiler supports the assignment operation over
structure.
struct student
{
int rollno;
char name[100];
};
// Function declaration
struct student read( );
void main( )
{
struct student s;
// Call function
s = read( );
32
}
// Function definition
struct student read( )
{
struct student t;
printf(“Enter Roll No. and Name of student\n”); scanf(“%d”,&t.rollno);
gets(t.name);
return( t ); // Returning structure variable
}
In above example we have defined one structure template for the student, which contain roll
number and name as structure member. We have used one function read() to read the data of
structure. This function return the value of type struct student and then it is assigned to
variable used inside main( ) function.
Important Points
1. The called function should be declared for its type, appropriate to the data type it is
expected to return. For example, if it is returning a copy of the entire structure, then it
should be declared as struct with an appropriate tag name.
2. The structure variable used as the actual argument and the corresponding formal
argument in the called function should be of the same struct type.
3. The return statement is necessary only when if the function is returning some data
back to the calling function. The expression may be any simple variable or structure
variable to an expression using simple variable.
4. When a function returns a structure, it should be assigned to a structure of identical
type in the calling function.
5. The called functions should be declared in the calling function appropriately.
3.7 UNIONS
33
value. Unions can be very handy when we need to talk to peripherals through some memory
mapped registers.
C unions allow us to data members which are mutually exclusive to share the same memory.
This is very important when memory is valuable, such as in embedded systems. Unions are
used in embedded programming where direct access to the memory is needed.
Structure allocate enough space to store all of the fields in the struct. The first field is stored
at the beginning of the struct, the second is stored after that, and so on.
Unions only allocate enough space to store the largest field which is listed in the union, and
all fields are stored at the same space.
The basic syntax of the Union in C Programming is as shown below
union UName
{
Data_Type Variable_Name; //Member
Data_Type Variable_Name; //Member
………….
};
Union is the system reserved keyword used to create and accessing its members. The UName
is the name given by user for this.
For example, employees, persons, students.
Data_Type means data type of the variable that we want to declare in the program. For
example, int, float, char, etc. And the Variable_Name is the name of the variable. For
example, id, age, name, salary. For Example
34
{
//Members
int Roll_No; //Data Type = int; Variable Name = Roll_No
char name[50]; //Data Type = char Array; Variable Name = name
char address[100]; //Data Type = Char Array; Variable Name = address
};
Declaration of Union
In declaration of Union before accessing the members inside it, we have to create the
variables. We can able to declare the variables in multiple ways. The First Approach is
declaring the union first, and then create the variable in the main function.
union employee
{
int age;
char name[50];
float salary;
};
int age;
char name[40];
float salary;
35
} emp1, emp2;
#include <stdio.h>
#include <string.h>
union Employee
{
int age;
char Name[40];
char Department[30];
float Salary;
};
int main()
{
union Employee emp1;
union Employee emp2;
emp1.age = 37;
strcpy(emp1.Name, "vijay");
strcpy(emp1.Department, "Science");
emp1.Salary = 85000.70;
36
printf(" Employee Department = %s \n", emp1.Department);
printf(" Employee Salary = %.2f \n\n", emp1.Salary);
printf("Details of the Second Employee \n" );
emp2.age = 30;
printf(" Employee Age = %d \n", emp2.age );
strcpy(emp2.Name, "chiru");
printf(" Employee Name = %s \n", emp2.Name );
strcpy(emp2.Department, "Computer science" );
printf(" Employee Department = %s \n ", emp2.Department );
emp2.Salary = 88000.20;
printf(" Employee Salary = %.2f \n ", emp2.Salary );
return 0;
}
3.8 SUMMARY
In this unit we have learnt some advance concepts on structure and unions such as passing to
function, pointers to structure and we also discussed about union in detail.
3.9 KEYWORDS
1. Explain the concept of structure as function arguments and pointer to structure with
suitable program.
2. Explain unions with example.
3. Define structure in C.
3.11 REFERENCES
37
Programming in ANSI C (Fifth Edition 2011) Publication: Mc Graw Hill by
Balagurusamy
Programming in C (First Edition 2011) Publication: Oxford Higher Education by
Reema Thareja
38
UNIT 4: POINTER
Structure
4.0 objectives
4.1 Introduction
4.2 Introduction to pointer
4.3 pointer arithmetic
4.4 pointers and arrays
4.5 pointers and structures
4.6 pointers and functions
4.7 Summary
4.8 Keywords
4.9 Questions
4.10 References
4.0 OBJECTIVES
39
4.1 INTRODUCTION
Pointer in C language is a variable which holds the address of another variable of same data
type. Pointers are used to access memory and manipulate the address. Pointers are one of the
most distinct and exciting features of C language.
40
Would assign the address 62264 (i.e. the location of a) to the variable p. The & operator will
be remembered as ‘address of’. The & operator can be used only with a simple variable or an
array.
Example,
int *p;
It declares the variable p as a pointer variable that points to an integer data type. Remember
that the type interferes to the data type of the variable being pointed to by p and not the type
of the value of the pointer. Similarly, the statement
float *x;
Declares x as a pointer to a floating-point variable.
Example
int quantity;
int*p; /* declaration of pointer */
41
p = &quantity; /* initialization */ We can also combine the initialization with the declaration.
That is,
int *p = &quantity;
They must ensure that the pointer variables always point to the corresponding type of data.
For example,
float a,b; int x, *p; p= &a;
b = *p;
We declare a pointer to be of int type, the system assumes that any address that the pointer
can hold will point to an integer variable. Since the compiler cannot detect such errors, care
should be taken to avoid wrong pointer assignments.
It is also possible to combine the declaration of data variable, since the declaration of pointer
variable and the initialization of the pointer variable in one step. For example,
Is perfectly valid. It declares x as an integer variable and pas a pointer variable and then
initializes pto the address of x. and also remember that the target variable x is declared first.
The statement int *p = &x, x; is not valid.
We could also define a pointer variable with an initial value of NULL or zero. That is, the
following statements are valid
int *p =null;
int *p = 0;
With the exception of null and zero, no other constant value can be assigned to a pointer
variable. For example, the following is wrong:
int *p = 5360; /*absolute addresses */
42
When a pointer has been assigned the address of a variable, the question arise is to how to
access the value of the variable using the pointer. Accessing of value of variable by using
another unary operator * (asterisk), usually known as the indirection operator. Another name
for the indirection operator is called as dereferencing operator. Consider the following
statements:
int quantity, *p, n; quantity = 179; p=&quantity; n=*p;
The first line declares quantity and n as integer variables and p as a pointer variable pointing
to an integer. The second line assigns the value 179 to quantity and the third line assigns the
address of quantity to the pointer variable p. The fourth line consists of indirection operator *.
When the operator * is always placed before a pointer variable in an expression, the pointer
returns the value of the variable of which the pointer value is the address. In this case, *p
returns the value of the variable quantity, because the p is the address of quantity. The * will
be remembered as ‘value at address’. Thus the value of n would 179. The two statements
p=&quantity; n=*p;
are equivalent to
n=*&quantity;which in turn is equivalent
n=quantity;
Example:
#include <stdio.h>
void ()
{
int var = 25;
int *pt;
pt = &var;
printf("Address is: %p \n",pt);
printf("Value is: %d \n", *pt);
}
int main()
{
TechVidvan();
}
Output:
43
Address is: 0x7ffc9e1fb704
Value is: 25
Like other variables in C. Pointer variables can be used in expressions. For example given
below, if p1 and p2 are properly declared and initialized pointers, then the following
statements are valid.
Note that there is a blank space between / and * in the item 3 above. The following is wrong.
Z = 5* - *p2/ *p1;
C allows us to add integers to or subtract from pointers, as well as to subtract one pointer
from another. P1+4,P2-2 and p1-p2 are all allowed. If p1 and p2 are both pointers to the same
array, then p2-p1 gives the number of element between p1 and p2.
44
Pointer increments and scale factor
We have seen that the pointer can be incremented like
p1 = p2 + 2; p1 = p1 + 1;
And so on. Remember, however an expression likep1++;
Will cause the pointer p1 to point to the nest value of its type. For example, if p1 is an integer
pointer with an initial value, say 2800, then after the operation p1 = p1+1, the value of p1 will
be 2802, and not 2801. That is, when we increment a pointer, its value is increased by the
‘length’ of the data type that it points to. This length called the scale factor.
If an array is declared, the compiler allocates a base address and sufficient amount of storage
to contain all the elements of the array in contiguous memory locations. The base address is
the location of the first element (index 0) of the array.
The compiler also defines the array name as a constant pointer to the first element. Suppose
we declare an array x as follows:
int x[5] = {1,2,3,4,5};
45
suppose the base address of x is 1000 and assuming that each integer requires two bytes, the
five elements will stored as follows:
Element Value Address
X[0] 1 1000
X[1] 2 1002
X[2] 3 1004
X[3] 4 1006
X[4] 5 1008
The name x is defined as a constant pointer pointing to the first element, x[0] and therefore
the value of x is 1000, the location where x[0] is stored. That is
X =&x[0] = 1000
If we declare p as an integer pointer, then we can make the pointer p to point to the array x by
the following assignment:
p = x;
This is equivalent to
p =&x[0];
Now, we will access every value of x using p++ to move from one element to another. The
relationship between p and x is shown as below:
p= &x[0] (=1000) p+1 =&x[1] (=1002)
p+2 =&x[2] (=1004)
p+3 =&x[3] (=1006)
p+4 =&x[4] (=1008)
We may notice that the address of an element is calculated using its index and the scale factor
of the data type.
#include <stdio.h>
int main () {
int value_array[] = {55, 366, 855, 112};
int a, *point[4];
printf("the array of pointer\n\n");
for (a = 0; a < 4; a++) {
point[a] = &value_array[a]; // assigning address!
46
}
for (a= 0; a < 4; a++) {
printf("Value => var[%d]: %d\n", a, *point[a] );
}
return 0;
}
output:
array of pointers!
The above statement declares product as an array of two elements, each of the type struct
inventory and ptr as a pointer to data objects of the type inventory. The assignment given in
below statement
ptr = product;
We would assign the address of the zeroth element of product to ptr. That is, the pointer ptr
will now point to product[0]. Its members will be accessed using the following notation.
ptr ->name ptr -> number ptr -> price
47
The symbol -> is called the arrow operator is made up of a sign and a greater than sign. Note
that ptr is simply another way of writing product[0]. When the pointer ptr is incremented
by one, it is made to point to the next record. i.e. product[1].
The following for statement will print the values of members of all the elements of product
array.
for(ptr=product; ptr<product+2;ptr++)
{
printf(“%s %d %f\n”,ptr->name,ptr->number,ptr->rate);
}
#include<stdio.h>
struct point
{
int a;
float b;
};
int main()
{
struct point p1={4,8.3};
struct point *p2=&p1;
printf("pointers to structures!\n\n");
printf(" The first value is: %d\n",p2->a);
printf("The second value is: %0.1f",p2->b);
return 0;
}
output:
pointer to structures!
48
If an array is passed to a function as an argument, only the address of the first element of the
array is passed, but not the actual values of the array elements. If x is an array, if we call any
function by passing x as an argument like sort(x), the address of x[0] is passed to the function
sort. The function uses this address for manipulating the array elements. Similarly, we will
pass the address of a variable as an argument to a function in the normal way.
If we pass addresses to a function, the parameters receiving the addresses should be pointers.
The process of calling a function using pointers to pass the addresses of variables is called as
‘call by reference’, where the process of passing the actual value of variable is called as ‘call
by value’. The function which is called by ‘reference’ can change the value of the variable
used in the call.
Consider the following code:
void main()
{
int x; x = 20;
change(&x); /* call by reference or address */
printf(“%d\n”,x);
}
change(int *p)
{
*p=*p+10;
}
If the function change() is called, the address of the variable, not its value, is passed into the
function change(). Inside change(), the variable p is declared as a pointer and therefore p is
the address of the variable x. The statement,
*p = *p + 10;
means‘add 10 to the value stored at the address p’. since p represents the address of x, the
value of x is changed from 20 to 30. Therefore the output of the program will be 30, not 20.
This mechanism is known as “call by address” or “pass by pointers”. Rules for pass by
Pointers given below:
1. The types of the actual argument and formal arguments should be same.
49
2. The actual arguments (in the function call) should be the address of variables that are
local to the calling function.
3. The formal arguments in the function header should be prefixed by the indirection
operator *.
4. If the prototype, the arguments must be prefixed by the symbol *.
5. To access the value of an actual argument in the called function, we should use the
corresponding formal argument prefixed with the indirection operator *.
Returning multiple values through pointer
In functions, we can seen that it return just one value using a return statement. That is
because; a return statement can return only value. Suppose, however that we need to get more
information from a function. We will achieve this using the arguments not only to receive
information but also to send back information to the calling function. The arguments that are
used to “send out” information are called output parameters.
The mechanism of sending back information through arguments is achieved using what are
known as the address operator (&) and indirection operator (*). Following is the example:
void main()
{
int x=20,y=10,s,d;
void mathoperation(int x, int y, int *s, int *d); clrscr();
mathoperation(x,y,&s,&d); printf(“\n s=%d \n d=%d”,s,d); getch();
}
void mathoperation(int x, int y, int *s, int *d)
{
*s=x+y;
*d=x-y;
}
#include <stdio.h>
void display(int *val);
int main () {
int a;
display(&a);
printf("TechVidvan Tutorial: Passing pointers to function!\n\n");
printf("Value is: %d\n",a);
return 0;
50
}
void display(int *val) {
*val = 1002;
return;
}
output:
TechVidvan Tutorial: Passing pointers to function!
4.7 SUMMARY
At the end of this unit we have learnt pointer concept in depth, we dealt with advance concept
on pointers such as passing pointer to function and returning pointer from function. In the
later stage we focused pointer arithmetic. In the last section of this unit we have discussed
pointers and arrays, pointers and structures and also pointer and functions..
4.8 KEYWORDS
1. How can pointers be used as arguments for function? Demonstrate the stages with
suitable code as an example?
2. Discuss pointers and functions.
3. With example explain pointer and arrays.
4. Describe declaration of pointer in C.
5. Explain pointers and functions.
4.10 REFERENCE
51
Programming in ANSI C (Fifth Edition 2011) Publication: Mc Graw Hill by
Balagurusamy
Programming in C (First Edition 2011) Publication: Oxford Higher Education by
Reema Thareja
52
Structure
5.0 objectives
5.1 Introduction
5.2 Dynamic memory allocation
5.3 Malloc() function
5.4 Calloc() function
5.5 Realloc() function
5.6 Free() function
5.7 Summary
5.8 Keywords
5.9 Questions
5.10 References
5.0 OBJECTIVES
5.1 INTRODUCTION
53
The dynamic memory allocation in c language concept enables the C programmer to
allocate memory at runtime. Dynamic memory allocation in c language is having the 4
functions of stdlib.h header file.
1. malloc()
2. calloc()
3. realloc()
4. free()
Function Task
malloc This function allocates memory requests size of bytes and returns a pointer to the 1 st
byte of allocated space.
calloc This function allocates space for an array of elements initializes them to zero and
returns a pointer to the memory.
Free This function frees previously allocated space
54
realloc This function modifies the size of previously allocated space.
5.3 MALLOC()
Malloc: Allocating a block of memory
A block mf memory can be allocated using the function malloc. The malloc function reserves
a block of memory of specified size and returns a pointer of type void. This means that we
will assign it to any type of pointer. It takes the following form:
ptr=(cast-type*)malloc(byte-size);
ptr is a pointer of type cast-type the malloc returns a pointer (of cast type) to an area of
memory with size byte-size.
Example:
x=(int*)malloc(1000*sizeof(int));
On successful execution of this statement a memory equivalent to 1000 times the area of int
bytes is reserved and the address of the first byte of memory allocated is assigned to the
pointer x of type int. The malloc allocates a block of contiguous bytes. The allocation will fail
if the space in the heap is not sufficient to satisfy the request. If it fails, it returns a NULL.
55
#include <stdlib.h>
int main(){
int n,i,*ptr,sum=0;
printf("Enter number of elements: ");
scanf("%d",&n);
ptr=(int*)malloc(n*sizeof(int)); //memory allocated using malloc
if(ptr==NULL)
{
printf("Error! memory not allocated.");
exit(0);
}
printf("Enter elements of array: ");
for(i=0;i<n;++i)
{
scanf("%d",ptr+i);
sum+=*(ptr+i);
}
printf("Sum=%d",sum);
free(ptr);
return 0;
}
5.4 CALLOC()
Calloc means Allocating multiple blocks of memory. Calloc is another memory allocation
function that is normally used for requesting memory space at runtime for storing derived
data types such as structures and arrays. The malloc allocates a single block of storage space
but the calloc allocates multiple blocks of storage, each of the same size and then sets all
bytes to zero. The general format of calloc is:
ptr=(cast-type*) calloc(n,element-size);
56
The above statement can allocates contiguous space for n blocks each size of elements size
bytes. Here all bytes are initialized to zero and a pointer to the first byte of the allocated
region is returned. If there is not enough space a null pointer is returned.
57
{
scanf("%d",ptr+i);
sum+=*(ptr+i);
}
printf("Sum=%d",sum);
free(ptr);
return 0;
}
5.5 REALLOC()
Realloc is used to altering the size of a block: If the previously allocated memory is not
sufficient and then we need additional space for more elements. It is also possible that the
memory allocated is much larger than necessary and we need to reduce it. In mentioned
above cases, we can change the size of memory already allocated with the help of the
function realloc. This process is known as the reallocation of memory. For example, if the
original allocation is done by the statement
ptr = malloc(size);
then reallocation of space may be done by the statement
ptr = realloc(ptr, newsize);
this function allocates a new memory space of size newsize to the pointer variable ptr and
returns a pointer to the first byte of the new memory block. The newsize may be larger or
smaller than the size.
58
printf("Address of previously allocated memory: ");
for(i=0;i<n1;++i)
printf("%u\t",ptr+i);
printf("\nEnter new size of array: ");
scanf("%d",&n2);
ptr=realloc(ptr,n2);
for(i=0;i<n2;++i)
printf("%u\t",ptr+i);
return 0;
}
5.6 FREE()
Free: Releasing the used space.The Compile time storage of a variable has allocated and
released by the system in according to the storage class. In the dynamic runtime allocation, it
is our responsibility to release the space when it is not required. When the storage is limited
then the release of storage space becomes more important. When we no longer want the data
we stored in a block of memory and we do not intend to use that block for storing any other
information, we may release that block of memory for future use, using the free function.
free(ptr);
ptr means the pointer that has been created by using malloc or calloc.
5.7 SUMMARY
At the end of this unit we have covered dynamic memory allocation. In dynamic memory
allocation we have discussed about different memory management functions such as
malloc(), calloc(), free() and realloc() with some programming examples.
5.8 KEYWORDS
59
The C Programming Language (Ansi C Version) by Brian W. Kernighan, Dennis M.
Ritchie
Expert C Programming: Deep C Secrets by Peter Van, Der Linden Simplifying C
(First Edition 2010) Publication: Dreamtech by Harshal Arolkar and Sonal Jain
Programming in ANSI C (Fifth Edition 2011) Publication: Mc Graw Hill by
Balagurusamy
Programming in C (First Edition 2011) Publication: Oxford Higher Education by
Reema Thareja
60
UNIT 6: LINKED LIST
Structure
6.0 objectives
6.1 Introduction
6.2 Linked list
6.3 Types of linked list
6.4 Singly linked list
6.5 Applications of linked list
6.6 Summary
6.7 Keywords
6.8 Questions
6.9 References
6.0 OBJECTIVES
61
6.1 INTRODUCTION
A linked list consists of various nodes, and each node contains two things: One is the data,
and the other is the pointer, which will point to the next node. A linked list basically can
have n nodes, and each node is connected to its next node with the help of a pointer.
6.2 LINKED LIST
A linked list is a data structure. A data structure is nothing but how we organize and store the
data in memory. A linked list consists of various nodes, and each node contains two things:
One is the data, and the other is the pointer, which will point to the next node. A linked list
basically can have n nodes, and each node is connected to its next node with the help of a
pointer. There are two types of linked lists: singly linked lists (SLL) and doubly linked lists
(DLL).
In a SLL, we have a single pointer that’ll point to the next node and, therefore, it is called a
singly linked list. In a DLL, we have two pointers: One pointer will point to the next node, and
another will point to the previous node. That’s why we call it a doubly linked list.
In C programming, we use structures to create a linked list. The structure is a data type inside
which we can define variables with different data types (e.g., int, char, pointer, etc.).
For creating a linked list, we’ll define the structure of our linked list (using the struct data
type), which will represent what a single node in a linked list will look like. And then we’ll
actually create a linked list by assigning memory to use using the malloc() function.
62
Advantages of linked lists:
Linked lists have many advantages. Some of the very important advantages are:
1. Linked lists are dynamic data structures. i.e., they can grow or shrink during
the execution of a program.
2. Linked lists have efficient memory utilization. Here, memory is not pre-
allocated. Memory is allocated whenever it is required and it is de-allocated
(removed) when it is no longer needed.
3. Insertion and Deletions are easier and efficient. Linked lists provide flexibility
in inserting a data item at a specified position and deletion of the data item
from the given position.
4. Many complex applications can be easily carried out with linked lists.
Basically we can put linked lists into the following four items:
A single linked list is one in which all nodes are linked together in some sequential
manner. Hence, it is also called as linear linked list.
A double linked list is one in which all nodes are linked together by multiple links which
63
helps in accessing both the successor node (next node) and predecessor node (previous
node) from any arbitrary node within the list. Therefore each node in a double linked list
has two link fields (pointers) to point to the left node (previous) and the right node (next).
This helps to traverse in forward direction and backward direction.
A circular linked list is one, which has no beginning and no end. A single linked list can be
made a circular linked list by simply storing address of the very first node in the link field
of the last node.
A circular double linked list is one, which has both the successor pointer and predecessor
pointer in the circular manner.
64
6.4 SINGLY LINKED LIST
Operations Performed on an SLL
1. Insert an element in the linked list
Before inserting a node (element) into a linked list, you first have to create a node by
using malloc.
Also, before inserting a node (element), you first have to check whether the head is
pointing to the NULL or not — otherwise, it will give a segmentation fault.
if (head == NULL) {
return;
}
Now, there are three ways in which we can insert this node in the above linked list
Insert node at the beginning
For inserting a node that we’ve created that’s being pointed by a pointer called new
at the beginning of the linked list, we have to write the following code.
new ->link = head;
head = new;
65
What this will do is: It’ll first store the starting address of the node that’s being
pointed by the pointer head into the node that’s being pointed by pointer new. And
then it’ll assign the address of the new pointer to the head pointer.
If you directly assign the address of new pointer to the head pointer to insert the
node at the beginning before storing the address of the head pointer to the new
pointer, then the entire linked list will be lost because, in this case, there’s no pointer
that’ll be pointing to that memory location where the starting node of our linked list
is present.
This might be somewhat confusing at first to understand, so I suggest you read it a
number of times and try to understand it visually.
b. Insert node in the middle
Now to insert the node in the middle, we first have to think about where we’ll be
inserting the new node.
Let say we want to insert the newly created node after the second node in the above
linked list. For that, we have to reach the second node and then store whatever the
second node is pointing too into the new->link. And then, we’ll insert the node at
the location.
66
Insert node in the middle
67
So let’s traverse it.
Example of a linked list
Code for traversing the above linked list:
Output:
Here, first, we have a template for our node which defines what we have in our
linked list. Secondly, we have the main function inside, for which we’ve created a
new pointer t of type struct node (a pointer that we’ll use to traverse the list) and a
while loop which will print the data inside the list and then increment the pointer.
In this, we are now touching the head pointer. If we do this, then we may lose some
of the nodes inside our linked list as we have no pointer at the starting position of
the list.
After creating another pointer — say, t — you have a choice. You can either move t
or head. it doesn’t matter which because now you have two pointers at the starting
position of the linked list.
3. Delete an element from the linked list
Before deleting a node (element), you first have to check whether the head is
pointing to the NULL or not. Otherwise, it’ll give a segmentation fault.
Whenever you’re deleting an element from the linked list that you’ve created using
the malloc() function, you also have to free it up by using a free() function. It’s not
compulsory to free the space after deleting an element, but it’s a good practice to do
so.
Also, create a temporary pointer — say, t — to hold the node that you want to
delete, and then do the other operations. Otherwise, the node that you want to delete
will get lost.
Conditions to check:
There are three ways to delete a node in the same way as insertion.
a. Delete the node at the beginning
To delete the node at the beginning, create a new pointer t, and make it point to the
head. Now, we have to move the position of the head pointer one step ahead using
head = head->next. Then free up the t to delete the first element in a linked list.
68
Here, we have to identify which node we want to delete. After that, create a new
pointer, and make it point to the position where the head pointer is pointing.
Let say we want to delete a node whose data part has the value 3. Then, check if t-
>next->data is 3 or not. If the data part, has a value of 3, then create another pointer
— say, p — to hold the next part of the node whose value is 3. After that, free the
location that’s currently pointed by the t pointer, and then assign the address of
pointer p to t->next.
The function delete_at_mid(), is used for deleting the intermediate node in the list.
void delete_at_mid()
{
int ctr = 1, pos, nodectr; node *temp, *prev; if(start == NULL)
{
}
else
{
69
printf("\n Empty List.."); return ;
printf("\n Enter position of node to delete: "); scanf("%d", &pos);
nodectr = countnode(start); if(pos > nodectr)
{
}
}
}
}
70
Traversal and displaying a list (Left to Right):
To display the information, you have to traverse (move) a linked list, node by node from
the first node, until the end of the list is reached. Traversing a list involves the following
steps:
The function traverse() is used for traversing and displaying the information stored in the
list from left to right.
void traverse()
{
node *temp; temp = start;
printf("\n The contents of List (Left to Right):
\n"); if(start == NULL )
printf("\n Empty List");
else
{
while (temp != NULL)
{
printf("%d ->", temp -> data);temp = temp -> next;
}
}
printf("X");
}
Linked lists are used to represent and manipulate polynomial. Polynomials are
expression containing terms with non zero coefficient and exponents. For example:
o P(x) = a0 Xn + a1 Xn-1 n-1 X + an
Represent very large numbers and operations of the large number such as addition,
multiplication and division.
71
Linked lists are to implement stack, queue, trees and graphs.
Implement the symbol table in compiler construction
7.7 SUMMARY
At the end of this unit we have covered linked list. Also discussed about types of liked list.
We have also discussed singly linked list. At the end of this unit also covered applications of
linked list.
7.8 KEYWORDS
72
UNIT 7: FILE HANDLING IN C
Structure
7.0 Objectives
7.1 Introduction
7.2 Basics of File handling in C
7.3 Defining and opening a file
7.4 Closing file
7.5 Input and output operations on file
7.6 Error Handling during I/O Operations
7.7 Summary
7.8 Keywords
7.9 Questions
7.10 References
7.0 OBJECTIVES
7.1 INTRODUCTION
A File is a collection of data stored in the secondary memory. So far data was entered into the
programs through the keyboard. So Files are used for storing information that can be
processed by the programs. Files are not only used for storing the data, programs are also
stored in files. In order to use files, we have to learn file input and output operations. That is,
how data is read and how to write into a file.
73
In programming, we may require some specific input data to be generated several numbers of
times. commonly, it is not enough to only display the data on the console. The data to be
displayed only a limited amount of data or may be very large can be displayed on the console,
and since the memory is volatile, it is impossible to recover the programmatically generated
data again and again. However, if we want to do so, we have to store it onto the local file
system which is volatile and will be accessed every time. Here, comes the need of file
handling in C.
File handling in C allows us to create, update, read, and delete the files stored on the local file
system through our C program. The below following operations can be performed on a file.
There are two well defined ways to perform the file operation in c. the first one is known as
the low level I/O and uses UNIX system calls. The second method is referred to as the high-
level I/O operation and uses function in C’s standard I/O library. There are listed in table.
74
getw() This function reads an integer from a file.
putw() This function writes an integer from a file.
There are many other functions. Not all of them are supported by all compilers.
Mode Description
r Open the file for reading only.
w Open the file for writing only.
75
A Open the file for appending (or editing) data to it.
Both the filename and mode are specified as strings. They would be enclosed in double
quotation marks. When trying to open a file, one of the following things may happen:
If the mode is ’writing’, a file with the specified name is created. if the file does not
exist. The content is detected, if the file already exists.
If the mode is ‘appending’, the file is opened with the current contents safe. A file
with the specified name is created if the file does not exist.
If the mode is ‘reading’, and if it exists, then the file is opened with the current
contents safe otherwise an error occurs.
The file data is opened for reading and results is opened for writing. In case, the result file
already exists, its content is detected and the file is opened as anew file. If data file does not
exist, an error will occur.
76
when we need to reopen the same file in a different mode. The I/O library supports a function
to do this for us. It takes the following form:
fclose (file_pointer);
This should close the file associated with the FILE pointer file_pointer. The following
segment of a program is given below.
-----
FILE *p1, *p2;
p1 = fopen (“INPUT”, “w”);
p2 = fopen (“OUTPUT”, “r”);
-----
fclose (p1); fclose (p2);
This program opens two files and closes them after all operation on them are completed.
After the file is closed, its file pointer can be reused for another file. Whenever a program
terminates automatically all files are closed.
putc(c, fp1);
For example, the statement should read a character from the file whose file pointer is fp2.
c = getc(fp2);
77
The file pointer moves by one character position for every operation of getc and putc. The
getc will return an end-of-file maker EOF, when end of the file has been reached. Therefore,
the reading would be terminated when EOF is encountered.
putw(integer,fp); getw(fp);
The most compilers support two other functions, namely fprintf and fscanf, that can handle a
group of mixed data simultaneously.
The functions fprintf and fscanf perform I/O operations that are identical to the familiar printf
and scanf functions, expect of course that they work on files. The first argument of these
functions is a file pointer which state the file to be used. The general form of fprintf is
fprintf(fp,”control string”,list);
Where fp is a file pointer which is associated with a file that has been opened for writing. The
control string contains output specifications for the items in the list. The list may include
variables, constants and string.
Example:
fprintf(f1,”%s %d %f”,name,age,7.5);
Here, name is an array variable of type char and age is an int variable.
The general format of fscanf is
fscanf(fp, ”control string”, list);
78
This statement would state the reading of the items in the list from the file specified by fp,
according to the specifications contained in the control string.
Example:
fscanf(f2,”%s %d”, item, &quantity);
Similar to scanf, fscanf also returns the number of items that are successfully read. When the
end of file is reached, it returns the value EOF.
Thus, to check the status of the pointer in the file and to detect the error is the file. C provides
two status-enquiry library functions
feof() - The feof() function can be used to test for an end of file condition
Syntax
Example
feof(FILE *file_pointer);
if(feof(fp))
printf(“End of file”);
79
ferror() - The ferror() function reports on the error state of the stream and returns true if an
error has occurred.
Syntax
ferror(FILE *file_pointer);
Example
if(ferror(fp)!=0)
printf(“An error has occurred”);
7.7 SUMMARY
At the end of this unit we have covered basics of file handling in C. Also discussed defining
and opening a file and then closing file. We have also discussed input and output operations
on file. At the end of this unit also covered error handling during I/O operations.
7.8 KEYWORDS
80
UNIT 8: PREPROCESSORS
Structure
8.0 objectives
8.1 Introduction
8.2 Preprocessors
8.3 Types of preprocessor
8.4 Macro substitution directive
8.5 File inclusion directive
8.6 Compiler control directive
8.7 Summary
8.8 Keywords
8.9 Questions
8.10 References
8.0 OBJECTIVES
8.1 INTRODUCTION
The C preprocessor is a macro preprocessor (allows you to define macros) that transforms
your program before it is compiled. These transformations can be the inclusion of header file,
macro expansions etc. All preprocessing directives begin with a # symbol. For example,
#define PI 3.14
8.2 PREPROCESSORS
Most often it is made as a misconception that Preprocessors or macros are part of the
compilation of the program, but it is totally wrong. Preprocessor directives are the type of
81
macros and a phase before compilation takes place. It can be said that these are some set of
instructions given to compiler to perform actual compilation. They are also known as longer
construct abbreviations for macros which means the value in macros gets replaced with the
segment of codes. Macro is defined by a special symbol and has a symbol starting with “#”
Therefore these # define is a kind of special preprocessor followed by the actual compiler. In
this topic, we are going to learn about Preprocessor Directives in C.
The preprocessor has a special type of representation for its identification like any
preprocessor directive initiates itself by a special symbol of “#” followed by an identifier and
then the directive name. Whitespace is also allowed before and after the #. For example, #
include.
Header files: Inclusion of header files are a way in which declarations can get
substituted by program syntax and program body.
Expanding Macro: Defining macros are like abbreviating a piece of code which a C
preprocessor replaces the macros with their respective definition throughout.
Compilation by Conditions: According to various scenarios or various conditions
inclusion of certain parts of the program is possible by conditional compilation.
Line Control: If you use a program to combine or rearrange someone or more source
files into an intermediate file for compilation, you can use line control to inform the
compiler of where each source line originated from.
Directive Description
82
#define Substitutes a preprocessor macro
Preprocessors Examples
#define MAX_ARRAY_LENGTH 20
This directive tells the CPP to replace instances of MAX_ARRAY_LENGTH with 20. Use
#define forconstants to increase readability.
These directives tell the CPP to get stdio.h from System Libraries and add the text to the current
source file. The next line tells CPP to get myheader.h from the local directory and add the conten
to the current source file.
#undef FILE_SIZE
#define FILE_SIZE 42
83
This tells the CPP to undefine existing FILE_SIZE and define it as 42.
#ifndef MESSAGE
#define MESSAGE "You wish!"
#endif
This tells the CPP to define MESSAGE only if MESSAGE isn't already defined.
#ifdef DEBUG
/* Your debugging statements here */
#endif
84
library header files should be used with angle brackets is the information that it gives the
reader. The angle brackets make it obvious that
#include <string.h>
references a library file. With the alternate form
#include "string.h"
it’s not clear if string.h is a library header or local file with same name is being used.
Remember that header files are suffixed with .h extension by convention. We can write our
own header files and include them in programs. For ex.,
/* sll.h */
#include <stdio.h>
#include <stdlib.h>#define T 1
#define I 2
#define S 3
#define D 4
#define Q 5
#define TRAVERSE "enter 1 to TRAVERSE the list..."
#define INSERT "enter 2 to INSERT new value in the list..."
#define SEARCH "enter 3 to SEARCH a value in the list..."
#define DELETE "enter 4 to DELETE a value from the list..."
#define QUIT "enter 5 to QUIT the program..."
/* function declarations */
int traverse(Node **);
void insert(Node **, const int);
int search(Node **, const int);
int delete(Node **, const int);
Notice here that header file named sll.h contained declarations to be used in a particular
program. The fact that everything in the header file is compiled each time it’s #include’d
85
suggests that each header file should only contain declarations for one set of functions or
data. It’s better to contain several header files, each containing the declarations appropriate
for a particular function or module than put up all declarations for the entire program in one
giant header file.
Note: Care should be taken that there is no space between the # and the word define. Also
there should be atleast a single space between #define and the identifier and between
the identifier and the string. Also, there will be no semi-colon at the end of the statement.
There are different forms of macro substitution. The most common are:
1. Simple macro substitution
2. Argumented macro substitution
3. Nested macro substitution
Simple Macro Substitution
The simple macro substitutions are generally used for declaring constants in a C program.
Some
86
8.6 COMPILER CONTROL DIRECTIVES
These compiler control directives are used in different situations. They are:
Situation 1
You have included a file containing some macro definitions. It is not known whether a certain
macro has been defined in that header file. However, you want to be certain that the macro is
defined.
This situation refers to the conditional definition of a macro. We want to ensure that the
macro TEST is always defined, irrespective of whether it has been defined in the header file
or not. This can be achieved as follows:
87
1 #include”DEFINE.H”
2 #ifndef TEST
3 #define TEST 1
4 #endif
DEFINE.H is the header that is supposed to contain the definition of TEST macro. The
directive #ifndef TEST searches the definition of TEST in the header file and if it is not
defined, then all the lines between the #ifndef and the corresponding #endif directive are
executed in the program.
8.7 SUMMARY
At the end of this unit we have discussed the preprocessors. Also covered types of
preprocessors. We have also dealt with macro substitution directive. At the end of this unit
also covered file inclusion directive and compiler code directive.
8.8 KEYWORDS
88