0% found this document useful (0 votes)
5 views21 pages

unit7 Functions

Unit-7 covers functions in C programming, emphasizing their importance in modularity, reusability, and maintainability. It details the components of functions, types including library and user-defined functions, variable scope, recursion, and methods for passing data to functions. Additionally, it discusses advantages and disadvantages of library functions, recursion, and the two main data passing techniques: pass by value and pass by reference.
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
Download as pdf or txt
0% found this document useful (0 votes)
5 views21 pages

unit7 Functions

Unit-7 covers functions in C programming, emphasizing their importance in modularity, reusability, and maintainability. It details the components of functions, types including library and user-defined functions, variable scope, recursion, and methods for passing data to functions. Additionally, it discusses advantages and disadvantages of library functions, recursion, and the two main data passing techniques: pass by value and pass by reference.
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
Download as pdf or txt
Download as pdf or txt
You are on page 1/ 21

Unit-7: Functions in C

Functions are a fundamental concept in C programming, enabling modular programming by dividing


the program into smaller, reusable blocks of code. Functions make programs more organized, easier to
understand, and maintainable while promoting code reuse.

1. Basics of Functions
A function is a block of code designed to perform a specific task. Functions can be called multiple
times within a program to reduce redundancy and improve efficiency.

Why Use Functions?


• Modularity: Breaks the program into smaller, manageable parts.
• Reusability: Allows the same function to be used in multiple places.
• Maintainability: Simplifies debugging and updates.
• Scalability: Handles large and complex programs efficiently.

Components of a Function
1. Declaration (Prototype):
• Specifies the function name, return type, and parameters.
• Example: int add(int a, int b);
2. Definition:
• Contains the logic of the function.
• Example:

int add(int a, int b) {


return a + b;
}

3. Call:
• Executes the function by passing arguments.
• Example: int result = add(5, 3);

2. Types of Functions
Functions in C are classified as:

2.1 Library Functions


Library functions in C are pre-defined functions provided by the C standard libraries. These
functions simplify programming by allowing developers to use pre-written and optimized
routines for common tasks like input/output, mathematical operations, string manipulation, and
memory management.

Why Use Library Functions?


1. Time-Saving: Avoid rewriting commonly used functions.
2. Reliability: Pre-tested and optimized functions ensure fewer errors.
3. Efficiency: Highly efficient implementations written by experts.
4. Standardization: Ensures compatibility across compilers and systems.

Categories of Library Functions


Library functions in C are grouped into several categories based on their usage. These functions are
declared in specific header files.

1. Input/Output Functions
These functions handle standard input and output operations and are declared in <stdio.h>.

Common Functions:
Function Description Example
printf() Prints formatted data to the console. printf("Hello, World!");
scanf() Reads formatted input from the user. scanf("%d", &num);
gets() Reads a string from the user. gets(str);
puts() Writes a string to the console. puts("Hello!");
Example Code:
#include <stdio.h>

int main() {
int num;
printf("Enter a number: ");
scanf("%d", &num);
printf("You entered: %d\n", num);
return 0;
}

2. Mathematical Functions
Mathematical functions are declared in <math.h> and provide operations like square roots, powers,
trigonometric calculations, and more.
Common Functions:
Function Description Example
sqrt() Calculates the square root. sqrt(25.0) → 5.0
pow() Calculates the power. pow(2.0, 3.0) → 8.0
sin() Calculates the sine of an angle. sin(1.57)
abs() Returns the absolute value. abs(-5) → 5
Example Code:
#include <stdio.h>
#include <math.h>

int main() {
double num = 16.0;
printf("Square root of %.2f is %.2f\n", num, sqrt(num));
printf("2 raised to the power 3 is %.2f\n", pow(2, 3));
return 0;
}

3. String Functions
String handling functions are declared in <string.h> and are used for operations like copying,
concatenation, length calculation, and comparison.

Common Functions:
Function Description Example
strlen() Returns the length of a string. strlen("Hello") → 5
strcpy() Copies one string to another. strcpy(dest, src);
strcat() Concatenates two strings. strcat(str1, str2);
strcmp() Compares two strings. strcmp("abc", "def") → < 0
Example Code:
#include <stdio.h>
#include <string.h>

int main() {
char str1[20] = "Hello";
char str2[20] = "World";
char result[40];

printf("Length of str1: %ld\n", strlen(str1));


strcpy(result, str1);
strcat(result, str2);
printf("Concatenated string: %s\n", result);
return 0;
}
4. Memory Management Functions
Memory management functions are declared in <stdlib.h> and allow dynamic allocation and
deallocation of memory.

Common Functions:
Function Description Example
ptr = malloc(10 *
malloc() Allocates memory dynamically. sizeof(int));
calloc() Allocates memory and initializes it to ptr = calloc(10, sizeof(int));
zero.
free() Frees allocated memory. free(ptr);
realloc() Reallocates memory to a new size. ptr = realloc(ptr, new_size);
Example Code:
#include <stdio.h>
#include <stdlib.h>

int main() {
int *arr, size = 5;
arr = (int *)malloc(size * sizeof(int));
for (int i = 0; i < size; i++) {
arr[i] = i + 1;
}
for (int i = 0; i < size; i++) {
printf("%d ", arr[i]);
}
free(arr);
return 0;
}

5. Utility Functions
Utility functions, declared in <stdlib.h>, perform tasks like conversions, random number
generation, and sorting.

Common Functions:
Function Description Example
atoi() Converts string to integer. atoi("123") → 123
atof() Converts string to float. atof("12.34") → 12.34
rand() Generates a random number. rand() % 10 → Random 0-9
qsort() Sorts an array. qsort(arr, n, sizeof(int), cmp)
Example Code:
#include <stdio.h>
#include <stdlib.h>

int main() {
printf("Random number: %d\n", rand() % 100);
return 0;
}

Advantages of Library Functions


1. Time-Efficient: Pre-written and optimized.
2. Error-Free: Thoroughly tested and reliable.
3. Cross-Platform Compatibility: Standardized across different compilers and platforms.
4. Ease of Use: Simple syntax and direct functionality.

Disadvantages of Library Functions


1. Limited Customization: Cannot modify the internal logic of library functions.
2. Dependency on Libraries: Requires the appropriate header file to be included.
3. Less Flexibility: May not cover all specific use cases.

2.2 User-Defined Functions


• Created by programmers for specific tasks.
Example:
#include <stdio.h>

int multiply(int x, int y) { // Function definition


return x * y;
}

int main() {
int a = 5, b = 10;
printf("Product: %d\n", multiply(a, b)); // Function call
return 0;
}

3. Variable Scope in Functions


3.1 Local Variables
• Declared inside a function.
• Accessible only within that function.

3.2 Global Variables


• Declared outside all functions.
• Accessible throughout the program.
3.3 Static Variables
• Retain their value between function calls.
Example:

#include <stdio.h>

void countCalls() {
static int count = 0; // Static variable
count++;
printf("Function called %d times\n", count);
}

int main() {
countCalls();
countCalls();
return 0;
}

Output:
Function called 1 times
Function called 2 times

4. Recursion
Recursion is a technique in programming where a function calls itself directly or indirectly to solve a
problem. Recursion simplifies solving problems that can be broken down into smaller, similar sub-
problems. It is a key concept in programming and is widely used for implementing algorithms like
factorial computation, Fibonacci series, and more.

How Recursion Works


1. Base Case:
• A condition in the function where recursion stops. Without this, the recursion would
continue indefinitely, causing a stack overflow.
2. Recursive Case:
• The part of the function that reduces the problem into smaller instances and calls the
function itself.

Structure of a Recursive Function


return_type function_name(parameters) {
if (base_condition) {
return result; // Base case
} else {
return recursive_call; // Recursive case
}
}

Example 1: Factorial Using Recursion


The factorial of a number n is defined as:
n!=n×(n−1)×(n−2)×…×1
With the base case: 0!=1.
Code Example:
#include <stdio.h>

int factorial(int n) {
if (n == 0) { // Base case
return 1;
} else {
return n * factorial(n - 1); // Recursive case
}
}

int main() {
int num = 5;
printf("Factorial of %d is %d\n", num, factorial(num));
return 0;
}

Output:
Factorial of 5 is 120

Explanation:
1. For factorial(5), the function calls itself as:
• 5×factorial(4)
• 4×factorial(3)
• 3×factorial(2)
• 2×factorial(1)
• 1×factorial(0)
2. The recursion stops when the base case (n == 0) is met, returning 1.
3. The results are multiplied step by step as the function returns to its previous calls.

Types of Recursion
1. Direct Recursion
• A function calls itself directly. Example:
void directRecursion() {
printf("Direct Recursion\n");
directRecursion(); // Calls itself
}

2. Indirect Recursion
• A function calls another function, which in turn calls the original function. Example:
void functionA();
void functionB();

void functionA() {
printf("Function A\n");
functionB(); // Calls functionB
}

void functionB() {
printf("Function B\n");
functionA(); // Calls functionA
}

Advantages of Recursion
1. Simplifies the code for problems that can be divided into sub-problems.
2. Reduces the need for complex loops in certain algorithms (e.g., tree traversal, backtracking).

Disadvantages of Recursion
1. May lead to stack overflow if the base case is not defined or the recursion depth is too large.
2. Can be less efficient than iterative solutions due to repeated function calls and memory
overhead.

Applications of Recursion
1. Mathematical Computations:
• Factorial, Fibonacci series, GCD, etc.
2. Data Structures:
• Traversing trees and graphs (e.g., depth-first search).
3. Problem Solving:
• Solving puzzles like the Tower of Hanoi.
4. Divide and Conquer Algorithms:
• QuickSort, MergeSort.
Example 2: Fibonacci Series Using Recursion
The Fibonacci series is defined as:
F(n)=F(n−1)+F(n−2)
With base cases:
F(0)=0,F(1)=1
Code Example:
#include <stdio.h>

int fibonacci(int n) {
if (n == 0) {
return 0; // Base case
} else if (n == 1) {
return 1; // Base case
} else {
return fibonacci(n - 1) + fibonacci(n - 2); // Recursive case
}
}

int main() {
int n = 10;
printf("Fibonacci series up to %d terms:\n", n);
for (int i = 0; i < n; i++) {
printf("%d ", fibonacci(i));
}
return 0;
}

Output:
Fibonacci series up to 10 terms:
0 1 1 2 3 5 8 13 21 34

Example 3: Tower of Hanoi


The Tower of Hanoi is a puzzle where you have to move n disks from one rod to another using an
auxiliary rod, following these rules:
1. Only one disk can be moved at a time.
2. A larger disk cannot be placed on top of a smaller disk.
3. All disks must be moved from peg A to peg C using peg B as an auxiliary peg.
Code Example:
#include <stdio.h>

void towerOfHanoi(int n, char source, char target, char auxiliary) {


if (n == 1) {
printf("Move disk 1 from %c to %c\n", source, target);
return;
}
towerOfHanoi(n - 1, source, auxiliary, target);
printf("Move disk %d from %c to %c\n", n, source, target);
towerOfHanoi(n - 1, auxiliary, target, source);
}

int main() {
int n = 3; // Number of disks
printf("Steps to solve Tower of Hanoi with %d disks:\n", n);
towerOfHanoi(n, 'A', 'C', 'B');
return 0;
}

Output:
Steps to solve Tower of Hanoi with 3 disks:
Move disk 1 from A to C
Move disk 2 from A to B
Move disk 1 from C to B
Move disk 3 from A to C
Move disk 1 from B to A
Move disk 2 from B to C
Move disk 1 from A to C

Key Differences: Recursion vs Iteration


Aspect Recursion Iteration
Definition Function calls itself. Repeats code using loops (for, while).
Base Case Essential to prevent infinite recursion. No base case required.
Memory Usage Uses more memory (stack for each call). More memory-efficient.
Code Simplicity Simplifies problems like tree traversal. Simpler for repetitive tasks.
Performance Slower due to function call overhead. Faster due to fewer operations.
Best Practices for Recursion
1. Always define a clear base case to prevent infinite recursion.
2. Avoid recursion for problems that can be solved iteratively to save memory.
3. Use tail recursion (a form of recursion where the recursive call is the last operation) when
possible, as it can be optimized by compilers.

Practice Questions
1. Write a recursive function to find the GCD of two numbers.
2. Implement a recursive function to calculate the power of a number.
3. Create a recursive function to reverse a string.
4. Write a program to traverse a binary tree using recursion.
5. Solve the Tower of Hanoi puzzle for 4 disks.

5. Passing Data to Functions


In C programming, passing arguments to functions is an essential concept. The two main ways to
pass data to functions are pass by value and pass by reference. These methods determine whether the
function works on a copy of the argument or directly modifies the original data.

1. Pass by Value
Definition
• In pass by value, a copy of the actual argument is passed to the function.
• The function works with the copy, and any changes made to the parameter inside the function
do not affect the original argument.

Key Characteristics
1. Changes to the parameter do not impact the original variable.
2. Safer method since the original data remains unmodified.
3. Slightly slower for large data as it requires copying the value.

Syntax and Example


#include <stdio.h>

void modifyValue(int x) {
x = 20; // Modifying the local copy
}

int main() {
int num = 10;
modifyValue(num); // Passing by value
printf("Value of num after function call: %d\n", num); // Original value
remains unchanged
return 0;
}

Output:
Value of num after function call: 10

Advantages of Pass by Value


1. Original data is protected from unintended changes.
2. No risk of side effects on the caller's variables.

Disadvantages of Pass by Value


1. Inefficient for large data structures (e.g., large arrays).
2. Changes inside the function are not reflected in the original data.

2. Pass by Reference
Definition
• In pass by reference, the memory address of the actual argument is passed to the function.
• The function works directly on the original data, and any changes made to the parameter affect
the original argument.

Key Characteristics
1. Changes to the parameter directly impact the original variable.
2. More efficient for large data structures as no copying is required.
3. Potentially riskier because the original data can be unintentionally altered.

Syntax and Example


#include <stdio.h>

void modifyValue(int *x) {


*x = 20; // Modifying the actual variable
}
int main() {
int num = 10;
modifyValue(&num); // Passing by reference
printf("Value of num after function call: %d\n", num); // Original value is
changed
return 0;
}

Output:
Value of num after function call: 20

Advantages of Pass by Reference


1. Efficient for large data as no copying is required.
2. Allows the function to modify the original data.
3. Useful for returning multiple values from a function.

Disadvantages of Pass by Reference


1. Original data can be unintentionally modified, leading to side effects.
2. More complex syntax (requires pointers).

Comparison of Pass by Value and Pass by Reference


Aspect Pass by Value Pass by Reference
A copy of the data is passed to the
Data Handling The memory address of the data is passed.
function.
Effect on
Original data remains unchanged. Original data can be modified.
Original
Efficiency Slower for large data due to copying. Faster as no copying is involved.
Syntax
Simpler syntax (no pointers). Requires pointers for implementation.
Simplicity
Protects the original data from Risk of unintended changes to the original
Safety
modifications. data.

When to Use Pass by Value


1. When the function does not need to modify the original data.
2. For small, simple data types (e.g., integers, floats).

When to Use Pass by Reference


1. When the function needs to modify the original data.
2. For large data structures (e.g., arrays, structs) to improve performance.
3. When multiple values need to be returned from a function.

Example: Pass by Value vs Pass by Reference


Code Example:
#include <stdio.h>

// Pass by Value
void passByValue(int x) {
x = 20;
printf("Inside passByValue: %d\n", x);
}

// Pass by Reference
void passByReference(int *x) {
*x = 20;
printf("Inside passByReference: %d\n", *x);
}

int main() {
int num = 10;

// Pass by Value
printf("Before passByValue: %d\n", num);
passByValue(num);
printf("After passByValue: %d\n\n", num);

// Pass by Reference
printf("Before passByReference: %d\n", num);
passByReference(&num);
printf("After passByReference: %d\n", num);

return 0;
}

Output:
Before passByValue: 10
Inside passByValue: 20
After passByValue: 10

Before passByReference: 10
Inside passByReference: 20
After passByReference: 20

Conclusion
• Pass by Value is safer and more straightforward but involves copying data, making it less
efficient for large datasets.
• Pass by Reference allows functions to directly modify original data and is more efficient for
large datasets but comes with risks of unintended side effects.

6. Using Arrays in Functions


Arrays can be passed to functions as arguments. Only the base address of the array is passed.
Example: Calculating the Sum of Array Elements
#include <stdio.h>

int calculateSum(int arr[], int size) {


int sum = 0;
for (int i = 0; i < size; i++) {
sum += arr[i];
}
return sum;
}

int main() {
int numbers[] = {1, 2, 3, 4, 5};
int size = sizeof(numbers) / sizeof(numbers[0]);
printf("Sum: %d\n", calculateSum(numbers, size));
return 0;
}

Output:
Sum: 15

7. Static and Register Variables


7.1 Static Variables
• Retain their value between function calls.
Example:
#include <stdio.h>

void increment() {
static int count = 0; // Static variable
count++;
printf("Count: %d\n", count);
}

int main() {
increment();
increment();
return 0;
}

Output:
Count: 1
Count: 2

7.2 Register Variables


• Stored in CPU registers for faster access.
• Typically used for frequently accessed variables.
Example:
#include <stdio.h>

int main() {
register int i; // Register variable
for (i = 0; i < 5; i++) {
printf("%d ", i);
}
return 0;
}

Output:
0 1 2 3 4

Conclusion
Functions in C provide modularity and reusability, making programs more organized and maintainable.
From built-in library functions to custom user-defined ones, mastering their usage is essential.
Understanding recursion, variable scope, and the nuances of passing data ensures writing efficient and
robust programs. Concepts like static and register variables add further optimization to program
behavior, making functions a critical topic in C programming for engineering students.
Practice Questions on Functions in C

1. Library Functions
Example Problem:
Write a program to find the square root of a given number using the sqrt() function from the
math.h library.

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

int main() {
double number;
printf("Enter a number: ");
scanf("%lf", &number);
printf("Square root of %.2f is %.2f\n", number, sqrt(number));
return 0;
}

Self-Do Questions:
1. Write a program to find the length of a string using the strlen() function.
2. Use the pow() function to calculate the power of a number raised to another number.
3. Write a program to sort an array of integers using the qsort() library function.

2. User-Defined Functions
Example Problem:
Write a user-defined function to calculate the area of a rectangle.
Solution:
#include <stdio.h>

float calculateArea(float length, float width) {


return length * width; // Function definition
}

int main() {
float length, width;
printf("Enter length and width: ");
scanf("%f %f", &length, &width);
printf("Area of rectangle: %.2f\n", calculateArea(length, width)); // Function
call
return 0;
}

Self-Do Questions:
1. Write a user-defined function to find the factorial of a number.
2. Create a function to check if a number is even or odd.
3. Write a function to convert Celsius to Fahrenheit.

3. Recursion
Example Problem:
Write a recursive function to calculate the sum of numbers from 1 to n.

Solution:
#include <stdio.h>

int sum(int n) {
if (n == 0) {
return 0; // Base case
}
return n + sum(n - 1); // Recursive case
}

int main() {
int n;
printf("Enter a number: ");
scanf("%d", &n);
printf("Sum of numbers from 1 to %d is %d\n", n, sum(n));
return 0;
}

Self-Do Questions:
1. Write a recursive function to find the greatest common divisor (GCD) of two numbers.
2. Create a recursive function to reverse a given string.
3. Write a recursive function to generate the Fibonacci series up to n terms.

4. Pass by Value
Example Problem:
Write a program to demonstrate pass by value using a function that attempts to change the value of a
variable.
Solution:
#include <stdio.h>

void modifyValue(int x) {
x = 20; // Local modification
}

int main() {
int num = 10;
modifyValue(num);
printf("Value of num after function call: %d\n", num); // Original value
remains unchanged
return 0;
}

Self-Do Questions:
1. Write a program to demonstrate the behavior of a pass-by-value function using a different data
type.
2. Create a function that calculates the square of a number using pass by value.
3. Write a program to demonstrate why changes inside a pass-by-value function do not affect the
original variable.

5. Pass by Reference
Example Problem:
Write a program to demonstrate pass by reference using a function that modifies the original value of a
variable.
Solution:
#include <stdio.h>

void modifyValue(int *x) {


*x = 20; // Changes the original variable
}

int main() {
int num = 10;
modifyValue(&num);
printf("Value of num after function call: %d\n", num); // Modified value
return 0;
}

Self-Do Questions:
1. Write a program to swap two numbers using pass by reference.
2. Create a function to calculate the sum of two numbers using pointers.
3. Write a program to demonstrate the difference between pass by reference and pass by value.

6. Using Arrays in Functions


Example Problem:
Write a function to find the largest element in an array.
Solution:
#include <stdio.h>

int findLargest(int arr[], int size) {


int largest = arr[0];
for (int i = 1; i < size; i++) {
if (arr[i] > largest) {
largest = arr[i];
}
}
return largest;
}

int main() {
int numbers[] = {1, 3, 7, 0, 5};
int size = sizeof(numbers) / sizeof(numbers[0]);
printf("Largest element: %d\n", findLargest(numbers, size));
return 0;
}

Self-Do Questions:
1. Write a function to calculate the sum of all elements in an array.
2. Create a function to reverse an array and print the reversed array.
3. Write a function to check if an array is sorted in ascending order.

7. Static Variables in Functions


Example Problem:
Write a program to demonstrate how a static variable retains its value across multiple function calls.
Solution:
#include <stdio.h>

void increment() {
static int count = 0; // Retains its value
count++;
printf("Count: %d\n", count);
}

int main() {
increment();
increment();
increment();
return 0;
}

Self-Do Questions:
1. Write a program to track how many times a specific function is called using a static variable.
2. Create a program to simulate a simple counter using a static variable.
3. Write a program to demonstrate the difference between static and local variables in functions.
8. Register Variables
Example Problem:
Write a program to demonstrate the use of a register variable in a loop.
Solution:
#include <stdio.h>

int main() {
register int i; // Register variable for faster access
for (i = 0; i < 5; i++) {
printf("%d ", i);
}
return 0;
}

Self-Do Questions:
1. Write a program to use a register variable for frequently accessed variables in a computation.
2. Create a program to compare the behavior of register and non-register variables.
3. Write a program to demonstrate that the address of a register variable cannot be accessed.

You might also like