1. Functions
A function is a self-contained block of code that performs a specific task. Think of it like a mini-program within your main program. Using functions helps organize your code, make it reusable, and easier to debug. For example, if you need to calculate the area of a circle multiple times, you can write a calculateArea() function and call it whenever needed, instead of writing the same code again and again.
Advantages of Creating Functions
Code Reusability: Write once, use multiple times throughout the program without duplicating code.
Modularity: Break complex problems into smaller, manageable pieces that are easier to understand and debug.
Maintainability: Changes need to be made in only one place, making code updates simpler and less error-prone.
Readability: Functions with descriptive names make code self-documenting and easier to follow.
Testing: Individual functions can be tested separately, making debugging more efficient.
Memory Management: Functions help manage variable scope and can reduce memory usage through local variables.
Types of Functions
Library Functions: These are pre-defined functions in C's standard libraries, like
printf(),scanf(), andsqrt(). You just need to include the appropriate header file (e.g.,<stdio.h>,<math.h>) to use them. They are ready to use.User-Defined Functions: These are functions that you, the programmer, create to perform a specific task not available in the standard library.
Function Components
- Function Definition: The actual code block of the function. It tells the compiler what the function does.
C example:return_type function_name(parameter_list) {// body of the function// ...return value;}
Function Prototype/Declaration: This tells the compiler about the function's existence, its return type, and the types of its parameters before the function is actually defined. It's like a forward declaration. You place it at the beginning of your program, usually before
main().C example:return_type function_name(parameter_type1, parameter_type2, ...);
Function Call: This is how you execute a function. You "call" the function by its name, passing any required arguments.
C example:function_name(argument1, argument2, ...);
Passing Values to Functions
Call by Value: In this method, a copy of the argument's value is passed to the function. Any changes made to the parameter inside the function do not affect the original variable.
Layman's Example: You give your friend a photocopy of your notes. Whatever they write or change on their copy doesn't affect your original notes.
Call by Reference: In this method, the memory address (a pointer) of the argument is passed to the function. Any changes made to the value at that address inside the function directly affect the original variable.
Layman's Example: You give your friend the actual key to your house. Whatever they do inside the house with the key directly affects your house.
Recursion
A recursive function is a function that calls itself to solve a problem. It's like a loop, but instead of using for or while, the function keeps calling itself with smaller versions of the same problem until it reaches a simple case that can be solved directly.
Key Components of Recursion:
- Base Case: A condition where the function stops calling itself (like a stop sign)
- Recursive Case: The function calls itself with a modified parameter (making progress toward the base case)
Simple Analogy:
Think of recursion like Russian nesting dolls (Matryoshka). Each doll contains a smaller doll inside, and you keep opening them until you reach the smallest doll that can't be opened further (base case).
1. Countdown 🚀
Think of it like counting down for a rocket launch. You start at 5, then 4, then 3... until you reach 0 and say "Blast off!" Each time, you call the same function with a number that's one less.
2. Factorial 📊
Instead of multiplying all numbers manually, you say "5! is just 5 times whatever 4! is". Then to find 4!, you say "4! is just 4 times whatever 3! is". You keep going until you reach 1! which you know is 1.
3. Sum of Numbers ➕
To find the sum of 1 to 10, you think: "It's just 10 plus the sum of 1 to 9". To find the sum of 1 to 9, it's "9 plus the sum of 1 to 8". You keep going until you reach 0.
4. Power Calculation 🔢
To calculate 2⁴, you think: "It's just 2 times 2³". To find 2³, it's "2 times 2²". You continue until you reach 2⁰ which is 1.
5. Fibonacci Sequence 🌀
Each Fibonacci number is the sum of the two previous numbers. So to find the 5th Fibonacci number, you need to find the 4th and 3rd, and so on, until you reach the base cases (0 and 1).
C Program:
#include <stdio.h>
// EXAMPLE 1: COUNTDOWN
// This function counts down from n to 1
void countdown(int n) {
// Base case: stop when we reach 0
if (n <= 0) {
printf("Blast off! 🚀\n");
return;
}
// Print current number
printf("%d... ", n);
// Recursive case: call countdown with n-1
countdown(n - 1);
}
// EXAMPLE 2: FACTORIAL
// Calculate n! = n × (n-1) × (n-2) × ... × 1
int factorial(int n) {
// Base case: 0! = 1 and 1! = 1
if (n <= 1) {
return 1;
}
// Recursive case: n! = n × (n-1)!
return n * factorial(n - 1);
}
// EXAMPLE 3: SUM OF NUMBERS
// Calculate sum of numbers from 1 to n
int sumNumbers(int n) {
// Base case: sum of numbers up to 0 is 0
if (n <= 0) {
return 0;
}
// Recursive case: sum(n) = n + sum(n-1)
return n + sumNumbers(n - 1);
}
// EXAMPLE 4: POWER CALCULATION
// Calculate base^exponent (base raised to the power of exponent)
int power(int base, int exponent) {
// Base case: anything to the power of 0 is 1
if (exponent == 0) {
return 1;
}
// Recursive case: base^exp = base × base^(exp-1)
return base * power(base, exponent - 1);
}
// EXAMPLE 5: FIBONACCI SEQUENCE
// Generate the nth Fibonacci number
// Sequence: 0, 1, 1, 2, 3, 5, 8, 13, 21, ...
int fibonacci(int n) {
// Base cases: first two Fibonacci numbers
if (n <= 0) {
return 0;
}
if (n == 1) {
return 1;
}
// Recursive case: fib(n) = fib(n-1) + fib(n-2)
return fibonacci(n - 1) + fibonacci(n - 2);
}
// Helper function to print Fibonacci sequence
void printFibonacciSequence(int count) {
printf("First %d Fibonacci numbers: ", count);
for (int i = 0; i < count; i++) {
printf("%d ", fibonacci(i));
}
printf("\n");
}
int main() {
printf("=== RECURSIVE FUNCTION EXAMPLES ===\n\n");
// Example 1: Countdown
printf("1. COUNTDOWN FROM 5:\n");
countdown(5);
printf("\n");
// Example 2: Factorial
printf("2. FACTORIAL CALCULATION:\n");
int num = 5;
printf("Factorial of %d = %d\n", num, factorial(num));
printf("Step by step: 5! = 5 × 4 × 3 × 2 × 1 = %d\n\n", factorial(num));
// Example 3: Sum of numbers
printf("3. SUM OF NUMBERS FROM 1 TO 10:\n");
int n = 10;
printf("Sum of 1 to %d = %d\n", n, sumNumbers(n));
printf("Step by step: 1+2+3+4+5+6+7+8+9+10 = %d\n\n", sumNumbers(n));
// Example 4: Power calculation
printf("4. POWER CALCULATION:\n");
int base = 2, exp = 4;
printf("%d^%d = %d\n", base, exp, power(base, exp));
printf("Step by step: 2^4 = 2 × 2 × 2 × 2 = %d\n\n", power(base, exp));
// Example 5: Fibonacci sequence
printf("5. FIBONACCI SEQUENCE:\n");
printFibonacciSequence(10);
printf("8th Fibonacci number = %d\n\n", fibonacci(8));
// Show how recursion works step by step
printf("=== HOW RECURSION WORKS (Factorial Example) ===\n");
printf("When we call factorial(4):\n");
printf("factorial(4) = 4 × factorial(3)\n");
printf("factorial(3) = 3 × factorial(2)\n");
printf("factorial(2) = 2 × factorial(1)\n");
printf("factorial(1) = 1 (BASE CASE - STOP HERE)\n");
printf("\nNow working backwards:\n");
printf("factorial(2) = 2 × 1 = 2\n");
printf("factorial(3) = 3 × 2 = 6\n");
printf("factorial(4) = 4 × 6 = 24\n");
return 0;
}
/*
UNDERSTANDING RECURSION:
Think of recursion like this:
- You have a big problem
- You break it into a smaller version of the same problem
- You keep breaking it down until you reach the simplest case
- Then you solve your way back up
REAL-WORLD ANALOGY:
Imagine you're looking for something in a stack of boxes:
1. Open the top box
2. If it's what you want → STOP (base case)
3. If not, look in the box inside this box (recursive call)
4. Repeat until you find it or run out of boxes
KEY RULES FOR RECURSION:
1. Always have a base case (or you'll get infinite recursion!)
2. Make sure you're making progress toward the base case
3. The function must call itself
ADVANTAGES:
- Clean, elegant code for problems that have recursive nature
- Easy to understand for mathematical problems
- Natural fit for tree-like data structures
DISADVANTAGES:
- Can be slower than loops (function call overhead)
- Can cause stack overflow if recursion is too deep
- Sometimes uses more memory than iterative solutions
*/
2. Structures and Unions
Structures
A structure in C is a user-defined data type that groups variables of different data types under a single name. It's useful for representing a record, like a student's information (name, roll number, and marks).
Layman's Example: Think of a structure as a file folder. Inside this folder, you can keep different types of documents like a student's photo (image data), their name (text), and their age (a number). All these different types of data are organized and managed as one unit.
Key Concepts
Definition: Defines the blueprint of the structure. No memory is allocated at this stage.
Declaration: Creates a variable of the structure type. Memory is allocated here.
Initialization: Assigns initial values to the members of the structure variable.
Accessing Members: You use the dot operator (
.) to access the individual members of a structure variable.
Unions
A union is similar to a structure, but with one key difference: all its members share the same memory location. The size of the union is equal to the size of its largest member. You can only store a value in one member of a union at a time.
Layman's Example: Imagine a single parking space in a busy city. This parking space can be used by a motorcycle, a car, or a truck, but only one at a time. The size of the parking space is determined by the biggest vehicle it needs to accommodate (the truck). The union works in a similar way, reserving memory for the largest member, and letting other members use that same space.
Difference between Structures and Unions [Very Important]
3. Pointers
A pointer is a variable that stores the memory address of another variable. Instead of holding a data value directly, it "points" to the location in memory where the data is stored.
Layman's Example: Think of a pointer as an index in a book. The index entry doesn't contain the full text of the topic; it just has the page number where you can find the information. Similarly, a pointer holds the memory address (the "page number") where the actual data is located.
Definition: A **pointer** is a variable that stores the
memory address of another variable. Instead of storing a direct value, it
"points to" the location in memory where the actual data is stored.
Key Concepts
Declaration: To declare a pointer, you use an asterisk (
*) before the variable name.Example:
int *ptr;declares a pointerptrthat can hold the address of an integer variable.
Address-of Operator (
&): This operator gives you the memory address of a variable.Example:
&xgives the memory address of the variablex.
Indirection/Dereference Operator (
*): This operator is used to access the value at the memory address stored in the pointer. It "dereferences" the pointer.Example:
*ptrgives you the value stored at the address contained inptr.
NULL Pointer: A pointer that does not point to any memory location. You can assign
NULLto a pointer to indicate it's not pointing to a valid address.
Declaration Syntax
Basic Syntax
data_type *pointer_name;
Examples of Declaration
int *p; //
Pointer to integer
float *fp; //
Pointer to float
char *cp; //
Pointer to character
double *dp; //
Pointer to double
Multiple Pointer Declaration
int *p1, *p2, *p3;
// Three integer pointers
int *p1, p2, *p3;
// p1 and p3 are pointers, p2 is int variable
Initialization
Method 1: Using address-of operator (&)
int x = 42;
int *p = &x; //
p points to x
Method 2: Initialize to NULL
int *p = NULL; //
Safe initialization
// or
int *p = 0; //
Also NULL
Method 3: Initialize after declaration
int x = 42;
int *p;
p = &x; //
Assign address later
Accessing Pointer Values
a) Address-of Operator (&)
Gets the address of a variable:
int x = 42;
printf("Address of x: %p\n", &x); // Prints memory address
printf("Address of x: %p\n", (void*)&x); //
Better format
b) Dereference Operator (*)
Accesses the value at the address:
int x = 42;
int *p = &x;
printf("Value of x: %d\n", x); // Direct access: 42
printf("Value of x: %d\n", *p); // Indirect access: 42
printf("Address in p: %p\n", p); // Address stored in p
printf("Address of p: %p\n", &p); // Address of pointer itself
Basic Operations
Reading Values
int x = 100;
int *p = &x;
printf("x
= %d\n", x); // 100
printf("*p = %d\n", *p); // 100
printf("p = %p\n", p); // Address of x
printf("&x = %p\n", &x); // Address of x
printf("&p = %p\n", &p); // Address of p
Modifying Values
int x = 100;
int *p = &x;
*p = 200; // Changes x to 200
printf("x
= %d\n", x); // 200
x = 300; // Direct change
printf("*p = %d\n", *p); // 300
Pointer Assignment
int x = 10, y = 20;
int *p1 = &x;
int *p2 = &y;
printf("*p1
= %d, *p2 = %d\n", *p1, *p2); //
10, 20
p1 = p2; // p1 now points to
y
printf("*p1
= %d, *p2 = %d\n", *p1, *p2); //
20, 20
Practice
Questions with Solutions
Question 1: Basic Pointer Declaration and Usage
Topic Covered: Declaration, initialization,
dereferencing
Problem: Write a program that declares an integer
variable, creates a pointer to it, and displays both the value and address.
#include <stdio.h>
int main() {
// SOLUTION:
int x = 42; // Declare integer variable
int *p = &x; // Declare pointer and initialize with
address of x
printf("Value
of x: %d\n", x); //
Direct access
printf("Value
via pointer: %d\n", *p); //
Indirect access
printf("Address
of x: %p\n", &x); //
Address of x
printf("Address
in pointer: %p\n", p); // Same
address stored in p
printf("Address
of pointer: %p\n", &p); //
Address of pointer itself
return 0;
}
==================================================================
Output:
Value of x: 42
Value via pointer: 42
Address of x: 0x7fff5fbff6ac
Address in pointer: 0x7fff5fbff6ac
Address of pointer: 0x7fff5fbff6a0
==================================================================
Question 2: Pointer Modification
Topic Covered: Modifying values through pointers
Problem: Create a program that modifies a variable's
value using a pointer.
#include <stdio.h>
int main() {
// SOLUTION:
int num = 100;
int *ptr = #
printf("Original value: %d\n", num);
*ptr = 200; // Modify value through pointer
printf("After
modification via pointer: %d\n", num);
*ptr += 50; // Add 50
using pointer
printf("After
adding 50: %d\n", num);
return 0;
}
==================================================================
Output:
Original value: 100
After modification via pointer: 200
After adding 50: 250
==================================================================
Question 3: Swapping Numbers Using Pointers
Topic Covered: Pass by reference, function parameters
Problem: Write a function to swap two numbers using
pointers.
#include <stdio.h>
// SOLUTION:
void swap(int *a, int *b) {
int temp = *a;
*a = *b;
*b = temp;
}
int main() {
int x = 10, y = 20;
printf("Before
swap: x = %d, y = %d\n", x, y);
swap(&x, &y); // Pass
addresses
printf("After
swap: x = %d, y = %d\n", x, y);
return 0;
}
==================================================================
**Output:**
Before swap: x = 10, y = 20
After swap: x = 20, y = 10
==================================================================
4. Working with Files
File handling is the process of performing operations like reading from, writing to, and updating files on a storage device. It allows a program to store data permanently, even after the program has finished running.
Key Concepts
File Pointer: A special pointer, typically of type
FILE*, that is used to manage a file. When you open a file, a file pointer is created to keep track of its location and status.File Manipulation Functions:
fopen(): Opens a file and returns a file pointer. It takes the file name and the access mode (e.g., "w" for write, "r" for read, "a" for append) as arguments.fclose(): Closes an opened file. It's crucial to close a file after you're done to save changes and free up system resources.fprintf(): Writes formatted data to a file. It works likeprintf()but writes to a file instead of the console.fscanf(): Reads formatted data from a file. It works likescanf()but reads from a file instead of the keyboard.fputc()/fgetc(): Writes/reads a single character.fputs()/fgets(): Writes/reads a string.
Sequential vs. Random File Access:
Sequential Access: Data is accessed in a linear, step-by-step manner from the beginning to the end. (e.g., reading a book from page 1 to the end).
Random Access: Allows you to jump directly to any location in the file without reading the preceding data. Functions like
fseek()andftell()are used for this. (e.g., using a book's index to directly go to a specific page).
Practice Questions and Answers
Functions
Q1: Write a C program to find the factorial of a number using a user-defined function.
Answer:
#include <stdio.h>
// Function prototype
long long factorial(int n);
int main() {
int num;
printf("Enter a positive integer: ");
scanf("%d", &num);
// Call the function
printf("Factorial of %d is %lld", num, factorial(num));
return 0;
}
// Function definition
long long factorial(int n) {
if (n >= 1) {
return n * factorial(n - 1); // Recursive call
} else {
return 1; // Base case
}
}
Q2: Write a C program to swap two numbers using Call by Reference.
Answer:
#include <stdio.h>
// Function to swap numbers using pointers
void swap(int *x, int *y) {
int temp;
temp = *x; // Store the value at address x
*x = *y; // Place the value at address y into address x
*y = temp; // Place the original value of x into address y
}
int main() {
int a = 10, b = 20;
printf("Before swapping: a = %d, b = %d\n", a, b);
// Pass addresses of a and b to the function
swap(&a, &b);
printf("After swapping: a = %d, b = %d\n", a, b);
return 0;
}
Structures and Unions
Q1: Define a structure Student with members name, roll, and marks. Write a program to read and display data for one student.
Answer:
#include <stdio.h>
// Define the structure
struct Student {
char name[50];
int roll;
float marks;
};
int main() {
struct Student s1; // Declare a structure variable
printf("Enter student name: ");
scanf("%s", s1.name); // Using . to access members
printf("Enter roll number: ");
scanf("%d", &s1.roll);
printf("Enter marks: ");
scanf("%f", &s1.marks);
// Displaying the data
printf("\n--- Student Details ---\n");
printf("Name: %s\n", s1.name);
printf("Roll Number: %d\n", s1.roll);
printf("Marks: %.2f\n", s1.marks);
return 0;
}
Q2: Write a program to demonstrate the difference in memory allocation between a structure and a union.
Answer:
#include <stdio.h>
// Define a structure
struct StudentInfo {
int id;
char grade;
float salary;
};
// Define a union
union EmployeeInfo {
int id;
char grade;
float salary;
};
int main() {
struct StudentInfo s;
union EmployeeInfo u;
// The size of the structure will be the sum of its members' sizes
printf("Size of StudentInfo structure: %zu bytes\n", sizeof(s));
// The size of the union will be the size of its largest member (float = 4 bytes)
printf("Size of EmployeeInfo union: %zu bytes\n", sizeof(u));
return 0;
}
Explanation: On a 32-bit system, int is 4 bytes, char is 1 byte, and float is 4 bytes. The structure's size will be 4 + 1 + 4 = 9 bytes. However, the union's size will be just 4 bytes, as all members share the same memory location, and it's sized to fit the largest member.
Pointers
Q1: Write a program to demonstrate the use of a pointer to access a variable.
Answer:
#include <stdio.h>
int main() {
int number = 50;
int *p; // Pointer to an integer
p = &number; // Store the address of 'number' in the pointer 'p'
printf("Value of number: %d\n", number);
printf("Address of number: %p\n", (void *)&number);
printf("Value stored in pointer p: %p\n", (void *)p);
printf("Value accessed via pointer: %d\n", *p); // Dereferencing the pointer
return 0;
}
Q2: Write a C program to find the largest element in an array using pointers.
Answer:
#include <stdio.h>
int main() {
int arr[] = {10, 5, 25, 1, 8};
int n = 5;
int *max = arr; // Pointer 'max' points to the first element
// Iterate through the array using pointer arithmetic
for (int i = 1; i < n; i++) {
if (*(arr + i) > *max) { // Compare the value at the current address with the max value
max = arr + i; // Update the pointer to point to the new maximum
}
}
printf("The largest element in the array is: %d\n", *max);
return 0;
}
File Handling
Q1: Write a C program to write a string "Hello, World!" to a file named test.txt.
Answer:
#include <stdio.h>
#include <stdlib.h> // For exit()
int main() {
FILE *fptr;
char text[50] = "Hello, World!";
// Open file in write mode
fptr = fopen("test.txt", "w");
// Check if the file was opened successfully
if (fptr == NULL) {
printf("Error: Could not open file.\n");
exit(1);
}
// Write the string to the file
fprintf(fptr, "%s", text);
printf("Data written to test.txt successfully.\n");
// Close the file
fclose(fptr);
return 0;
}
Q2: Write a C program to read the contents of the test.txt file and display them on the screen.
Answer:
#include <stdio.h>
#include <stdlib.h> // For exit()
int main() {
FILE *fptr;
char ch;
// Open file in read mode
fptr = fopen("test.txt", "r");
// Check if the file was opened successfully
if (fptr == NULL) {
printf("Error: Could not open file.\n");
exit(1);
}
// Read the file character by character until the end of file (EOF)
printf("Content of the file:\n");
while ((ch = fgetc(fptr)) != EOF) {
printf("%c", ch);
}
// Close the file
fclose(fptr);
return 0;
}
Comprehensive Practice Questions
Q1: Write a program to store and display the details of N students using an array of structures. The details should include name, roll number, and marks. The program should also find and print the details of the student with the highest marks.
Q2: Write a C program using recursion to calculate the sum of digits of a given number. (For example, if the number is 123, the sum should be 1+2+3=6).
Q3: Create a program that uses pointers to reverse a given string.
Q4: Write a C program to read the contents of a text file and count the number of vowels (a, e, i, o, u, both uppercase and lowercase) present in it.
Comprehensive Answers
A1: Array of Structures and Finding Max Marks
#include <stdio.h>
struct Student {
char name[50];
int roll;
float marks;
};
int main() {
int n, i, max_index = 0;
printf("Enter the number of students: ");
scanf("%d", &n);
struct Student students[n];
// Input details for N students
for (i = 0; i < n; i++) {
printf("\nEnter details for student %d:\n", i + 1);
printf("Name: ");
scanf("%s", students[i].name);
printf("Roll Number: ");
scanf("%d", &students[i].roll);
printf("Marks: ");
scanf("%f", &students[i].marks);
}
// Find the student with the highest marks
for (i = 1; i < n; i++) {
if (students[i].marks > students[max_index].marks) {
max_index = i;
}
}
// Display details of the student with highest marks
printf("\n--- Student with Highest Marks ---\n");
printf("Name: %s\n", students[max_index].name);
printf("Roll Number: %d\n", students[max_index].roll);
printf("Marks: %.2f\n", students[max_index].marks);
return 0;
}
A2: Sum of Digits using Recursion
#include <stdio.h>
int sumOfDigits(int n) {
// Base case: if the number is 0, the sum is 0
if (n == 0) {
return 0;
}
// Recursive case: add the last digit and call the function with the remaining part
return (n % 10) + sumOfDigits(n / 10);
}
int main() {
int number;
printf("Enter a number: ");
scanf("%d", &number);
int sum = sumOfDigits(number);
printf("Sum of digits of %d is: %d\n", number, sum);
return 0;
}
A3: String Reversal using Pointers
#include <stdio.h>
#include <string.h>
void reverseString(char *str) {
int length = strlen(str);
char *start = str;
char *end = str + length - 1;
char temp;
while (start < end) {
// Swap the characters at start and end pointers
temp = *start;
*start = *end;
*end = temp;
// Move pointers towards the center
start++;
end--;
}
}
int main() {
char str[100];
printf("Enter a string: ");
scanf("%s", str);
reverseString(str);
printf("Reversed string: %s\n", str);
return 0;
}
A4: Vowel Counter using File Handling
#include <stdio.h>
#include <stdlib.h>
int main() {
FILE *fptr;
char ch;
int vowelCount = 0;
fptr = fopen("test.txt", "r");
if (fptr == NULL) {
printf("Error: Could not open file.\n");
return 1;
}
while ((ch = fgetc(fptr)) != EOF) {
if (ch == 'a' || ch == 'e' || ch == 'i' || ch == 'o' || ch == 'u' ||
ch == 'A' || ch == 'E' || ch == 'I' || ch == 'O' || ch == 'U') {
vowelCount++;
}
}
fclose(fptr);
printf("Number of vowels in the file: %d\n", vowelCount);
return 0;
}

No comments:
Post a Comment