C Module 5
C Module 5
MODULE 5
FILES
So far in all the programs the input to the program and output were done through standard
input output devices like key board and monitor. Here the data entered through keyboard will
be stored in memory and processed during the execution of the program. These data
associated with the program will be lost on termination of the program. Similarly there is no
option for saving the output of a program displayed on the screen.
Also in case of large amount of data processing data entry through keyboard is time
consuming. We need to re-enter the entire data if any mistake occurs.
To solve these issues we can make use of file. A file can be defined as a collection
data stored on secondary storage devices like disks. So all the input data which needs to be
processed can be combined and stored on the memory device in the form of a data file. Thus,
data files allow us to store information permanently, and to access and alter that information
whenever necessary .There are two different types of data files, called stream-oriented data
files ,and system oriented data files.
Stream oriented data files can be subdivided into two categories. In the first category
are text files consisting of consecutive characters. These characters can be interpreted as
individual data items, or as components of strings or numbers. The second category of
stream-oriented data files, often referred to as unformatted data files, organizes data in to
blocks containing contiguous bytes of information. These blocks represent more complex
data structures, such as arrays and structures. Separate library functions are available for
processing these files.
System oriented data files are more closely related to the computer’s operating
system than stream oriented data files. They are somewhat more complicated to work with,
though their use may be more efficient for certain kinds of applications.
Different file operations in C programming are as follows:
Function Operation
Name
fopen() Creates a new file for use Opens a new existing file for
use
fclose Closes a file which has been opened for use
getc() Reads a character from a file
putc() Writes a character to a file
fprintf() Writes a set of data values to a file
fscanf() Reads a set of data values from a file
getw() Reads a integer from a file
putw() Writes an integer to the file
fseek() Sets the position to a desired point in the file
ftell() Gives the current position in the file
rewind() Sets the position to the begining of the file
(Table: 5.1)
USING FILE IN C
Following are the four main steps involved while using a file
• Declaring a file pointer variable
• Open a file.
• Read the file or write the data in the file
• Close the file.
DECLARING A FILE POINTER VARIABLE
First of all we need to declare a pointer to the FILE structure which is being defined
in <stdio.h>.This pointer is used to store the address of the FILE structure which is being
returned by fopen().This FILE structure contains details about the file which is being opened
by fopen().The pointer variable is used to traverse through the file.
For declaring any variable to file type pointer, it is necessary to write FILE in capital
and then pointer variable name.
FILE *p;
OPENING OF A FILE
For opening a file we use library function fopen().First we declare pointer variable as
FILE type pointer. We write this as –
FILE *p;
Then p=fopen(―filename‖,mode);
Here filename is the name of data file where data/record is stored. Mode
decides which operation (read, write or append) is to be performed with the data file.
MODES:-
1· write(w)
This mode open a new file for writing a record, if the filename already exists
then using this mode, the previous data/records are erased and the new data/record
entered is written in to the file.
Example:
p=fopen(“rec.dat”,”w”);
Here rec.dat is the filename and w is the mode.
2· append(a)
This mode open a file for appending a data/record. If the file does not exist
then a file with the same name will be created .In append mode already existing data
in the file wont be affected.
Example:
p=fopen(“rec.dat”,”a”);
Here rec.dat is the filename and a is the mode
3· read(r)
This mode is used for opening a file for reading purpose only.
Example:
p=fopen(“rec.dat”,”r”);
If the file rec.dat does not exist then compiler return NULL to the file pointer.
4· write+read(w+)
This mode is used both for reading and writing purpose. This is same as the
―w‖ mode but can also read the record which is stored in the file.
Example:
p=fopen(“rec.dat”,”w+”);
5· append+read(a+)
This mode is used both for reading and appending purpose. This is same as the
―a‖ mode but can also read the record which is stored in the file.
Example:
p=fopen(“rec.dat”,”a+”);
6· read+write(r+)
This mode is used both for reading and writing purpose. Opens an already
existing file for reading .It is also possible to write to the file also.
Example:
p=fopen(“rec.dat”,”r+”);
5.2CLOSING A FILE
The files which are opened using the fopen() function must be closed at end of the
program.this is written as-
fclose(p);
where p is the pointer to the file which has been opened using fopen()
FILE *p;
char name[10];
p=fopen(“rec.dat”,”w+”);
printf(“Enter your name”);
scanf(“%s”,name);
fprintf(p,“My Name is %s ”,name);
fclose(p)
}
Output
Enter your name
abc
Output on rec.dat as My Name is abc
2· fscanf()
This function is same as the scanf() function but this reads the data from the
file ,so this has one or more parameter that is the file pointer.
Syntax-
fscanf(fptr,‖control character‖,&variable-names);
/*Program to understand the use of fscanf() */
#include<stdlib.h>
#include<stdio.h>
main()
{
FILE *p;
char name[10];
int sal;
p=fopen("sal.dat","w+");
printf("NAME\t SALARY\n");
scanf("%s%d",name,&sal);
fprintf(p,"%s%d",name,sal);
fscanf(p,"%s %d",name,&sal);
printf("NAME\t SALARY\n");
printf("%s\t%d\n",name,sal);
fclose(p);
}
Output
NAME SALARY
xyz15000
From sal.dat as
NAME SALARY
xyz 15000
3· fgetc()
This function is same as the getc() function.It also read a single character from
a given file and increments the file pointer position. It returns EOF,If the end of the of
the file is reached or it encounters an error.
Syntax-
fgetc(fptr);
ch=fgetc(fptr);
wherefptr is a file pointer
4· fputc()
This function writes the character to the specified stream at the current file
position and increments the file position indicator.
Syntax-
fputc(ch,fptr);
Wherefptr is a file pointer and ch is a variable written to the file which is
pointed by the file pointer.
/*Program to understand the use of fputc() function */
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int main()
{
FILE *fptr;
char name[10],ch;
printf("Enter the file name:");
scanf("%s",name);
printf(“Enter a character”);
fptr=fopen(name,"w");
ch=getchar();
fputc(ch,fptr);
fclose(fptr);
return 0; }
Output
Enter the file name:
sjcet
Enter a character j
5· fgets()
This function is used to read a string from a given file and copies the string to
a memory location which is referenced by an array.
Syntax-
fgets(sptr,max,fptr) ;
When sptr is a string pointer, which points to an array,max is the length of the
array and fptr is a file pointer which points to a given file.
/*program to understand the use of fgets() */
#include<stdio.h>
#include<stdlib.h>
void main()
{
FILE *fptr;
char name[10],arr[50];
int i=0;
printf("Enter the file name:");
scanf("%s",name);
if((fptr=fopen(name,"r"))!=NULL)
{
if(fgets(arr,10,fptr)!=NULL)
while(arr[i]!='\0')
{
putchar(arr[i]);
i++;
}
}
fclose(fptr);
getch();
}
Output
Enter the file name:sjcet
palai
6· fputs()
This function is used to write a string to a given file.
Syntax-
fputs(sptr,fptr)
Where sptr is a string pointer, which points to an array and fptr is a file pointer
which points to a given file.
/*program to understand the use of fputs() */
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
void main()
{
FILE *fptr;
char name[10],arr[50];
printf("Enter the file name");
scanf("%s",name);
fptr=fopen(name,"w");
printf("The string is:");
gets(arr);
fputs(arr,fptr);
fclose(fptr);
}
Output
Enter the file name:sjcet
stringis:palai
1 fwrite()
This function is used for writing an entire block to a given file.
Syntax-
fwrite(buffer_address, size, count, file_pointer);
Here, buffer_address is the address of the memory area, whose contents are to be
written to the file denoted by the fourth argument file_pointer. The second argument size
specifies the number of bytes of a block (record) and count specifies the number of blocks
of data to be written to the file.. The function returns the number of blocks of data written to
the file. On successful execution, the value returned by the function would be the value of
the third argument, count. Otherwise, the value would be less than the value of count
Example:
# include<stdlib.h>
# include<stdio.h>
struct emp
{
int empno ;
char name [20] ;
float salary;
}
int main()
{
int i, n;
fp = fopen("emp.dat", "w") ;
printf ( "Enter the number of employees \n" ) ;
scanf("%d", &n) ;
printf ( "Enter empno, name and salary of %d employees \n" , n) ;
for (i = 1; i < = n ; i + + )
{
scanf ( "%d%s%f" , &e.empno, e.name, &e.salary);
fwrite(&e, sizeof(e), 1, fp) ;
}
fclose(fp);
return 0 ;
}
2 fread()
This function reads an entire block from a file.
Syntax-
fread (buffer_address , size, count, file__pointer) ;
The first argument buffer_address is the address of the memory area, to which the contents
read from the file denoted by the fourth argument file_pointer are to be written into. The
second argument size specifies the number of bytes of a block (record) and count specifies
the number of blocks of data to be read from the file. The function returns the number of
blocks of data read from the file. On successful execution, the value returned by the function
would be the value of the third argument, count. Otherwise, the value would be less than the
value of count
Example:
#include <stdio.h>
# include<stdlib.h>
struct emp
{
int empno;
char name [20] ;
float salary;
};
int main ()
{
struct emp e;
FILE *fp;
int i, n;
3. Copy all the records of f ilel to f ile2 except the record to be deleted
4. Remove the file f ilel.
5. Rename the file file2 as f ilel
PROGRAM
#include <stdio.h>
# include<stdlib.h>
struct emp
{
int empno;
char name [20] ;
float salary;
};
int main ()
{
FILE * fin, *fout;
struct emp e ; int eno;
1.feof()
The macro feof() is used for detecting whether the file pointer is at the end of
file or not. It returns nonzero if the file pointer is at the end of file, otherwise it
returns zero.
2.ferror()
The macro ferror() is used for detecting whether an error occur in the
file on file pointer or not. It returns the value nonzero if an error, otherwise it
returns zero.
Syntax-
ferror(fptr);
/*Program to understand the use of ferror() */
#include<stdlib.h>
#include<stdio.h>
main()
{
FILE *fptr;
char name[15],ch;
printf(“Enter the file name”);
scanf(“%s”,name);
if((fptr=fopen(name,”r”)!=NULL)
while((ch=getc(fptr))!=EOF)
{
printf(“%c”,ch);
if(ferror(fptr))
{
printf(“Error in file”);
exit(1);
}
}
fclose(fptr);
}
3.unlink()
This function is used for deleting the file from the directory.
Syntax-
unlink(filename);
Example:
if((fptr=fopen(name,”r”)!=NULL)
unlink(name);
1) fseek()
This function is used for setting the pointer position in the file at the specified
byte and the syntax of its usage is as follows:
(Table: 5.2)
Example:
fseek(p,5L,0)
0 means pointer position is beginning of the file; from this statement pointer
position is skipped 5 bytes forward from the current position.
/*Program to understand the use of fseek() */
#include<stdio.h>
#include<stdlib.h>
int main()
{
FILE *fp;
int n,ch;
fp=fopen("text.txt","r");
printf("\n Contents of file\n");
while((ch=fgetc(fp))!=EOF)
printf("%c",ch);
printf("\nHow many characters including spaces would you like to
skip?:");
scanf("%d",&n);
fseek(fp,n,0);
printf("\nInformation after %d bytes\n",n);
while((ch=fgetc(fp))!=EOF)
printf("%c",ch);
fclose(fp);
return 0;
}
2) ftell()
ftell(fptr) -where fptr is the file pointer
This function returns the value of the current pointer position in the file. The
value is count from the beginning of the file
/*Program to understand the use of ftell() */
#include<stdio.h>
#include<stdlib.h>
int main()
{
FILE *fp;
fp=fopen("text.txt","r");
fseek(fp,21,SEEK_SET);
ch=fgetc(fp);
while(!feof(fp))
{
printf("%c\t",ch);
printf("%d\n",ftell(fp));
ch=fgetc(fp);
}
fclose(fp);
return 0;}
3) rewind()
This function is used to move the file pointer to the beginning of the given
file.This can be written as
Syntax-
rewind(fptr);
/*Program to understand the use of rewind() */
#include<stdio.h>
#include<stdlib.h>
int main()
{
FILE *fp;
char c;
clrscr();
fp=fopen("text.txt","r");
fseek(fp,18,SEEK_SET);
printf("Pointer is at %d\n",ftell(fp));
printf("Before rewind:\t");
while(!feof(fp))
{
c=fgetc(fp);
printf("%c",c);
}
printf("\nAfter rewind():\t");
rewind(fp);
while(!feof(fp))
{
c=fgetc(fp);
printf("%c",c); }
return 0;}
struct emp
{
int empno;
char name [20] ;
float salary;
};
int main ()
{
FILE *fp;
int nor, last_byte;
fp = fopen("emp.dat", "r" );
fseek(fp, 0L, SEEK_END);
last_byte = ftell(fp);
nor = last_byte/sizeof(struct emp) ;
printf ( "The number of records = %d" , nor) ;
fclose(fp);
return 0 ;
The structure struct emp is defined with the fields empno, name and salary. In the
main(), variable fp is declared to be a pointer to FILE type. The integer variables nor and
last_byte collects the number of records in the file emp. dat and the last byte number of the
file respectively. To be able to find the number of records in the file emp. dat, it is first
opened in read mode with the statement fp = fopen ( " emp. dat" , "r"); once the file is
opened, the file pointer points to the first byte of the file. The file pointer is moved to the last
byte with the statement fseek (f p, 0L, SEEK_END) ; The current position (the last byte
number) of the file pointer is then retrieved and assigned to the variable last_byte with the
statement last_byte = ftell (fp) ; Now, the variable last_byte has collected the size of the file
emp.dat in terms of bytes. So, the expression last_byte/sizeof (struct emp) evaluates to the
number of records in the file emp. dat and it is assigned to the variable nor, which is then
displayed. Before the program terminates, the file emp.dat is closed.
The following is the sequence of steps to be used to read nth record from a file:
1. Open the file in read mode. (Mode of opening: "r" or "rb")
2. Accept the record number of the record to be read.
3. Obtain the starting byte number of the record to be read.
4. Move the file pointer to the starting byte position of the record.
5. Read the record and display it.
6. Close the file.
#include <stdio.h>
#include <stdlib.h>
struct emp
{
int eno ;
char name [20] ;
float salary;
};
int main ()
{
FILE *fp;
int recno;
struct emp e;
fp = fopen("emp.dat", "rb");
if (fp == NULL)
{
printf ( "emp.dat cannot be opened" ) ;
exit(0);
}
The structure struct emp is defined with the fields empno, name and salary.
In the main (), variable fp is declared to be a pointer to FILE type and it is to denote the file
emp.dat, whose records are to be read directly, e is declared to be a variable of struct emp
type, which is to collect the employee details read from the file emp.dat directly. The
statement fp = f open ( " err.dat", "r") ; opens the file in read mode and assigns reference
to the file to the pointer. The record number of the record to be read accepted into the
variable recno. The file pointer of the file is moved fp to the beginning of the record to be
read with the statement fseek ( fp, (recno-1) *sizeof (e) , SEEK_SET) ; . Note that the
expression (recno-1) *sizeof (e) evaluates to the starting byte number of the record to be
read. Once the file pointer is made to point to the record to be read, the record is read into the
variable e with the following statement fread (&e, sizeof(e), 1, fp) ; The contents of the
variable e are then displayed.
#include <stdio.h>
#include <stdlib.h>
struct emp
{
int eno;
char name [20] ;
float salary;
};
int main ()
{
FILE *fp;
int position, recno;
struct emp e;
fp = fopen("emp.dat", " r + " ) ;
i f ( f p = = NULL)
{
p r i n t f ( " e m p . d a t cannot be opened") ;
exit(0);
}
scanf("%d", &recno);
fseek(fp, (recno-1)*sizeof(e), SEEK_SET);
printf ( "Enter new details of the employee \n" ) ;
scanf("%d%s%f", &e.eno, e.name, &e.salary);
fwrite(&e, sizeof(e), 1, fp) ; fclose(fp);
return 0;
}
The structure struct emp is defined with the fields empno, name and salary. In the
main (), variable fp is declared to be a pointer to FILE type and it is to denote the file
emp.dat, records of which are to be updated, e is declared to be a variable of struct emp
type, which is to collect an employee's new details entered through the keyboard. The
statement fp = f open (―emp. dat", "r+") ; opens the file in update mode and assigns
reference to the file to the file pointer fp. The record number of the record to be updated is
accepted into the variable recno. The file pointer of the file is moved to the beginning of the
record to be updated with the statement fseek (fp, (recno-1) *sizeof (e) , SEEK_SET) ; Note
that the expression (recno-1) *sizeof (e) evaluates to the starting byte number of the record to
be updated. Once the file pointer is made to point to the record to be updated, new values for
the record are accepted into the variable e and they are written back to the file with the
statement fwrite(&e, sizeof(e), 1, fp) ;
c) Storage of numbers
The only function that is available for storing numbers in a disk file is the fprintf ()
function. Text and characters are stored one character per byte. Numbers are stored as strings
of characters. Thus, 1234.even though it occupies two bytes in memory, when transferred to
the disk using fprintf (), would occupy four bytes, one byte per character. Hence if large
amount of numerical data is to be stored in a disk file, using text mode may turn out to be
inefficient. The solution is to open the file in binary mode and use those functions (fread ()
and fwrite ()) which store the numbers in binary format. It means each number would occupy
same number of bytes on disk as it occupies in memory
BINARY MODES
1) wb
This mode opens a binary file in write mode
2) rb
This mode opens a binary file in read mode
3) ab
This mode opens a binary file in append mode
4) r+b
This mode opens a pre-existing file in read and write mode i.e. file can be read
and written
4) w+b
This mode creates a new file in read and write mode
5) a+b
This mode opens a file in append mode i.e. data can be written at the end of
file. If file does not exist a new file is created.
In general terms, the decomposition of a word into distinct bit fields can be written as
struct tag
{
member 1: bitwidth;
member 2: bitwidth;
…………
member m: bitwidth;
};
Here each bit field is an integer that has a specified width. By this technique the exact
number of bits required by the bit field is specified by bitwidth. So the whole word is not
required to hold a field. The interpretation of these bit fields may vary from one C compiler
to another. For example, some C compilers may order the bit fields from right to left, where
as other C compilers will order them from left to right.
Example:
struct sample
{ unsigned a:1;
unsigned b:3;
unsigned c:2;
unsigned d:1;
};struct sample v;
The first declaration defines a structure which is subdivided in to four bit fields, called
a,b,c and d. These bit fields have widths of 1 bits,3 bits,2 bits and 1 bit ,respectively. Hence,
the bit fields occupy a total of 7 bits within a word of memory. Any additional bits within the
word will remain uncommitted.
Following figure illustrates the layout of the bit fields within the word, assuming a 16-bit
word with the fields ordered from right to left.
15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
(Fig:5.1)
The integer, argc is the argument count. It is the number of arguments passed
into the program from the command line, including the name of the program.
argv is a array of character pointers which provides the names of arguments. argv[0] is the
name of the program, or an empty string if the name is not available. After that, every
element number less than argc is a command line argument. Almost any program that wants
its parameters to be set when it is executed could use this. One common use is to write a
function that takes the name of a file and outputs the entire text of it onto the screen.
Output
Total number of arguments are:4
./a.out ab cd ef
Program 2:
#include <stdio.h>
int main ( int argc, char *argv[] )
{
if ( argc != 2 ) /* argc should be 2 for correct execution */
{
/* We print argv[0] assuming it is the program name */
printf( "usage: %s filename", argv[0] );
}
else
{
// We assume argv[1] is a filename to open
FILE *file = fopen(argv[1], "r" );
/* fopen returns 0, the NULL pointer, on failure */
if ( file == 0 )
{
printf( "Could not open file\n" );
}
else
{
char x;
while ( ( x = fgetc( file ) ) != EOF )
{
printf( "%c", x );
}
}
fclose( file );
}
}
The following are the general rules governing the preprocessor directives:
1. All preprocessor directives should start with the symbol #. ANSI allows the symbol to
be preceded by spaces or tabs.
2. Only one directive can appear in a line.
3. The directives are not terminated by semicolons.
4. The preprocessor directives can be placed anywhere in a source program. The
directives apply to the source code, which follows them.
The preprocessor directives are broadly classified into three types based on the purposes
for which they are used.
The #include preprocessor directive has already been used in all our programs and we
know that it is used to include a file as part of the source program file. For example, in
response to the directive #include <stdio.h>, the preprocessor expands the source file by
embedding the contents of the header file stdio . h, before the source program is submitted to
the C compiler. In all our earlier programs, # include has been used to include the header
files. As a matter of fact, contents of any text file can be included as part of a source program
with the help of the directive. If the file name is enclosed within double quotes, then the file
is expected to be available in the current working directory.
Example
#include <stdio.h>
Here, MACRO_NAME is the name of a macro; it should conform to the rules, which
are used to construct valid identifiers and normally it is written using upper case letters just
to distinguish it from the identifiers. segment_of_text is actually the string referred to by the
MACRO_NAME. Once a symbolic name (MACRO_NAME) is assigned to a segment of
text, throughout the program, the symbolic name can be used in place of the segment of text.
The preprocessor then replaces all the occurrences of the MACRO_NAME by the segment
of text.
Example
(i) #def ine COUNT 10
COUNT becomes the symbolic name for the constant 10
(ii) #def ine NO_OF_STUDENTS 10 0
NO_OF_STUDENTS becomes the symbolic name for the constant 100
(iii) #def ine OR | |
The symbolic name OR can be used in place of the logical operator ||
int main ()
{
int r;
float area, circum;
printf (''Enter radius of a circle \n" ) ;
scanf(u%d", &r) ;
area = PI * r * r ;
circum = 2 * PI * r;
printf("Area = %f \n" , area) ;
printf("Circumference = %f \n" , circum) ;
return 0 ;
}
The preprocessor acts on the source program produces the following output. Note
that the macro PI has been replaced by the value 3.14 by the preprocessor. The process of
replacement of macros by their corresponding segments of texts is termed Macros
Substitution. The output produced by the preprocessor is then submitted to the compiler for
compilation.
if (a > 0) a = a + 1
If we are to assign a symbolic name for this, we would define a macro INCREMENT_A as
follows:
#define INCREMENT_A if ( a > 0) a = a + 1
Consider another C conditional statement i f ( b > 0 ) b = b + 1
If we are to assign a symbolic name for the statement, we can define another macro
INCREMENT_B as follows:
As can be seen, both the statements have the same structure except the variable names. Here,
we can define only one macro by name INCREMENT with an argument and it can represent
both the conditional statements considered above. The macro is defined as follows:
Nesting of MACROS
We can also use one macro in the definition of another macro. That is macro definitions
may be nested.
Finds the cube of the value of x, where square (x) finds the square of the value of x.
A macro is a symbolic name assigned to a segment of text. The segment of text can be
merely a sequence of digits or it can be a string enclosed within double quotes or it can even
be a C statement, whereas a function is a self-contained program by itself. As far as usage of
the macros with arguments and functions in programs is concerned, they look alike. But
there are significant differences between them.
Macros are expanded to their Function calls are not affected during
replacement strings during preprocessing.
preprocessing.
Advantages of Macros
When macros are used as symbolic names for some replacement strings, which are
used quite often in a program, following are the advantages offered by macros definition:
1. The macros definition increases the degree of readability of programs since the names
selected for the macros are normally selected to be reflective of the meaning of the
replacement strings.
2. The macros definition enhances easier modifiability since any change made in the
replacement string in the macro definition will be effected in all its occurrences
throughout the program
1. To make the programs portable so that they can be compiled according to the
machines being used.
2. To make the programs suit different situations without the need for rewriting the
programs from scratch.
Conditional Compilation is accomplished with the help of the following conditional
compilation directives:
#ifdef MACRO_NAME
statements-1
#else
statements-2
#endif
In the above program, a macro by name SUM has been defined with the directive
#define SUM in the main( ) , since #ifdef SUM evaluates to true, the statements r = a + b;
printf ( "sum = %d‖, r) ; are selected for compilation. The statements between #else and
#endif are ignored by the compiler. As a result, when the program is run, the program finds
the sum of the variables a and b, and displays it.
If we remove the definition of the macro SUM and compile and run the program, the
program finds the difference between a and b, and displays it. This is because, in the absence
of the macro SUM, the statements between #else and #endif are compiled.
#ifdef macrol
statements-1
#elif macro2
statements-2
#elif macro3
statements-3
#elif macro4
statements-4
#else
statements-5
endif
Here, only one out of many alternative blocks of code will be considered for
compilation depending on what macro has been defined previously.
printf("Remainder = %d \n" , r) ;
#endif
return 0 ;
}
In the above program, since the macro defined is MULT, the statements:
r - a * b;
printf ("Product = %d \n" , r) ;
only will be compiled and other alternative blocks are skipped by the compiler. As a result,
when the program is run, it displays the product of the values of the variables a and b.
# if directive
The # if directive is to select a block of code for compilation when a test-expression
(rather than a macro) evaluates to true. Otherwise, to ignore the block of code for
compilation.
#if - #endif
#if - #else - #endif
#if - #elif - #else - #endif
are similar to their #ifdef counterparts except the fact that, here macros are replaced by test-
expressions.
The above example programs, which were written to illustrate conditional compilation,
were just to highlight the fact that the compilation can be done selectively with respect to
blocks of code. When we compiled and ran the programs, we understood this fact. In real life
programming environments, we need to prepare programs in such a way that the programs
run on different types of machines or the programs should cater to different clients. The
facility of conditional compilation plays an important role since the same programs are made
to suit to the differing environments by conditionally compiling the required sections of code
for a particular environment.