0% found this document useful (0 votes)
14 views

File Handling and C Preprocessors

Uploaded by

khurana.nitin122
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
14 views

File Handling and C Preprocessors

Uploaded by

khurana.nitin122
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 50

Topic: Introduction to Files, Reading and Writing from Files

---

1. Introduction to Files

Definition

Files in C programming are used to store data permanently in a structured manner. Unlike
variables and arrays that lose their value once the program terminates, files ensure the
persistence of data by saving it to a storage device.

Why Use Files?

Persistence: Data can be saved for later use.

Large Data Handling: Suitable for storing large volumes of data.

Sharing: Enables data sharing between programs or users.

Organized Data Storage: Data is stored in a structured way, making it easy to manage.

File Types in C

1. Text Files

Contain readable characters (e.g., .txt, .csv).

Data is stored in human-readable format.

2. Binary Files

Contain data in binary form (e.g., .dat).

Compact and faster for reading/writing but not human-readable.


---

2. File Operations in C

C provides several standard library functions to perform operations on files. Key operations
include:

1. Opening a File: Using fopen() to create or open a file.

2. Reading from a File: Using fscanf(), fgets(), or fgetc().

3. Writing to a File: Using fprintf(), fputs(), or fputc().

4. Closing a File: Using fclose() to release file resources.

---

3. Reading from a File

Basic Steps for Reading a File

1. Declare a FILE pointer.

2. Use fopen() to open the file in read mode ("r").

3. Read the data using file I/O functions (fgetc, fgets, fscanf).

4. Close the file using fclose().

---

Example 1: Reading a File Character by Character


#include <stdio.h>

int main() {
FILE *file;
char ch;

// Open the file in read mode


file = fopen("example.txt", "r");

if (file == NULL) {
printf("File not found!\n");
return 1;
}

// Read the file character by character


while ((ch = fgetc(file)) != EOF) {
printf("%c", ch); // Print each character
}

// Close the file


fclose(file);

return 0;
}

Output Explanation:

If example.txt contains Hello World, the program prints Hello World character by character.

---

Example 2: Reading a File Line by Line

#include <stdio.h>

int main() {
FILE *file;
char line[100];

// Open the file in read mode


file = fopen("example.txt", "r");
if (file == NULL) {
printf("File not found!\n");
return 1;
}

// Read the file line by line


while (fgets(line, sizeof(line), file)) {
printf("%s", line); // Print each line
}

// Close the file


fclose(file);

return 0;
}

Output Explanation:

If example.txt contains:

Hello
World

the program prints:

Hello
World

---

Example 3: Reading Data in a Structured Format

#include <stdio.h>

int main() {
FILE *file;
char name[20];
int age;

// Open the file in read mode


file = fopen("data.txt", "r");
if (file == NULL) {
printf("File not found!\n");
return 1;
}

// Read structured data


while (fscanf(file, "%s %d", name, &age) != EOF) {
printf("Name: %s, Age: %d\n", name, age);
}

// Close the file


fclose(file);

return 0;
}

Output Explanation:

If data.txt contains:

Alice 30
Bob 25

the program prints:

Name: Alice, Age: 30


Name: Bob, Age: 25

---

4. Writing to a File

Basic Steps for Writing to a File

1. Declare a FILE pointer.

2. Use fopen() to open the file in write mode ("w" or "a").

"w": Overwrites the file.


"a": Appends data to the file.

3. Write data using file I/O functions (fputc, fputs, fprintf).

4. Close the file using fclose().

---

Example 1: Writing a File Character by Character

#include <stdio.h>

int main() {
FILE *file;
char text[] = "Hello, World!";
int i = 0;

// Open the file in write mode


file = fopen("output.txt", "w");

if (file == NULL) {
printf("Error creating file!\n");
return 1;
}

// Write the file character by character


while (text[i] != '\0') {
fputc(text[i], file);
i++;
}

printf("Data written successfully.\n");

// Close the file


fclose(file);

return 0;
}
Output Explanation:

Creates output.txt containing:

Hello, World!

---

Example 2: Writing a File Line by Line

#include <stdio.h>

int main() {
FILE *file;
char *lines[] = {"First line", "Second line", "Third line"};
int i;

// Open the file in write mode


file = fopen("output.txt", "w");

if (file == NULL) {
printf("Error creating file!\n");
return 1;
}

// Write lines to the file


for (i = 0; i < 3; i++) {
fputs(lines[i], file);
fputs("\n", file); // Add newline
}

printf("Data written successfully.\n");

// Close the file


fclose(file);

return 0;
}

Output Explanation:
Creates output.txt containing:

First line
Second line
Third line

---

Example 3: Writing Structured Data

#include <stdio.h>

int main() {
FILE *file;
char name[] = "Alice";
int age = 30;

// Open the file in write mode


file = fopen("data.txt", "w");

if (file == NULL) {
printf("Error creating file!\n");
return 1;
}

// Write structured data


fprintf(file, "%s %d\n", name, age);

printf("Data written successfully.\n");

// Close the file


fclose(file);

return 0;
}

Output Explanation:

Creates data.txt containing:

Alice 30
---

5. Summary

Reading and Writing: Core operations for file handling in C.

Functions: Master fopen, fclose, fgetc, fgets, fputc, fputs, and fprintf for effective file handling.

Error Handling: Always check if fopen() returns NULL to handle file access errors gracefully.

---

More details on functions below:-


Advanced Topics in File Handling

---

1. fgetc()

Definition and Background

fgetc() reads a single character from a file and advances the file pointer. It is particularly useful
when reading files character by character.

Syntax:

int fgetc(FILE *stream);

Returns the character read (as an int) or EOF if the end of the file or an error occurs.

Example Code 1: Reading Characters from a File

#include <stdio.h>

int main() {
FILE *file = fopen("example.txt", "r");
if (file == NULL) {
printf("File could not be opened.\n");
return 1;
}
char ch;
while ((ch = fgetc(file)) != EOF) {
printf("%c", ch);
}
fclose(file);
return 0;
}

Explanation:

fgetc(file) reads one character at a time until EOF.

The program prints the entire content of example.txt.

Output (Example):

Hello, World!

---

Example Code 2: Counting Characters in a File

#include <stdio.h>

int main() {
FILE *file = fopen("example.txt", "r");
if (file == NULL) {
printf("File could not be opened.\n");
return 1;
}
int count = 0;
while (fgetc(file) != EOF) {
count++;
}
printf("Number of characters: %d\n", count);
fclose(file);
return 0;
}

Output:
Number of characters: 13

---

2. fgets()

Definition and Background

fgets() reads a string (including spaces) from a file until a newline character (\n), the specified
maximum number of characters, or EOF.

Syntax:

char *fgets(char *str, int n, FILE *stream);

str: Pointer to the buffer to store the string.

n: Maximum number of characters to read (including the null terminator).

stream: File pointer.

Example Code 1: Reading a Line from a File

#include <stdio.h>

int main() {
FILE *file = fopen("example.txt", "r");
if (file == NULL) {
printf("File could not be opened.\n");
return 1;
}
char buffer[50];
if (fgets(buffer, 50, file) != NULL) {
printf("Line: %s\n", buffer);
}
fclose(file);
return 0;
}

Output (Example):
Line: Hello, World!

---

Example Code 2: Reading Multiple Lines

#include <stdio.h>

int main() {
FILE *file = fopen("example.txt", "r");
if (file == NULL) {
printf("File could not be opened.\n");
return 1;
}
char buffer[50];
while (fgets(buffer, 50, file) != NULL) {
printf("%s", buffer);
}
fclose(file);
return 0;
}

Explanation:

fgets(buffer, 50, file) reads each line until EOF.

Handles files with multiple lines.

Output (Example):

Hello, World!
Welcome to C programming.

---

3. fputc()

Definition and Background

fputc() writes a single character to a file.


Syntax:

int fputc(int char, FILE *stream);

Writes the character as char to the file stream.

Returns the character written, or EOF if an error occurs.

Example Code 1: Writing a Single Character

#include <stdio.h>

int main() {
FILE *file = fopen("output.txt", "w");
if (file == NULL) {
printf("File could not be opened.\n");
return 1;
}
fputc('A', file);
fclose(file);
printf("Character written to file.\n");
return 0;
}

Output (File Content):

---

Example Code 2: Writing Multiple Characters

#include <stdio.h>

int main() {
FILE *file = fopen("output.txt", "w");
if (file == NULL) {
printf("File could not be opened.\n");
return 1;
}
char str[] = "Hello";
for (int i = 0; str[i] != '\0'; i++) {
fputc(str[i], file);
}
fclose(file);
printf("String written to file.\n");
return 0;
}

Output (File Content):

Hello

---

4. fputs()

Definition and Background

fputs() writes a string to a file. Unlike fputc, it writes the entire string, excluding the null
terminator.

Syntax:

int fputs(const char *str, FILE *stream);

Example Code 1: Writing a String to a File

#include <stdio.h>

int main() {
FILE *file = fopen("output.txt", "w");
if (file == NULL) {
printf("File could not be opened.\n");
return 1;
}
fputs("Hello, World!", file);
fclose(file);
printf("String written to file.\n");
return 0;
}

Output (File Content):

Hello, World!
---

Example Code 2: Appending a String

#include <stdio.h>

int main() {
FILE *file = fopen("output.txt", "a");
if (file == NULL) {
printf("File could not be opened.\n");
return 1;
}
fputs("\nWelcome!", file);
fclose(file);
printf("String appended to file.\n");
return 0;
}

Output (File Content):

Hello, World!
Welcome!

---

5. fprintf()

Definition and Background

fprintf() is used to write formatted data to a file, similar to printf but for files.

Syntax:

int fprintf(FILE *stream, const char *format, ...);

Example Code 1: Writing Formatted Text

#include <stdio.h>

int main() {
FILE *file = fopen("output.txt", "w");
if (file == NULL) {
printf("File could not be opened.\n");
return 1;
}
fprintf(file, "Name: %s, Age: %d\n", "Alice", 25);
fclose(file);
printf("Formatted text written to file.\n");
return 0;
}

Output (File Content):

Name: Alice, Age: 25

---

Example Code 2: Logging Data

#include <stdio.h>

int main() {
FILE *file = fopen("log.txt", "w");
if (file == NULL) {
printf("File could not be opened.\n");
return 1;
}
for (int i = 1; i <= 3; i++) {
fprintf(file, "Log Entry %d: Status OK\n", i);
}
fclose(file);
printf("Log entries written to file.\n");
return 0;
}

Output (File Content):

Log Entry 1: Status OK


Log Entry 2: Status OK
Log Entry 3: Status OK

---
Error Handling in C

Definition and Background

Error handling refers to the process of detecting, managing, and recovering from errors in a
program. In C, errors can occur during program execution due to reasons like invalid input, file
not found, or division by zero. C provides several ways to handle errors, such as:

Return codes from functions.

The errno variable.

Functions like perror() and strerror() for descriptive error messages.

Key Concepts

1. errno: A global variable in <errno.h> that stores error codes.

2. perror(): Prints an error message to stderr.

3. strerror(): Returns a string describing an error code.

---

Example 1: Handling Division by Zero

#include <stdio.h>

int main() {
int a = 10, b = 0;
if (b == 0) {
printf("Error: Division by zero is not allowed.\n");
} else {
printf("Result: %d\n", a / b);
}
return 0;
}
Explanation:

Before performing division, the program checks if b is zero.

If b is zero, an error message is displayed. Otherwise, the division is performed.

Output:

Error: Division by zero is not allowed.

---

Example 2: File Error Handling with errno

#include <stdio.h>
#include <errno.h>
#include <string.h>

int main() {
FILE *file = fopen("nonexistent.txt", "r");
if (file == NULL) {
printf("Error: %s\n", strerror(errno));
} else {
fclose(file);
}
return 0;
}

Explanation:

The program attempts to open a non-existent file.

When fopen fails, errno is set, and strerror(errno) provides a descriptive error message.

Output:

Error: No such file or directory

---
Example 3: Using perror()

#include <stdio.h>

int main() {
FILE *file = fopen("nonexistent.txt", "r");
if (file == NULL) {
perror("File Error");
} else {
fclose(file);
}
return 0;
}

Explanation:

When the file cannot be opened, perror() prints a descriptive error message prefixed with "File
Error".

Output:

File Error: No such file or directory

---

Example 4: Checking for Invalid Input

#include <stdio.h>

int main() {
int num;
printf("Enter a number: ");
if (scanf("%d", &num) != 1) {
printf("Error: Invalid input. Please enter a valid number.\n");
} else {
printf("You entered: %d\n", num);
}
return 0;
}

Explanation:
scanf returns the number of inputs successfully read. If it’s not 1, an error is reported.

Output (on entering abc):

Error: Invalid input. Please enter a valid number.

---

Remove Files (remove() Function)

Definition and Background

The remove() function in C is used to delete a file from the filesystem. It is part of the <stdio.h>
library. If successful, it returns 0; otherwise, it returns a non-zero value.

Syntax:

int remove(const char *filename);

---

Example 1: Successful File Deletion

#include <stdio.h>

int main() {
if (remove("example.txt") == 0) {
printf("File deleted successfully.\n");
} else {
perror("Error deleting file");
}
return 0;
}

Explanation:

The program attempts to delete example.txt.

If successful, it prints a success message; otherwise, perror is used to display an error.


Output (if file exists):

File deleted successfully.

---

Example 2: Deleting a Non-Existent File

#include <stdio.h>

int main() {
if (remove("nonexistent.txt") != 0) {
perror("Error deleting file");
}
return 0;
}

Explanation:

Since nonexistent.txt does not exist, remove() fails, and perror() prints an error message.

Output:

Error deleting file: No such file or directory

---

Example 3: Deleting a Read-Only File

#include <stdio.h>

int main() {
if (remove("readonly.txt") == 0) {
printf("File deleted successfully.\n");
} else {
perror("Error deleting file");
}
return 0;
}

Explanation:
If the file readonly.txt is write-protected, remove() fails, and an error is printed.

Output (if file is read-only):

Error deleting file: Permission denied

---

Example 4: User Input for File Deletion

#include <stdio.h>

int main() {
char filename[100];
printf("Enter the name of the file to delete: ");
scanf("%s", filename);

if (remove(filename) == 0) {
printf("File '%s' deleted successfully.\n", filename);
} else {
perror("Error deleting file");
}
return 0;
}

Explanation:

The user is prompted to input the file name.

The program attempts to delete the file and reports success or failure.

Output (on successful deletion):

Enter the name of the file to delete: example.txt


File 'example.txt' deleted successfully.

---
Renaming Files

Definition and Background

The rename() function in C is used to change the name of a file or move it to a new location. It is
defined in <stdio.h>.

Syntax:

int rename(const char *oldname, const char *newname);

---

Example 1: Renaming a File

#include <stdio.h>

int main() {
if (rename("oldfile.txt", "newfile.txt") == 0) {
printf("File renamed successfully.\n");
} else {
perror("Error renaming file");
}
return 0;
}

Explanation:

The file oldfile.txt is renamed to newfile.txt.

If the operation fails, an error message is displayed.

Output:

File renamed successfully.

---

Example 2: Renaming a Non-Existent File

#include <stdio.h>
int main() {
if (rename("nonexistent.txt", "newfile.txt") != 0) {
perror("Error renaming file");
}
return 0;
}

Explanation:

Attempting to rename a non-existent file results in an error.

Output:

Error renaming file: No such file or directory

---

Example 3: Moving a File

#include <stdio.h>

int main() {
if (rename("example.txt", "backup/example.txt") == 0) {
printf("File moved successfully.\n");
} else {
perror("Error moving file");
}
return 0;
}

Explanation:

The file is moved to the backup directory by renaming its path.

Output:

File moved successfully.

---
Example 4: User Input for Renaming

#include <stdio.h>

int main() {
char oldname[100], newname[100];
printf("Enter the current file name: ");
scanf("%s", oldname);
printf("Enter the new file name: ");
scanf("%s", newname);

if (rename(oldname, newname) == 0) {
printf("File renamed to '%s'.\n", newname);
} else {
perror("Error renaming file");
}
return 0;
}

Explanation:

The user inputs the current and new file names.

The program attempts to rename the file and reports success or failure.

Output (on successful renaming):

Enter the current file name: oldfile.txt


Enter the new file name: renamedfile.txt
File renamed to 'renamedfile.txt'.

---
Introduction to C Preprocessors

C preprocessors are a set of directives provided by the C language to process the source code
before it is passed to the compiler. These directives begin with the # symbol and are executed
by the preprocessor, which is a part of the compilation process. The preprocessor directives
allow us to include files, define constants, perform conditional compilation, and more.

The preprocessor does not produce object code; it only prepares the source code for the
compiler by performing textual substitutions, removing comments, and handling other tasks
defined by the directives.

---

Key Preprocessor Directives in C

1. #define: Used to define constants or macros.

2. #include: Used to include files, typically header files.

---

Understanding #define Directive

The #define directive is used to define a constant or a macro. A macro is a fragment of code
that can be substituted throughout the program.

Syntax

#define identifier value

Identifier: The name of the constant or macro.

Value: The value to be associated with the identifier.

Key Points

It is a textual substitution; the compiler replaces the identifier with the value wherever it appears.
It has no type-checking.

Macros can be multi-line or parameterized.

---

Examples of #define

Example 1: Defining a Constant

#include <stdio.h>
#define PI 3.14159

int main() {
printf("The value of PI is: %f\n", PI);
return 0;
}

Explanation:

The #define PI 3.14159 creates a constant PI.

Every occurrence of PI in the code is replaced with 3.14159 before compilation.

Output:

The value of PI is: 3.141590

---

Example 2: Using a Macro for Calculations

#include <stdio.h>
#define SQUARE(x) (x * x)

int main() {
int num = 5;
printf("The square of %d is: %d\n", num, SQUARE(num));
return 0;
}

Explanation:

#define SQUARE(x) (x * x) defines a macro for squaring a number.

The macro replaces SQUARE(num) with (num * num).

Output:

The square of 5 is: 25

---

Example 3: Multi-line Macro

#include <stdio.h>
#define AREA_RECTANGLE(length, breadth) \
(length * breadth)

int main() {
int length = 10, breadth = 5;
printf("The area of the rectangle is: %d\n", AREA_RECTANGLE(length, breadth));
return 0;
}

Explanation:

The multi-line macro is used to calculate the area of a rectangle.

The backslash (\) allows the macro definition to span multiple lines.

Output:

The area of the rectangle is: 50

---

Example 4: Conditional Compilation with #define


#include <stdio.h>
#define DEBUG

int main() {
#ifdef DEBUG
printf("Debug mode is ON\n");
#else
printf("Debug mode is OFF\n");
#endif
return 0;
}

Explanation:

The #ifdef checks if DEBUG is defined.

Since DEBUG is defined, the printf statement inside the #ifdef block is executed.

Output:

Debug mode is ON

---

Understanding #include Directive

The #include directive is used to include the contents of a file (usually header files) into the
program. This helps in reusing code and maintaining modularity.

Syntax

#include <filename>
#include "filename"

<filename>: Used for standard library files.

"filename": Used for user-defined files.

Key Points

Reduces code duplication by reusing standard and custom header files.


Includes functions, macros, and constants declared in the header file.

---

Examples of #include

Example 1: Using Standard Header File

#include <stdio.h>

int main() {
printf("Hello, World!\n");
return 0;
}

Explanation:

The #include <stdio.h> includes the Standard Input/Output library.

Functions like printf are defined in this header file.

Output:

Hello, World!

---

Example 2: Including Multiple Header Files

#include <stdio.h>
#include <math.h>

int main() {
double num = 25.0;
printf("The square root of %.2f is %.2f\n", num, sqrt(num));
return 0;
}

Explanation:
#include <stdio.h> provides access to printf.

#include <math.h> provides access to mathematical functions like sqrt.

Output:

The square root of 25.00 is 5.00

---

Example 3: Using a User-defined Header File

File: myheader.h

#define MESSAGE "Welcome to C Programming!"

File: main.c

#include <stdio.h>
#include "myheader.h"

int main() {
printf("%s\n", MESSAGE);
return 0;
}

Explanation:

The #include "myheader.h" includes the user-defined header file.

The MESSAGE macro defined in myheader.h is used in the program.

Output:

Welcome to C Programming!

---

Example 4: Nested Includes


#include <stdio.h>
#include <math.h>

int main() {
printf("Logarithm of 10: %.2f\n", log10(10));
return 0;
}

Explanation:

The #include directives ensure that necessary files are included in the program.

Functions like log10 from math.h are accessible.

Output:

Logarithm of 10: 1.00

---

Summary

#define: Used to define constants and macros. Simplifies repetitive tasks and improves code
readability.

#include: Used to include standard or user-defined files, making functions and macros
accessible.

Preprocessor directives enhance the flexibility, reusability, and modularity of programs, making
them a critical component of C programming.
Conditional Compilation Directives

Conditional compilation directives are preprocessor directives in C that allow specific portions of
code to be included or excluded during the compilation process based on certain conditions.
These directives make the code flexible, platform-independent, and more manageable,
especially when working on large projects or cross-platform applications.

Introduction to Conditional Compilation Directives

Conditional compilation directives enable the programmer to control the inclusion or exclusion of
code fragments based on conditions evaluated at compile-time. These conditions are typically
related to whether a specific macro is defined or not. They are particularly useful for:

1. Debugging (e.g., adding or removing debug statements).

2. Platform-dependent code (e.g., different code for Windows and Linux).

3. Enabling or disabling features in the code.

The commonly used conditional compilation directives in C are:

1. #ifdef

2. #ifndef

3. #endif

4. #else

These directives are evaluated by the C Preprocessor, which processes them before the
compiler translates the program.

---
1. #ifdef Directive

The #ifdef directive checks if a macro is defined. If the macro is defined, the code following
#ifdef is included in the program. Otherwise, it is skipped.

Syntax

#ifdef MACRO_NAME
// Code to include if MACRO_NAME is defined
#endif

Example 1

#include <stdio.h>

#define DEBUG_MODE

int main() {
#ifdef DEBUG_MODE
printf("Debugging is enabled.\n");
#endif
printf("Program is running normally.\n");
return 0;
}

Explanation:

The macro DEBUG_MODE is defined using #define.

Since DEBUG_MODE is defined, the line inside #ifdef DEBUG_MODE is included.

Output:

Debugging is enabled.
Program is running normally.

Example 2

#include <stdio.h>

// Macro not defined here


int main() {
#ifdef FEATURE_A
printf("Feature A is enabled.\n");
#endif
printf("Program continues without Feature A.\n");
return 0;
}

Explanation:

The macro FEATURE_A is not defined.

The block inside #ifdef FEATURE_A is excluded from compilation.

Output:

Program continues without Feature A.

Example 3

#include <stdio.h>

#define ENABLE_LOGS

int main() {
#ifdef ENABLE_LOGS
printf("Logging feature is enabled.\n");
#endif
printf("Application initialized.\n");
return 0;
}

Explanation:

Since ENABLE_LOGS is defined, the logging message will appear in the output.

Output:

Logging feature is enabled.


Application initialized.

Example 4
#include <stdio.h>

#define FLAG

int main() {
#ifdef FLAG
printf("Flag is defined.\n");
#endif
printf("End of program.\n");
return 0;
}

Explanation:

The FLAG macro is defined, so the message "Flag is defined." is included.

Output:

Flag is defined.
End of program.

---

2. #ifndef Directive

The #ifndef directive checks if a macro is not defined. If the macro is not defined, the code
following #ifndef is included. Otherwise, it is skipped.

Syntax

#ifndef MACRO_NAME
// Code to include if MACRO_NAME is not defined
#endif

Example 1

#include <stdio.h>

// Macro not defined here

int main() {
#ifndef FEATURE_X
printf("Feature X is not defined.\n");
#endif
return 0;
}

Explanation:

The macro FEATURE_X is not defined.

The code inside #ifndef FEATURE_X is included.

Output:

Feature X is not defined.

Example 2

#include <stdio.h>

#define FEATURE_Y

int main() {
#ifndef FEATURE_Y
printf("Feature Y is not defined.\n");
#else
printf("Feature Y is defined.\n");
#endif
return 0;
}

Explanation:

The macro FEATURE_Y is defined.

The code block after #ifndef is skipped, and the #else block is executed.

Output:

Feature Y is defined.

Example 3
#include <stdio.h>

int main() {
#ifndef DEBUG
printf("Debug mode is not enabled.\n");
#endif
return 0;
}

Explanation:

Since DEBUG is not defined, the message "Debug mode is not enabled." is included in the
output.

Output:

Debug mode is not enabled.

Example 4

#include <stdio.h>

#define PRODUCTION

int main() {
#ifndef TEST
printf("Test environment is not active.\n");
#endif
return 0;
}

Explanation:

TEST is not defined, so the #ifndef block is included.

Output:

Test environment is not active.

---
3. #endif Directive

The #endif directive marks the end of a conditional directive block. It is always paired with #ifdef
or #ifndef.

Example

#include <stdio.h>

#define MODE

int main() {
#ifdef MODE
printf("Mode is defined.\n");
#endif
return 0;
}

Explanation:

The #endif marks the end of the #ifdef MODE block.

Output:

Mode is defined.

---

4. #else Directive

The #else directive specifies an alternate code block to be included if the condition of the #ifdef
or #ifndef directive is false.

Syntax

#ifdef MACRO_NAME
// Code if MACRO_NAME is defined
#else
// Code if MACRO_NAME is not defined
#endif
Example 1

#include <stdio.h>

#define WINDOWS

int main() {
#ifdef WINDOWS
printf("Windows environment detected.\n");
#else
printf("Non-Windows environment detected.\n");
#endif
return 0;
}

Explanation:

Since WINDOWS is defined, the first block is included.

Output:

Windows environment detected.

Example 2

#include <stdio.h>

int main() {
#ifdef UNIX
printf("UNIX system.\n");
#else
printf("Not a UNIX system.\n");
#endif
return 0;
}

Explanation:

Since UNIX is not defined, the #else block is included.

Output:

Not a UNIX system.


Example 3

#include <stdio.h>

#define USE_GUI

int main() {
#ifdef USE_GUI
printf("Graphical User Interface enabled.\n");
#else
printf("Command Line Interface enabled.\n");
#endif
return 0;
}

Explanation:

Since USE_GUI is defined, the first block is included.

Output:

Graphical User Interface enabled.

Example 4

#include <stdio.h>

int main() {
#ifdef FEATURE_A
printf("Feature A is available.\n");
#else
printf("Feature A is not available.\n");
#endif
return 0;
}

Explanation:

Since FEATURE_A is not defined, the #else block is executed.

Output:
Feature A is not available.

---

Conclusion

Conditional compilation directives such as #ifdef, #ifndef, #else, and #endif are powerful tools
that help manage code effectively. They allow programmers to write adaptable and maintainable
programs, especially when dealing with platform-dependent code or feature toggling. Always
remember to include an #endif to close your conditional blocks for clarity and error-free
compilation.
Introduction to Predefined Macro Names in C

Predefined macros in C are special macros that are defined by the compiler itself. These
macros provide information about the compilation environment, such as the current file name,
the date and time of compilation, or the current line number in the code. Unlike user-defined
macros, these macros are not required to be explicitly defined in the program. They are
automatically available to the programmer and can be very useful for debugging, logging, or
providing dynamic information during execution.

Key Predefined Macro Names in C

1. __FILE__: Represents the name of the current file as a string literal.

2. __LINE__: Represents the current line number in the source code as an integer.

3. __DATE__: Represents the date of compilation in the format "MMM DD YYYY".

4. __TIME__: Represents the time of compilation in the format "HH:MM:SS".

---

Detailed Explanation of Each Predefined Macro

1. __FILE__

Definition:
__FILE__ is a predefined macro that contains the name of the current source file. It helps in
logging and debugging by indicating in which file an error or operation occurred.

Example Codes:

1. Basic Example:

#include <stdio.h>
int main() {
printf("This code is in file: %s\n", __FILE__);
return 0;
}

Output:

This code is in file: example.c

Explanation: The __FILE__ macro outputs the name of the current file (e.g., "example.c"). This
is useful for identifying where a piece of code is executed.

2. Error Reporting:

#include <stdio.h>
void reportError() {
printf("Error occurred in file: %s\n", __FILE__);
}
int main() {
reportError();
return 0;
}

Output:

Error occurred in file: example.c

Explanation: The __FILE__ macro is used to dynamically display the file name when reporting
errors.

3. Using with File Operations:

#include <stdio.h>
int main() {
FILE *fp = fopen(__FILE__, "r");
if (fp) {
printf("Successfully opened file: %s\n", __FILE__);
fclose(fp);
}
return 0;
}

Output:
Successfully opened file: example.c

Explanation: The macro is used to open the current source file dynamically.

4. Combining with Other Macros:

#include <stdio.h>
int main() {
printf("File: %s, Line: %d\n", __FILE__, __LINE__);
return 0;
}

Output:

File: example.c, Line: 5

Explanation: The __FILE__ and __LINE__ macros are combined to give detailed information
about the file and line number.

---

2. __LINE__

Definition:
__LINE__ provides the current line number in the source code file. It is helpful for tracking
where specific operations are being executed.

Example Codes:

1. Displaying Line Number:

#include <stdio.h>
int main() {
printf("This is line number: %d\n", __LINE__);
return 0;
}

Output:

This is line number: 4


2. Debugging Line Number:

#include <stdio.h>
void debugLine() {
printf("Debugging at line: %d\n", __LINE__);
}
int main() {
debugLine();
return 0;
}

Output:

Debugging at line: 6

3. Using in Conditional Compilation:

#include <stdio.h>
int main() {
#if __LINE__ < 10
printf("Code is in the first 10 lines.\n");
#else
printf("Code is beyond line 10.\n");
#endif
return 0;
}

Output:

Code is in the first 10 lines.

4. Tracking Function Execution:

#include <stdio.h>
void function() {
printf("Function called at line: %d\n", __LINE__);
}
int main() {
printf("Main starts at line: %d\n", __LINE__);
function();
return 0;
}

Output:

Main starts at line: 7


Function called at line: 4

---

3. __DATE__

Definition:
__DATE__ contains the current compilation date in the format "MMM DD YYYY".

Example Codes:

1. Basic Compilation Date:

#include <stdio.h>
int main() {
printf("This file was compiled on: %s\n", __DATE__);
return 0;
}

Output:

This file was compiled on: Nov 27 2024

2. Displaying Date in a Log:

#include <stdio.h>
void logInfo() {
printf("Log generated on: %s\n", __DATE__);
}
int main() {
logInfo();
return 0;
}
Output:

Log generated on: Nov 27 2024

3. Combining with __TIME__:

#include <stdio.h>
int main() {
printf("Compiled on: %s at %s\n", __DATE__, __TIME__);
return 0;
}

Output:

Compiled on: Nov 27 2024 at 14:30:00

4. Displaying Build Information:

#include <stdio.h>
int main() {
printf("Build Information - Date: %s\n", __DATE__);
return 0;
}

Output:

Build Information - Date: Nov 27 2024

---

4. __TIME__

Definition:
__TIME__ contains the current compilation time in the format "HH:MM:SS".

Example Codes:

1. Displaying Compilation Time:


#include <stdio.h>
int main() {
printf("Compilation time: %s\n", __TIME__);
return 0;
}

Output:

Compilation time: 14:30:00

2. Logging Events with Time:

#include <stdio.h>
void logEvent() {
printf("Event logged at: %s\n", __TIME__);
}
int main() {
logEvent();
return 0;
}

Output:

Event logged at: 14:30:00

3. Using __TIME__ with Loops:

#include <stdio.h>
int main() {
printf("Program compiled at: %s\n", __TIME__);
for (int i = 0; i < 3; i++) {
printf("Iteration %d at compile time.\n", i);
}
return 0;
}

Output:

Program compiled at: 14:30:00


Iteration 0 at compile time.
Iteration 1 at compile time.
Iteration 2 at compile time.
4. Debugging with Time:

#include <stdio.h>
int main() {
printf("Debug started at: %s\n", __TIME__);
return 0;
}

Output:

Debug started at: 14:30:00

---

Summary

Predefined macros like __FILE__, __LINE__, __DATE__, and __TIME__ provide dynamic
information about the compilation environment.

These macros are valuable for debugging, logging, and tracking program execution.

They help make the code more flexible and provide metadata about the program.

By understanding and applying these macros effectively, programmers can improve the
maintainability and debuggability of their C programs.

You might also like