Unit- 4 File Management in C
Introduction
It is often necessary to generate specific input data multiple times. Sometimes, simply displaying the data on the console is not enough.
The data to be displayed may be very large, and only a limited amount of data can be displayed on the console. Additionally, since memory is volatile, it is impossible to recover programmatically generated data repeatedly. However, we can store the data onto the local file system, which is non-volatile and can be accessed every time. This is where file handling in C comes in.
File handling in C enables us to create, update, read, and delete files stored on the local file system using our C program. The following operations can be performed on a file:
- Creating a new file
- Opening an existing file
- Reading from a file
- Writing to a file
- Deleting a file
We can also perform other operations on a file, such as copying, renaming, and moving. These operations can be very useful in managing files and directories in our C programs. In order to perform these operations, we use various file handling functions provided by the C standard library, such as fopen(), fclose(), fread(), fwrite(), remove(), rename(), and rewind(). By mastering these functions, we can create powerful file management systems in our C programs.
High Level I/O Functions
| Function Name | Operation |
|---|---|
| fopen() | Creates a new file or opens an existing file |
| fclose() | Closes an opened file |
| getc() | Reads a character from a file |
| putc() | Writes a character to a file |
| fprintf() | Writes formatted data to a file |
| fscanf() | Reads formatted data from a file |
| getw() | Reads an integer from a file |
| putw() | Writes an integer to a file |
| fseek() | Sets the file position indicator to a specific location |
| ftell() | Returns the current file position indicator |
| rewind() | Resets the file position indicator to the beginning of the file |
Defining and Opening a File
Defining a file is the process of creating a file and associating it with a file pointer. The syntax for defining a file is as follows:
FILE *fp;
fp = fopen("filename", "mode");
FILE:
FILEis a predefined structure in C that is used to handle files.- It is defined in the
stdio.hheader file. - The
FILEstructure contains all the necessary information about a file, such as its name, location, size, and type. - A
FILEpointer is used to access a file and perform operations on it, such as reading and writing data.
The mode parameter specifies the purpose for which the file is to be opened. The following modes are available:
"r": Open for reading."w": Open for writing. If the file exists, its contents are truncated. If the file does not exist, a new file is created."a": Open for writing. If the file exists, new data is written to the end of the file. If the file does not exist, a new file is created."r+": Open for reading and writing."w+": Open for reading and writing. If the file exists, its contents are truncated. If the file does not exist, a new file is created."a+": Open for reading and writing. If the file exists, new data is written to the end of the file. If the file does not exist, a new file is created.
Here is an example of how to define and open a file in C:
#include <stdio.h>
void main()
{
FILE *fp;
fp = fopen("example.txt", "w");
if (fp == NULL)
printf("File does not exist \n");
else
printf("File opened successfully \n");
fclose(fp);
}
File opened successfully
Closing a file
Closing a file is important to ensure that all of the data written to the file is saved and that the file is released from memory. To close a file, we use the fclose() function. The syntax for closing a file is as follows:
fclose(file_pointer);
- Here,
file_pointeris the file pointer that we want to close. - The
fclose()function returns 0 if the file is closed successfully, and a nonzero value if there is an error. - It is good practice to close a file after we are done using it, as leaving a file open can lead to data corruption or other issues.
Input Output Operations On File
putc() and getc() These functions are useful for reading and writing data to and from files.
getc() function
The getc() function is used to read a character from a file. Its syntax is as follows:
int getc(FILE *file_pointer);
- Here,
file_pointeris the file pointer that we want to read from. - The
getc()function returns the character read as anunsigned charcast to anint, orEOFif the end of the file is reached or an error occurs.
Example:
#include <stdio.h>
void main()
{
FILE *fp;
int ch;
fp = fopen("example.txt", "r");
if(fp == NULL)
printf("File is not exist\n");
else
{
ch = getc(fp);
printf("%c", ch);
}
fclose(fp);
}
H
Read Whole String
#include <stdio.h>
void main()
{
FILE *fp;
int ch;
fp = fopen("example.txt", "r");
if (fp == NULL)
printf("File is not exist\n");
else
{
while ((ch = getc(fp)) != EOF)
printf("%c", ch);
}
fclose(fp);
}
Hello
What is EOF:
- EOF stands for "End of File".
- It is a constant value that is returned by some file handling functions in C, such as
getc(), when the end of a file has been reached. - The value of EOF is typically -1, but it can vary depending on the implementation.
- It is used as a sentinel value to indicate that there is no more data to be read from a file.
putc() function
The putc() function is used to write a character to a file.
Its syntax is as follows:
int putc(character, FILE *file_pointer);
- Here,
characteris the character to write, andfile_pointeris the pointer for the file to write to. putc()returns the character written as anunsigned charcast to anint, orEOFif an error occurs.
#include <stdio.h>
void main()
{
FILE *fp;
int ch;
fp = fopen("example.txt", "w+");
if (fp == NULL)
{
printf("File not opened");
}
putc('a', fp);
fclose(fp); // closing file
}
getw and putw functions
putw() function
The putw() function is used to write an integer to a file
syntax:
putw(int value, FILE *file_pointer);
- Here,
valueis the integer to write, andfile_pointeris the pointer for the file to write to. putw()returns a non-negative value if the write is successful, andEOFif an error occurs.
Example:
#include <stdio.h>
void main()
{
FILE *fp; //declares a file pointer
int num; //declares a variable
fp = fopen("test.txt", "w"); //opens the file test.txt for writing
putw(5, fp); //writes the number 5 to the file
fclose(fp); //closes the file
}
This program writes the integer 1234 to the file example.txt.
getw() function
The getw() function is used to read an integer from a file.
syntax:
getw(FILE *file_pointer);
- Here,
file_pointeris the file pointer that we want to read from. getw()returns the integer read, orEOFif the end of the file is reached or an error occurs.
Example:
#include <stdio.h> //Include the standard input/output library
void main() //Start of the main function
{
FILE *fp; //Declare a pointer to a file type
int get; //Declare an integer variable
fp = fopen("test.txt", "r"); //Open the file test.txt in read mode
get = getw(fp); //Read the first integer from the file
printf("Value in test.txt is : %d", get); //Print the integer
fclose(fp); //Close the file
}
Value in test.txt is : 5
fprintf and fscanf functions
fprintf() function
The fprintf() function is used to write formatted data to a file.
Its syntax is as follows:
fprintf(FILE *pointer, "Control String", list);
fprintf()returns the number of characters written, or a negative value if an error occurs.
Example:
#include <stdio.h>
int main()
{
FILE *fp;
char name[] = "Naruto";
int age = 20;
float height = 5.8;
fp = fopen("example.txt", "w+");
fprintf(fp, "Name: %s\nAge: %d\nHeight: %f\n", name, age, height);
fclose(fp);
return 0;
}
This program writes the formatted data to the file example.txt.
fscanf() function
The fscanf() function is used to read formatted data from a file.
Its syntax is as follows:
int fscanf(FILE *file_pointer, const char *format, list);
- Here,
file_pointeris the file pointer that we want to read from,formatis the format string, and...are the variables to store the formatted data. fscanf()returns the number of input items successfully matched and assigned, orEOFif the end of the file is reached or an error occurs.
Example:
#include <stdio.h>
int main()
{
FILE *fp;
char name[20];
int age;
float height;
fp = fopen("example.txt", "r");
fscanf(fp, "Name: %s\nAge: %d\nHeight: %f", name, &age, &height);
printf("Name: %s\nAge: %d\nHeight: %f\n", name, age, height);
fclose(fp);
return 0;
}
This program reads the formatted data from the file example.txt and prints it on the console.
Here is an example program that writes data to a file and then reads that data from the file:
#include <stdio.h>
int main()
{
FILE *fp;
char name[20];
int age;
float height;
// Open the file for writing
fp = fopen("example.txt", "w+");
if (fp == NULL)
{
printf("Error: could not open file for writing\n");
return 1;
}
// Write data to the file
fprintf(fp, "Name: %s\nAge: %d\nHeight: %f\n", "John", 25, 5.8);
// Close the file
fclose(fp);
// Open the file for reading
fp = fopen("example.txt", "r");
if (fp == NULL)
{
printf("Error: could not open file for reading\n");
return 1;
}
// Read data from the file
fscanf(fp, "Name: %s\nAge: %d\nHeight: %f", name, &age, &height);
// Print the data to the console
printf("Name: %s\nAge: %d\nHeight: %.1f\n", name, age, height);
// Close the file
fclose(fp);
return 0;
}
Name: John
Age: 25
Height: 5.8
This program writes the data "Name: John, Age: 25, Height: 5.8" to the file example.txt, and then reads that data from the file and prints it to the console.
Error handling during I/O operations:
During input/output (I/O) operations, there are a number of typical error situations that can occur.
- These include opening a file that does not exist
- Attempting to read from or write to a file that is not open
- Attempting to read beyond the end of a file.
- To handle these situations, we can use error handling techniques such as checking return values from.
feof() function
The feof() function is used to check whether the end of a file has been reached.
Its syntax is as follows:
int feof(FILE *file_pointer);
- Here,
file_pointeris the file pointer that we want to check. feof()returns a nonzero value if the end of the file has been reached, or 0 otherwise.
Example:
#include <stdio.h>
int main()
{
FILE *fp;
int ch;
fp = fopen("example.txt", "r");
if (fp == NULL)
{
printf("Error: could not open file\\n");
return 1;
}
while (!feof(fp))
{
ch = getc(fp);
printf("%c", ch);
}
fclose(fp);
return 0;
}
This program reads the data from the file example.txt character by character until the end of the file is reached, and then prints the data to the console.
ferror() function
The ferror() function is used to check whether an error has occurred during a file operation.
Its syntax is as follows:
int ferror(FILE *file_pointer);
- Here,
file_pointeris the file pointer that we want to check. ferror()returns a nonzero value if an error has occurred, or 0 on Success.
Here is an example program that uses the ferror() function:
#include <stdio.h>
int main() {
FILE *fp;
fp = fopen("example.txt", "r");
if (fp == NULL)
{
printf("Error: could not open file\n");
return 1;
}
putc('A', fp);
if (ferror(fp))
{
printf("Error: an error occurred during file operation\n");
return 1;
}
fclose(fp);
}
Output:
Error: an error occurred during file operation
This program opens the file example.txt for reading and checks whether an error occurred during the file operation using the ferror() function. If an error did occur, the program prints an error message to the console.
Random Access to Files
Random access to files involves reading or writing data to a file at a specific location, rather than sequentially from the beginning to the end of the file. This can be useful for editing or updating specific parts of a file without having to read or rewrite the entire file.
ftell() function
The ftell() function is used to determine the current file position indicator. Its syntax is as follows:
long ftell(FILE *file_pointer);
- Here,
file_pointeris the file pointer that we want to check. ftell()returns the current file position indicator as along int, or1Lif an error occurs.
Example:
#include <stdio.h>
int main()
{
FILE *fp;
int ch;
fp = fopen("example.txt", "r");
if (fp == NULL)
{
printf("Error: could not open file\n");
return 1;
}
printf("Current file position: %ld\n", ftell(fp));
ch = fgetc(fp);
printf("Current file position: %ld\n", ftell(fp));
fclose(fp);
}
Output:
Current file position: 0
Current file position: 1
This program opens the file example.txt for reading and gets the current file position using the ftell() function. It then prints the current file position to the console.
rewind() function
The rewind() function is used to reset the file position indicator to the beginning of the file.
Its syntax is as follows:
void rewind(FILE *file_pointer);
- Here,
file_pointeris the file pointer that we want to reset.
Example:
#include <stdio.h>
int main()
{
FILE *fp;
int ch;
fp = fopen("example.txt", "r");
if (fp == NULL)
{
printf("Error: could not open file\n");
return 1;
}
printf("Current file position: %ld\n", ftell(fp));
ch = fgetc(fp);
printf("Current file position: %ld\n", ftell(fp));
rewind(fp);
printf("After rewind file position: %ld\n", ftell(fp));
fclose(fp);
}
Output:
Current file position: 0
Current file position: 1
After rewind file position: 0
This program opens the file example.txt for reading, gets the current file position using the ftell() function, resets the file position indicator to the beginning of the file using the rewind() function, and then gets the current file position again using the ftell() function. It then prints both file positions to the console.
fseek() function
The fseek() function is used to set the file position indicator to a specific location within a file. Its syntax is as follows:
int fseek(FILE *file_pointer, long int offset, int position);
- Here,
file_pointeris the file pointer that we want to set the position for,offsetis the number of bytes from theposition, andpositionis the point of reference for the offset. fseek()returns 0 on success, and a nonzero value on failure.
The position parameter can be one of the following:
SEEK_SETor0: Beginning of fileSEEK_CURor1: Current position of the file pointerSEEK_ENDor2: End of file
Example:
#include <stdio.h>
int main()
{
FILE *fp;
fp = fopen("example.txt", "r");
if (fp == NULL)
{
printf("Error: could not open file\n");
return 1;
}
printf("Current file position: %ld\n", ftell(fp));
fseek(fp, 5, SEEK_SET); // Same as fseek(fp, 5, 0);
printf("Current file position after fseek: %ld\n", ftell(fp));
fclose(fp);
}
Output:
Current file position: 0
Current file position after fseek: 5
This program opens the file example.txt for reading, gets the current file position using the ftell() function, sets the file position indicator to 5 bytes from the beginning of the file using the fseek() function with offset 5 from beginning of file, and then gets the current file position again using the ftell() function. It then prints both file positions to the console.
Command Line Arguments
Command line arguments are input parameters that are passed to a program when it is executed. In C, these arguments can be passed to the main() function as parameters.
The syntax for the main() function is as follows:
int main(int argc, char *argv[])
- Here,
argcis an integer that represents the number of command line arguments that were passed to the program. argvis an array of character strings that represent the command line arguments.
For example, if a program is executed with the command ./program arg1 arg2 arg3, then argc would be 4 and argv would be an array of 4 character strings containing ./program, arg1, arg2, and arg3.

Reading Command Line Arguments
To read command line arguments in a C program, we can use the argc and argv parameters of the main() function.
#include <stdio.h>
#include <conio.h>
void main(int argc, char *argv[])
{
printf("argv[0] = %s\n", argv[0]);
printf("argv[1] = %s\n", argv[1]);
printf("argv[2] = %s\n", argv[2]);
printf("argv[3] = %s\n", argv[3]);
getch();
}
To Run this program Open Command Prompt Locate the path of progra:
For Compile : gcc hello.c -o hello
For Run with Arguments : ./hello dog cat frog
This program reads the command line arguments passed to it and prints them to the console.
argv[0] = D:\hello.exe
argv[1] = dog
argv[2] = cat
argv[3] = frog
The Preprocessors
- Preprocessors
- Introduction
- Types of Preprocessors Directives
- Macro
- Introduction
- Format of Macro
- Simple Macro Substitution
- Argument
- Macro Substitution
- Nested Macro Substitution
- File inclusion
- Compiler control directives
The C preprocessor is a micro processor that is used by compiler to transform your code before compilation. It is called micro preprocessor because it allows us to add macros.
Proprocessor direcives are executed before compilation.

All preprocessor directives starts with hash # symbol.
| Preprocessor Directive | Description |
|---|---|
| #include | Includes a header file in the source code |
| #define | Defines a macro |
| #undef | Undefines a macro |
| #ifdef | Tests whether a macro is defined |
| #ifndef | Tests whether a macro is not defined |
| #if | Tests a compile-time condition |
| #else | The alternative for #if |
| #elif | The alternative for #if and #else |
| #endif | Ends a conditional block |
| #error | Generates a compilation error |
Types of Preprocessors Directives
- Macro Substitution Directives
- File Inclusion Directives
- Complier Control Directives
Macro Substitution
A macro is a fragment of code which has been given a name. Whenever the name is used, it is replaced by the contents of the macro. Macros are commonly used to define constants or to provide a shortcut for a sequence of instructions.
There are diiferent forms of macro Substitution:
- Simple Macro Substitution
- Argumented Macro Substitution
- Nested Macro Substitution
Simple Macro Substitution
Format of Macros
Macros are defined using the #define directive. The general syntax of a macro is as follows:
#define MACRO_NAME macro_value
Here, MACRO_NAME is the name of the macro, and macro_value is the value that the macro will be replaced with.
For example, the following code defines a macro called PI:
#define PI 3.14159
Once defined, we can use the macro PI in our code like this:
#include <stdio.h>
#define PI 3.14159
void main()
{
printf("PI : %f", PI);
}
The preprocessor will replace PI with 3.14159, so the code that is actually compiled will be:
PI : 3.141590
More Examples:
#define COUNT 100
#define FALSE 0
#define SUBJECT 6
#define CITY “Idar”
Difference between Macro and Variables
In computer programming, a macro and a variable are two essential concepts used to store and manipulate data. Although they appear similar, they are not the same. Here are the main differences between macros and variables:
Macros
A macro is a preprocessor directive that allows a programmer to define a sequence of instructions, which can be reused throughout the program. A macro is defined using the #define directive, which associates a name with a value or a sequence of values. The preprocessor replaces the name with the corresponding value or sequence of values whenever it encounters the name in the code.
Variables
A variable is a named storage location in memory that holds a value. The value of a variable can be changed during the execution of a program. A variable is defined using a data type and a name. The data type specifies the type of data that can be stored in the variable, such as integer, floating-point, or character. The name is used to refer to the variable in the code.
Differences
The main differences between macros and variables are:
- Scope: Macros are global, meaning that they can be used throughout the program, while variables can be global or local, meaning that they can only be used in a specific part of the program.
- Type Checking: Macros are not type-checked, meaning that they can be used to define any sequence of instructions, while variables are type-checked, meaning that they can only hold values of the specified data type.
- Memory Allocation: Macros do not allocate memory, meaning that they do not occupy any space in memory, while variables allocate memory, meaning that they occupy space in memory.
In conclusion, macros and variables are both essential concepts in computer programming, but they serve different purposes. Macros are used to define reusable sequences of instructions, while variables are used to store and manipulate data.
Argumented Macro Substitution
We can also define macros that take arguments. The syntax for defining an argumented macro is as follows:
#define MACRO_NAME(argument1, argument2, ...) macro_expression
Here, MACRO_NAME is the name of the macro, argument1, argument2, etc. are the arguments that the macro will take, and macro_expression is the expression that the macro will be replaced with.
For example, the following code defines an argumented macro called MAX that takes two arguments and returns the larger of the two:
#define SUM(a, b) (a + b)
Once defined, we can use the macro SUM in our code like this:
#include "stdio.h"
#define SUM(a, b) (a + b)
int main()
{
printf("Sum is %d", SUM(2, 4));
return 0;
}
The preprocessor will replace SUM with (a + b)
Sum is 6
Nested Macro Substitution
We can also use one macro in the defination of another macro. That is, macro definations may be nester.
For example:
#define NUM 5
#define NUM2 NUM * 2
#include "stdio.h"
#define NUM 5
#define NUM2 NUM * 2
int main()
{
printf("NUM2 = %d", NUM2);
return 0;
}
NUM2 = 10
Undefining Macro
We can undefine a previously defined macro using the #undef directive.
The syntax is as follows:
#undef MACRO_NAME
Here, MACRO_NAME is the name of the macro to be undefined.
For example, the following code defines a macro called NUM and then undefines it:
#include "stdio.h"
// Simple Nested Macro
#define NUM 5
int main()
{
printf("NUM = %d", NUM);
#undef NUM
printf("NUM = %d", NUM); // Error: NUM is not defined
return 0;
}
After the #undef directive, the NUM macro will no longer be defined and cannot be used in the code.
It can be redefined later if needed.
File Inclusion
The #include directive is used to include a header file or an external file in the source code. The general syntax of a #include directive is as follows:
#include <header_file_name>
Here, header_file_name is the name of the header file to be included.
The stdio.h header file contains declarations for standard input and output functions such as printf().
For example, the following code includes the stdio.h header file:
#include <stdio.h>
int main()
{
printf("Hello, world!");
return 0;
}
Hello, world!
For External File:
We can add an external file to our code using the #include statement.
Syntax:
#include "external_file_name"
For Example:
void sayHello()
{
printf("Hello, World!");
}
#include <stdio.h>
#include "hello.txt"
int main()
{
sayHello();
}
Hello, World!
Compiler Control Directives
- Conditional Compilation directives are a type of directive that helps to compile a specific portion of the program or to skip the compilation of some specific part of the program based on some conditions.
This can be done with the help of the two preprocessing commands ifdef
‘ and endif
#ifdef:
The #ifdef preprocessor directive checks if macro is defined by #define. If yes, it executes the code otherwise #else code is executed, if present.
Syntax
#ifdef macro_name
statement1;
statement2;
statement3;
.
.
.
statementN;
#endif
If the macro with the name macro_name is defined, then the block of statements will execute normally, but if it is not defined, the compiler will simply skip this block of statements.
Syntax with #else
#ifdef MACRO
//successful code
#else
//else code
#endif
For Example: If TAKE_INPUT is defined, then take input from user, else assign a value to a.
#include <stdio.h>
#include <conio.h>
#define TAKE_INPUT
void main()
{
int a = 0;
#ifdef TAKE_INPUT
printf("Enter a:");
scanf("%d", &a);
#else
a = 2;
#endif
printf("Value of a: %d\n", a);
}
Enter a:5
Value of a: 5