User Defined Functions

Introduction

User-defined functions are custom functions created by programmers to perform specific tasks in C programs. Unlike built-in library functions, user-defined functions are designed to solve particular problems or break down complex programs into smaller, manageable pieces. Functions are essential for writing organized, reusable, and maintainable code.

Functions promote the principle of “divide and conquer” by allowing complex problems to be broken into smaller sub-problems. They enable code reusability, reduce redundancy, and make programs easier to understand, debug, and maintain.

Key Concepts

Modularity: Breaking programs into smaller, independent units that perform specific tasks.

Reusability: Writing code once and using it multiple times throughout the program.

Abstraction: Hiding implementation details and providing a simple interface.

Maintainability: Making code easier to modify, debug, and enhance.

Function Structure

Basic Components

  1. Function Declaration/Prototype: Tells the compiler about the function’s existence
  2. Function Definition: Contains the actual implementation of the function
  3. Function Call: Invokes the function to execute its code

Function Syntax

return_type function_name(parameter_list) {
    // Function body
    // Local variables
    // Statements
    return value;  // if return_type is not void
}

Function Declaration and Definition

Simple Function Example

#include <stdio.h>

// Function declaration (prototype)
void greet();

int main() {
    greet();  // Function call
    return 0;
}

// Function definition
void greet() {
    printf("Hello, World!\n");
}

Function with Parameters

#include <stdio.h>

// Function to add two numbers
int add(int a, int b) {
    int sum = a + b;
    return sum;
}

int main() {
    int result = add(5, 3);
    printf("Sum: %d\n", result);
    return 0;
}

Function with Return Value

#include <stdio.h>

// Function to calculate square of a number
int square(int num) {
    return num * num;
}

int main() {
    int number = 7;
    int result = square(number);
    printf("Square of %d is %d\n", number, result);
    return 0;
}

Types of Functions

1. Functions with No Parameters and No Return Value

#include <stdio.h>

void displayMenu() {
    printf("=== MAIN MENU ===\n");
    printf("1. Option A\n");
    printf("2. Option B\n");
    printf("3. Exit\n");
}

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

2. Functions with Parameters but No Return Value

#include <stdio.h>

void printTable(int num) {
    printf("Multiplication table of %d:\n", num);
    for (int i = 1; i <= 10; i++) {
        printf("%d x %d = %d\n", num, i, num * i);
    }
}

int main() {
    printTable(5);
    return 0;
}

3. Functions with No Parameters but Return Value

#include <stdio.h>

int getRandomNumber() {
    return rand() % 100 + 1;  // Random number between 1-100
}

int main() {
    srand(time(NULL));
    int random = getRandomNumber();
    printf("Random number: %d\n", random);
    return 0;
}

4. Functions with Parameters and Return Value

#include <stdio.h>

float calculateArea(float length, float width) {
    return length * width;
}

int main() {
    float l = 5.5, w = 3.2;
    float area = calculateArea(l, w);
    printf("Area: %.2f\n", area);
    return 0;
}

Practical Examples

Example 1: Calculator Functions

#include <stdio.h>

float add(float a, float b) {
    return a + b;
}

float subtract(float a, float b) {
    return a - b;
}

float multiply(float a, float b) {
    return a * b;
}

float divide(float a, float b) {
    if (b != 0) {
        return a / b;
    } else {
        printf("Error: Division by zero!\n");
        return 0;
    }
}

int main() {
    float num1, num2;
    char operator;
    
    printf("Enter first number: ");
    scanf("%f", &num1);
    printf("Enter operator (+, -, *, /): ");
    scanf(" %c", &operator);
    printf("Enter second number: ");
    scanf("%f", &num2);
    
    switch (operator) {
        case '+':
            printf("Result: %.2f\n", add(num1, num2));
            break;
        case '-':
            printf("Result: %.2f\n", subtract(num1, num2));
            break;
        case '*':
            printf("Result: %.2f\n", multiply(num1, num2));
            break;
        case '/':
            printf("Result: %.2f\n", divide(num1, num2));
            break;
        default:
            printf("Invalid operator!\n");
    }
    
    return 0;
}

Example 2: Number Analysis Functions

#include <stdio.h>

int isEven(int num) {
    return num % 2 == 0;
}

int isPrime(int num) {
    if (num <= 1) return 0;
    for (int i = 2; i * i <= num; i++) {
        if (num % i == 0) return 0;
    }
    return 1;
}

int factorial(int num) {
    if (num <= 1) return 1;
    int fact = 1;
    for (int i = 2; i <= num; i++) {
        fact *= i;
    }
    return fact;
}

void analyzeNumber(int num) {
    printf("Analysis of %d:\n", num);
    printf("Even: %s\n", isEven(num) ? "Yes" : "No");
    printf("Prime: %s\n", isPrime(num) ? "Yes" : "No");
    printf("Factorial: %d\n", factorial(num));
}

int main() {
    int number;
    printf("Enter a number: ");
    scanf("%d", &number);
    analyzeNumber(number);
    return 0;
}

Example 3: Array Processing Functions

#include <stdio.h>

void printArray(int arr[], int size) {
    for (int i = 0; i < size; i++) {
        printf("%d ", arr[i]);
    }
    printf("\n");
}

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

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

int main() {
    int numbers[] = {23, 45, 67, 12, 89, 34};
    int size = sizeof(numbers) / sizeof(numbers[0]);
    
    printf("Array: ");
    printArray(numbers, size);
    printf("Maximum: %d\n", findMax(numbers, size));
    printf("Average: %.2f\n", calculateAverage(numbers, size));
    
    return 0;
}

Function Parameters

Pass by Value

#include <stdio.h>

void increment(int x) {
    x = x + 1;  // Only changes local copy
    printf("Inside function: x = %d\n", x);
}

int main() {
    int num = 5;
    printf("Before function: num = %d\n", num);
    increment(num);
    printf("After function: num = %d\n", num);  // num unchanged
    return 0;
}

Pass by Reference (using pointers)

#include <stdio.h>

void increment(int *x) {
    *x = *x + 1;  // Changes original value
    printf("Inside function: *x = %d\n", *x);
}

int main() {
    int num = 5;
    printf("Before function: num = %d\n", num);
    increment(&num);
    printf("After function: num = %d\n", num);  // num changed
    return 0;
}

Important Points

  • Function Prototype: Always declare function prototypes before main() or before first use
  • Return Statement: Functions with non-void return type must return a value
  • Local Variables: Variables declared inside functions are local to that function
  • Parameter Names: Parameter names in declaration and definition can be different
  • Code Reusability: Write functions for tasks that are performed multiple times
  • Single Responsibility: Each function should perform one specific task

Common Mistakes and Solutions

Mistake 1: Missing Function Prototype

// Wrong - function used before declaration
int main() {
    int result = add(5, 3);  // Error: 'add' not declared
    return 0;
}

int add(int a, int b) {
    return a + b;
}

// Correct - declare prototype first
int add(int a, int b);  // Prototype

int main() {
    int result = add(5, 3);
    return 0;
}

int add(int a, int b) {
    return a + b;
}

Mistake 2: Missing Return Statement

// Wrong - missing return in non-void function
int multiply(int a, int b) {
    int result = a * b;
    // Missing return statement
}

// Correct - always return a value
int multiply(int a, int b) {
    int result = a * b;
    return result;
}

Advanced Function Example

Student Grade Management System

#include <stdio.h>

void inputGrades(float grades[], int size) {
    printf("Enter %d grades:\n", size);
    for (int i = 0; i < size; i++) {
        printf("Grade %d: ", i + 1);
        scanf("%f", &grades[i]);
    }
}

float calculateAverage(float grades[], int size) {
    float sum = 0;
    for (int i = 0; i < size; i++) {
        sum += grades[i];
    }
    return sum / size;
}

char assignLetterGrade(float average) {
    if (average >= 90) return 'A';
    else if (average >= 80) return 'B';
    else if (average >= 70) return 'C';
    else if (average >= 60) return 'D';
    else return 'F';
}

void displayReport(float grades[], int size, float average, char letter) {
    printf("\n=== GRADE REPORT ===\n");
    printf("Grades: ");
    for (int i = 0; i < size; i++) {
        printf("%.1f ", grades[i]);
    }
    printf("\nAverage: %.2f\n", average);
    printf("Letter Grade: %c\n", letter);
}

int main() {
    const int NUM_GRADES = 5;
    float grades[NUM_GRADES];
    
    inputGrades(grades, NUM_GRADES);
    float average = calculateAverage(grades, NUM_GRADES);
    char letterGrade = assignLetterGrade(average);
    displayReport(grades, NUM_GRADES, average, letterGrade);
    
    return 0;
}

Benefits of User-Defined Functions

Code Organization

  • Break complex problems into smaller, manageable pieces
  • Create logical groupings of related functionality
  • Improve code readability and understanding

Reusability

  • Write once, use multiple times
  • Reduce code duplication
  • Consistent implementation across the program

Maintainability

  • Easier to debug and fix issues
  • Changes in one function don’t affect others
  • Simplified testing of individual components

Team Development

  • Different team members can work on different functions
  • Clear interfaces between different parts of the program
  • Easier to assign and track development tasks

Summary

User-defined functions are essential building blocks for creating well-structured, maintainable C programs. They enable programmers to break complex problems into smaller, manageable pieces, promote code reusability, and improve program organization. Understanding function declaration, definition, and calling mechanisms is crucial for effective C programming. Functions support different parameter passing methods and return types, allowing flexible design of program modules. Key benefits include improved code organization, reduced redundancy, easier debugging, and enhanced team collaboration. Mastering user-defined functions is fundamental for progressing to advanced programming concepts and building sophisticated software applications. Proper use of functions leads to cleaner, more maintainable code that follows good software engineering practices.


Part of BCA Programming with C Course (UGCOA22J201)