Method I: In this method, one structure is written inside another structure
5.31 Random File Accessing: In random file accessing any required record can be read at random
5.32.3 The remove and rename Functions: These functions are used to remove and rename a file
int i,rno;
char name[15];
FILE *fp;
clrscr();
fp=fopen("SECOND.DAT","w+");
if(fp!=NULL) {
printf("Enter Roll No. and Name of 5 Students:\n");
for(i=0;i<5;i++) {
scanf("%d%s",&rno,name);
fprintf(fp,"%d %s\n",rno,name);
}
rewind(fp);
printf("\nFile Records Are:\n");
while(!feof(fp)) {
fscanf(fp,"%d %s\n",&rno,name);
printf("%3d %-15s\n",rno,name);
}
fclose(fp);
}
getch();
}
5.32.3 The remove and rename Functions: These functions are used to remove and rename a file.
(i) remove(): remove() is used to erase or remove a file from the disk.
Syntax:
remove(“filename”);
where filename refers to the name of the file to be removed.
Example:
remove(“Student.dat”);
(ii) rename(): rename() is used to rename an existing file.
Syntax:
rename(“old filename”,”new filename”);
Example:
rename(“Student.dat”,”Stdrec.dat”);
Make sure that files are closed before remove and rename functions will be used.
5.33 Errors during File Processing: When an error is encountered during file processing, the program execution will be terminated and error messages will be displayed. Following measures may be adopted to identify or avoid errors during file processing.
(i) ferror function can be used to detect any error during file accessing. This function will return a zero when there is no error, otherwise it will return a non-zero number.
FILE *fileptr;
if(ferror(fileptr)==0)
Prepared by Mr. K. G. Page 113 printf(“\nThe file is available for processing”);
else
printf(“\nError in accessing thefile!!!”);
(ii) To verify whether a file exists in the disk, the following definitions will help.
if(fileptr==NULL)
printf(“\nNo content or file does not exist”);
(iii) When data in a file may be exhausted, end of file condition will be encountered. Use the following definition to display end of file condition.
if(feof(fileptr)==EOF)
printf(“\nEnd of file is reached”);
Note that EOF is a macro which specifies the end of file condition.
Entering an invalid file name or trying to write data to a write protected disk are some of the other reasons for errors during file processing.
5.34 Command Line Arguments: What is a command line argument? It is a parameter supplied to a program when the program is invoked. This parameter may represent a filename the program should process. For example, if we want to execute a program to copy the contents of a file named A to another one named B, then we may use a command line like
C:\> Filecopy A B
Filecopy is the filename where the executable code of the program is stored. This eliminates the need of the program to request the user to enter the filenames during execution. How do these parameters get into the program?
We know that every C program should have one main function and that it marks the beginning of the program. But it can also take arguments like other functions. main()can take two arguments called argc and argv and the information contained in the command line is passed on to the program through these arguments, when main() is called up by the system.
The variable argc is an argument counter that counts the number of arguments on the command line. The argv is an argument vector and represents an array of character pointers that points to the command line arguments. The size of this array is equal to the value of argc. For the command line given above, argc is three and argv is an array of three pointers to strings as shown below.
argv[0] Filecopy argv[1] A
argv[2] B
In order to access the command line arguments, we must declare the main()as its parameters as follows:
void main(int argc, char *argv[]) {
………
………
}
The keyword void is optional. It is not necessary that we should always use the variable names argc and argv. In place of these any other variable names can also be used.
The first parameter in the command line is always program name and therefore argv[0]
always represents the program name.
Example:
#include<stdio.h>
Prepared by Mr. K. G. Page 114
#include<conio.h>
void main(int argc,char *argv[]) {
int i;
printf("Total Number of Arguments=%d\n",argc);
printf("Arguments Are:\n");
for(i=0;i<argc;i++) printf("%s\n",argv[i]);
getch();
}
Output:
C:\TURBOC3\SOURCE\T.EXE Total Number of Arguments=4 Arguments Are:
C:\TURBOC3\SOURCE\T.EXE 1
2 3
5.35 C Preprocessor: The C source code may include instructions for the compiler, which are executed at the beginning of the compilation process. These instructions are known as preprocessor commands or directives.
Rules for Defining a Preprocessor:
(i) All preprocessor directives must begin with the sharp sign (#).
(ii) They must start in the first column and on most C++ compiler there can be no space between sign and directive.
(iii) The preprocessor directive is not terminated by semicolon.
(iv) Only one preprocessor directive can occur in a line.
Example: Some commonly used preprocessor directives are:
#include, #define, #undef, #if, #else, #error etc.
These directives can be divided into three categories:
1. Macro substitution directives 2. File inclusion directives
3. Conditional compilation directives
1. Macro Substitution Directives: Macro substitution is a process where an identifier is replaced by a predefined string composed of one or more tokens. The preprocessor accomplishes this task under the direction of #define statement. This statement, usually known as a macro definition (or simply a macro) takes the following form:
#define identifier string
If this statement is included in the program at the beginning, then the preprocessor replaces every occurrence of the identifier in the source code by the string.
There are different forms of macro substitution. The most common forms are:
a) Simple Macro Substitution: Simple string replacement is commonly used to define constants. Examples of definition of constant are:
#define PI 3.141592
Prepared by Mr. K. G. Page 115
#define FALSE 0
#define SIZE sizeof(int)*4
#define TEST if(x>y)
Notice that we have written all macros (identifiers) in capitals. It is a convention to write all macros in capitals to identify them as symbolic constant. A definition, such as
#define M 5
will replace all occurrences of M with 5, starting from the line of definition to the end of the program. However, a macro inside a string does not get replaced. Consider the following two lines:
total=M*value;
printf(“M=%d\n”,M);
These two lines would be changed during preprocessing as follows:
total=5*value;
printf(“M=%d\n”,5);
Notice that the string “M=%d\n” is left unchanged.
Whenever we use expressions for replacement, care should be taken to prevent an unexpected order of evaluation. Consider the evaluation of the equation
ratio=D/A;
where D and A are macros defined as follows:
#define D 45-22
#define A 78+32
The result of the preprocessor’s substitution for D and A is:
ratio=45-22/78+32;
This is certainly different from the expected expression (45-22)/(78+32)
Correct result can be obtained by using parentheses around the strings as shown below:
#define D (45-22)
#define A (78+32)
It is a wise practice to use parentheses for expressions used in macro definitions.
b) Argumented Macro Substitution: The preprocessor permits us to define more complex and more useful form of replacements. It takes the form:
#define identifier(f1, f2,….,fn) string
Notice that there is no space between the macro identifier and the left parentheses. The identifiers f1, f2,……, fn are the normal macro arguments that are analogous to the formal arguments in a function definition.
There is a basic difference between the simple replacement and replacement of macros with arguments. When a macro is called, the preprocessor substitutes the string, replacing the formal parameters with the actual parameters. Here, the string behaves like a template.
A simple example of a macro with arguments is
#define CUBE(x) (x*x*x) If the following statement appears later in the program
volume=CUBE(side);
then the preprocessor would expand this statement to:
volume=(side*side*side);
Prepared by Mr. K. G. Page 116 Consider the following statement:
volume=CUBE(a+b);
This would expand to:
volume=(a+b * a+b * a+b);
which would obviously not produce the correct results. This is because the preprocessor performs a blind text substitution of the argument a+b in place of x. this shortcoming can be corrected by using parentheses for each occurrence of a formal argument in the string.
Example
#define CUBE(x) ((x) * (x) * (x))
This would result in correct expansion of CUBE(a+b)as shown below:
volume=((a+b) * (a+b) * (a+b))
Remember to use parentheses for each occurrence of a formal argument, as well as the whole string.
c) Nested Macro Substitution: We can also use one macro in the definition of another macro. This is, macro definitions may be nested. For example, consider the macro definitions:
#define SQUARE(x) ((x) * (x))
#define CUBE(x) (SQUARE(x) * (x))
#define SIXTH(x) (CUBE(x) * CUBE(x))
The preprocessor expands each #define macro, until no more macros appear in the text. For example, the last definition is first expanded into
((SQUARE(x) * (x)) * (SQUARE(x) * (x))) Since SQUARE(x) is still a macro it is further expanded into
((((x) * (x)) * (x)) * (((x) * (x)) * (x))) which is finally evaluated as x6.
2. File Inclusion Directives: A file inclusion directive is commonly used to include the contents