Mastering C Programming Concepts: Data Structures, Control Flow, and File I/O
Two-Dimensional Arrays and Matrix Addition in C
A two-dimensional array (2D array) is a type of array that stores data in a matrix format, consisting of rows and columns. It can be visualized as an array of arrays. Each element in a 2D array is accessed by two indices: the row index and the column index.
Declaration of a Two-Dimensional Array
In C language, a 2D array is declared using the following syntax:
data_type array_name[rows][columns];Example: To declare a 2×2 integer matrix:
int matrix[2][2];This declaration creates a matrix structure like:
| a[0][0] a[0][1] |
| a[1][0] a[1][1] |C Program to Add Two Square Matrices
This program demonstrates the addition of two 2×2 square matrices.
#include <stdio.h>
int main() {
int i, j;
int size = 2; // Defines the size of the square matrix
// Matrix A initialization
int A[2][2] = {
{1, 2},
{3, 4}
};
// Matrix B initialization
int B[2][2] = {
{5, 6},
{7, 8}
};
int sum[2][2];
// Adding two matrices element by element
for(i = 0; i < size; i++) {
for(j = 0; j < size; j++) {
sum[i][j] = A[i][j] + B[i][j];
}
}
// Displaying the result
printf("Sum of the matrices:\n");
for(i = 0; i < size; i++) {
for(j = 0; j < size; j++) {
printf("%d ", sum[i][j]);
}
printf("\n");
}
return 0;
}Understanding Functions and Array Sorting in C
A function is a block of code that performs a specific, well-defined task and can be called multiple times in a program. Functions help in breaking down a program into smaller, manageable parts, improving readability and promoting code reusability.
Components of a User-Defined Function
- Function Definition: The actual implementation of the function, which includes the function name, return type, parameters, and the body (the code block).
- Function Declaration (Prototype): Tells the compiler about the function name, return type, and parameters before the function is used or defined later in the code.
- Function Call: Invoking or using the function in the main program or another function.
Example Syntax:
return_type function_name(parameter list); // Declaration
return_type function_name(parameter list) { // Definition
// function body code
}C Program to Sort an Array Using a Function
This program sorts an array in ascending order by passing the array as an argument to a separate function (using the Bubble Sort algorithm).
#include <stdio.h>
// Function declaration
void sortArray(int arr[], int size);
int main() {
int arr[100], n, i;
printf("Enter number of elements: ");
scanf("%d", &n);
printf("Enter %d elements:\n", n);
for(i = 0; i < n; i++) {
scanf("%d", &arr[i]);
}
sortArray(arr, n); // Function call
printf("Sorted array: ");
for(i = 0; i < n; i++) {
printf("%d ", arr[i]);
}
return 0;
}
// Function definition to sort array in ascending order
void sortArray(int arr[], int size) {
int i, j, temp;
// Bubble Sort implementation
for(i = 0; i < size - 1; i++) {
for(j = i + 1; j < size; j++) {
if(arr[i] > arr[j]) {
temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
}
}
}Variables, Keywords, Identifiers, and Fibonacci Series
Variable and Keyword Definitions
- Variable: A variable in C is a named storage location used to hold data. The value stored in a variable can be modified during program execution. It must be declared with a specific data type before use. Example:
int age; - Keyword: A keyword is a reserved word in C that has a special, predefined meaning to the compiler. Keywords cannot be used as variable names or identifiers. Examples:
int,return,if,while.
Rules for Valid Identifiers in C
Identifiers are names given to variables, functions, arrays, etc.
- An identifier can include letters (A–Z, a–z), digits (0–9), and underscores (_).
- It must begin with a letter or an underscore (it cannot start with a digit).
- Keywords cannot be used as identifiers.
- Identifiers are case-sensitive (e.g.,
Ageandageare treated as different identifiers). - No special characters are allowed (such as
@,#,!,%, etc.).
C Program to Display the First 40 Fibonacci Numbers Using Recursion
#include <stdio.h>
// Recursive function to return the Fibonacci number at position n
int fibonacci(int n) {
if (n == 0)
return 0;
else if (n == 1)
return 1;
else
return fibonacci(n - 1) + fibonacci(n - 2);
}
int main() {
int i;
printf("First 40 Fibonacci numbers:\n");
for (i = 0; i < 40; i++) {
printf("%d ", fibonacci(i));
}
printf("\n");
return 0;
}C File Handling: Modes and Creating File Copies
File Opening Modes in C
In C, files are opened using the fopen() function along with a mode string. The common modes are:
| Mode | Description |
|---|---|
"r" | Open for reading. The file must exist. |
"w" | Open for writing. Creates a new file or truncates an existing file to zero length. |
"a" | Open for appending. Writes data to the end of the file. |
"r+" | Open for reading and writing. The file must exist. |
"w+" | Open for reading and writing. Truncates the file to zero length or creates the file if it doesn’t exist. |
"a+" | Open for reading and appending. Data is written to the end of the file. The file is created if it doesn’t exist. |
Note: Add "b" (e.g., "rb") to the mode string for binary mode, which is important when handling non-text files, especially in Windows environments.
C Program to Create an Exact Copy of an Original File
#include <stdio.h>
#include <stdlib.h>
int main() {
FILE *original, *duplicate;
char ch;
// Open the original file in read mode
original = fopen("original.txt", "r");
if (original == NULL) {
printf("Error opening original file\n");
return 1;
}
// Open the duplicate file in write mode
duplicate = fopen("duplicate.txt", "w");
if (duplicate == NULL) {
printf("Error opening duplicate file\n");
fclose(original);
return 1;
}
// Read character by character from original and write to duplicate until EOF
while ((ch = fgetc(original)) != EOF) {
fputc(ch, duplicate);
}
// Close both files
fclose(original);
fclose(duplicate);
printf("File duplicated successfully\n");
return 0;
}C Structures and Unions: Adding Time Values
What is a Union?
A union in C is a special data type that allows storing different data types in the same memory location. Unlike structures, where each member has its own memory location, all members of a union share the same memory space. Consequently, only one member of the union can hold a valid value at any given time.
C Program to Add Two Time Values Using Structure (mm:ss)
#include <stdio.h>
// Define a structure to hold time values
struct Time {
int minutes;
int seconds;
};
// Function to add two time structures
struct Time addTime(struct Time t1, struct Time t2) {
struct Time result;
// Add seconds
result.seconds = t1.seconds + t2.seconds;
// Calculate carry-over minutes and add initial minutes
result.minutes = t1.minutes + t2.minutes + result.seconds / 60;
// Normalize seconds (seconds < 60)
result.seconds = result.seconds % 60;
return result;
}
int main() {
struct Time time1, time2, total;
// Sample input 1 (2 minutes, 50 seconds)
time1.minutes = 2;
time1.seconds = 50;
// Sample input 2 (3 minutes, 30 seconds)
time2.minutes = 3;
time2.seconds = 30;
total = addTime(time1, time2);
// Display result in mm:ss format (using %02d for leading zeros)
printf("Total Time = %02d:%02d\n", total.minutes, total.seconds);
return 0;
}
/* Output:
Total Time = 06:20
*/Control Flow: Break Statement vs. Continue Statement
Both break and continue are control flow statements used within loops, but they serve fundamentally different purposes:
| Feature | Break Statement | Continue Statement |
|---|---|---|
| Purpose | Halts the entire execution flow of the loop or switch block immediately. | Skips the remaining code in the current iteration and proceeds to the next iteration of the loop. |
| Scope | Exits the loop entirely. | Only interrupts the current iteration’s flow. |
| Usage | Can be used in switch, for, while, and do-while statements. | Primarily used in for, while, and do-while loops (not used in switch). |
| Syntax | break; | continue; |
| Example | for(int i = 0; i < 10; i++) { if(i == 5) break; } (Loop stops at i=5) | for(int i = 0; i < 10; i++) { if(i == 5) continue; } (i=5 is skipped, loop continues to i=6) |
Nested Loops and Finding Prime Numbers (1 to 100)
A nested loop is a loop placed inside the body of another loop. The inner loop executes completely for every single execution of the outer loop. Nested loops are commonly used for working with multi-dimensional data structures (like 2D arrays) or for tasks requiring repeated checks, such as finding prime numbers.
Program to Print Prime Numbers Between 1 and 100 (Python Example)
Note: The following example is provided in Python, demonstrating the logic for finding prime numbers within a range.
def is_prime(num):
if num <= 1:
return False
# Check divisibility up to the square root of num
for i in range(2, int(num**0.5) + 1):
if num % i == 0:
return False
return True
def print_primes(start, end):
print("Prime numbers between %d and %d:" % (start, end))
for num in range(start, end + 1):
if is_prime(num):
print(num, end=" ")
# Print prime numbers between 1 and 100
print_primes(1, 100)Dynamic Memory Allocation (DMA) in C
DMA, or Dynamic Memory Allocation, refers to the process of allocating memory manually during program execution (runtime). This allows programs to manage memory efficiently, especially when the required size of a data structure is not known at compile time. Functions like malloc(), calloc(), realloc(), and free() are used for DMA in C.
C Program to Read N Numbers Using DMA and Display Only Odd Numbers
This program uses calloc() to dynamically allocate memory for N integers, reads the input, and then displays only the odd numbers.
#include <stdio.h>
#include <stdlib.h>
int main() {
int n;
int *data; // Pointer to hold the base address of the allocated memory
printf("Enter the total number of elements: ");
scanf("%d", &n);
// Allocating memory for n integers using calloc
data = (int *)calloc(n, sizeof(int));
if (data == NULL) {
printf("Error!!! Memory not allocated.\n");
exit(0);
}
// Storing numbers entered by the user.
for (int i = 0; i < n; ++i) {
printf("Enter number %d: ", i + 1);
scanf("%d", data + i);
}
// Displaying only odd numbers
printf("\nOdd numbers entered:\n");
for (int i = 0; i < n; ++i) {
if (*(data + i) % 2 != 0) {
printf("%d ", *(data + i));
}
}
printf("\n");
// Freeing the dynamically allocated memory
free(data);
return 0;
}Differentiating While and Do-While Loops in C
Both while and do-while loops are used for iteration, but they differ primarily in when the loop condition is checked.
| Feature | While Loop (Entry-Controlled) | Do-While Loop (Exit-Controlled) |
|---|---|---|
| Condition Check | The condition is tested before the loop body is executed (entry control). | The condition is tested after the loop body is executed (exit control). |
| Execution Guarantee | The loop body may or may not execute at all (zero or more times). | The loop body is guaranteed to execute at least once, even if the condition is initially false. |
| Syntax Requirement | No semicolon is needed after the condition. | A semicolon is required after the while(expression) statement. |
| Syntax Example | | |
Understanding Loop Iteration for Odd Numbers
The term “odd loop” is not a standard programming construct but typically refers to a loop designed to iterate over or process only odd numbers within a given range, often by checking the modulus operator (%).
Simple Program Illustrating Odd/Even Check
This program reads a single integer and determines if it is odd or even.
#include<stdio.h>
int main()
{
int num;
printf("Enter an integer: ");
scanf("%d",&num);
if(num % 2 == 0)
printf("Even\n");
else
printf("Odd\n");
return 0;
}Short Notes on C/C++ Fundamentals
h3>Preprocessor
The C Preprocessor (CPP) is not technically part of the compiler but is a separate step that occurs before the actual compilation process. It acts as a text substitution tool, instructing the compiler to perform required pre-processing tasks. Preprocessing is the first step in compiling C code. Key functions include:
- Including header files (e.g.,
#include <stdio.h>). - Defining constants (e.g.,
#define PI 3.14). - Expanding macros.
Preprocessor statements are called directives and always begin with the hash (#) symbol.
h3>Switch Statement
The switch statement is a multi-way branch control statement that provides an efficient alternative to a long series of if-else if statements. It allows a variable to be compared against different constant integral values (cases). When a match is found, the corresponding block of code is executed. The break statement is typically used within a switch block to exit after a case is executed. Nesting of switch statements is permitted.
Arrays vs. Pointers: Differences and Similarities
What is a Pointer?
A pointer is a variable that stores the memory address of another variable. Pointers are essential for dynamic memory allocation, passing large data structures efficiently, and implementing complex data structures.
Comparison of Arrays and Pointers
| Feature | Array | Pointer |
|---|---|---|
| Definition | A collection of objects of the same data type stored in contiguous memory locations. | A variable that holds the memory address of another variable. |
| Memory Allocation | Static in nature; size is fixed at compile time. | Dynamic in nature; memory can be allocated or freed at runtime (using DMA functions). |
| Initialization | Can be initialized during definition (e.g., int arr[5] = {1, 2, 3};). | Cannot be initialized at definition; must be assigned an address later. |
| Arithmetic | The array name itself is a constant pointer and cannot be incremented (arr++ is invalid). | Can be incremented or decremented to move to the next or previous memory location (ptr++ is valid). |
| Memory Management | Memory is automatically allocated and released when the variable goes out of scope. | Requires manual deallocation (using free()) to prevent memory leaks. |
| Memory Layout | Memory allocation is sequential and contiguous. | Memory allocation can be random (depending on the heap state). |
