Functions Examples Progress
0%
Functions  ·  Examples Page

Functions — 10 Deep Examples

Ten programs covering every function technique — math utilities, recursive patterns, sorting algorithms, string processing, multiple return values, and a complete student system.

1Math Utils
2Number Check
3Swap & Sort
4Fibonacci Two Ways
5Pascal Triangle
6String Library
7Multiple Return
8Recursive Patterns
9Array Functions
10Student System
1

Math Utility Library — abs, power, sqrt, log

Multiple helper functions
Concepts: multiple functions, return types, math operations

Build a mini math library with clean, reusable functions. Each function has a single responsibility. Fast power uses repeated squaring (O(log n) instead of O(n)) — an IIT-favourite optimisation. Custom mySqrt uses the Newton-Raphson method to converge on the square root without importing math.h.

math_utils.c
C
#include <stdio.h>

/* Absolute value — works for negatives too */
int myAbs(int n) {
    return (n < 0) ? -n : n;
}

/* Fast power: O(log exp) using repeated squaring */
long fastPow(long base, int exp) {
    long result = 1;
    while (exp > 0) {
        if (exp % 2 == 1)        /* odd exponent: multiply once */
            result *= base;
        base *= base;            /* square the base */
        exp  /= 2;              /* halve the exponent */
    }
    return result;
}

/* Newton-Raphson square root — no math.h needed */
double mySqrt(double n) {
    if (n < 0) return -1;   /* error */
    double guess = n / 2.0;
    for (int i = 0; i < 50; i++)      /* 50 iterations = very precise */
        guess = (guess + n / guess) / 2.0;
    return guess;
}

/* Greatest common divisor — Euclid's algorithm */
int gcd(int a, int b) {
    return (b == 0) ? a : gcd(b, a % b);
}

/* Least common multiple */
int lcm(int a, int b) {
    return (a / gcd(a, b)) * b;
}

/* Ceiling division: a / b rounded up */
int ceilDiv(int a, int b) {
    return (a + b - 1) / b;
}

int main() {
    printf("abs(-42)       = %d\n",   myAbs(-42));
    printf("fastPow(2,10)  = %ld\n",  fastPow(2, 10));
    printf("fastPow(3,5)   = %ld\n",  fastPow(3, 5));
    printf("mySqrt(144)    = %.4f\n", mySqrt(144));
    printf("mySqrt(2)      = %.6f\n", mySqrt(2));
    printf("gcd(48,18)     = %d\n",   gcd(48, 18));
    printf("lcm(12,18)     = %d\n",   lcm(12, 18));
    printf("ceilDiv(10,3)  = %d\n",   ceilDiv(10, 3)); /* ceil(10/3)=4 */
    return 0;
}
terminal
output
abs(-42)       = 42
fastPow(2,10)  = 1024
fastPow(3,5)   = 243
mySqrt(144)    = 12.0000
mySqrt(2)      = 1.414214
gcd(48,18)     = 6
lcm(12,18)     = 36
ceilDiv(10,3)  = 4
fastPow trace for 2^10: exp=10(even)→base=4,exp=5 | exp=5(odd)→result=4,base=16,exp=2 | exp=2(even)→base=256,exp=1 | exp=1(odd)→result=1024,exp=0. Done in 4 steps vs 10 multiplications. For 2^64, that's 6 steps vs 64.
example 2
2

Number Property Checker — Prime, Armstrong, Perfect

Boolean functions
Concepts: bool-style int return, helper functions, digit extraction

Three number property functions that each return 1 (true) or 0 (false). Armstrong number: sum of each digit raised to the power of the number of digits equals the original (153 = 1³+5³+3³). Perfect number: sum of proper divisors equals itself (6 = 1+2+3).

number_check.c
C
#include <stdio.h>

int countDigits(int n) {
    int count = 0;
    while (n != 0) { n /= 10; count++; }
    return count;
}

long power(int base, int exp) {
    long r = 1;
    while (exp--) r *= base;
    return r;
}

/* Prime: no divisors from 2 to sqrt(n) */
int isPrime(int n) {
    if (n <= 1) return 0;
    for (int i = 2; i * i <= n; i++)
        if (n % i == 0) return 0;
    return 1;
}

/* Armstrong: sum of (each digit ^ numDigits) == n */
int isArmstrong(int n) {
    int  digits = countDigits(n);
    long sum = 0;
    int  temp = n;
    while (temp != 0) {
        sum  += power(temp % 10, digits);
        temp /= 10;
    }
    return sum == n;
}

/* Perfect: sum of proper divisors == n */
int isPerfect(int n) {
    if (n <= 1) return 0;
    int sum = 1;
    for (int i = 2; i * i <= n; i++)
        if (n % i == 0) {
            sum += i;
            if (i != n/i) sum += n/i;
        }
    return sum == n;
}

int main() {
    int tests[] = {1,2,6,9,17,28,97,153,496};
    printf("%-6s %-8s %-12s %-8s\n","N","Prime","Armstrong","Perfect");
    printf("-------------------------------------\n");
    for (int i=0; i<9; i++)
        printf("%-6d %-8s %-12s %s\n",
               tests[i],
               isPrime(tests[i])     ? "YES" : "no",
               isArmstrong(tests[i]) ? "YES" : "no",
               isPerfect(tests[i])   ? "YES" : "no");
    return 0;
}
terminal
output
N      Prime    Armstrong    Perfect
-------------------------------------
1      no       YES          no
2      YES      no           no
6      no       no           YES
9      no       no           no
17     YES      no           no
28     no       no           YES
97     YES      no           no
153    no       YES          no
496    no       no           YES
example 3
3

Correct Swap + Three Sorting Functions

Pass by reference
Concepts: pointers, bubble sort, selection sort, insertion sort

The correct swap using pointers, then three classic sorting algorithms each packaged as a clean reusable function. Insertion sort is the most efficient for nearly-sorted arrays and is used inside sort algorithms like Timsort.

swap_sort.c
C
#include <stdio.h>

void swap(int *a, int *b) {
    int t = *a; *a = *b; *b = t;
}

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

/* Bubble Sort: O(n²) — compare adjacent, bubble max to end */
void bubbleSort(int arr[], int n) {
    for (int i=0; i<n-1; i++) {
        int swapped = 0;
        for (int j=0; j<n-i-1; j++)
            if (arr[j] > arr[j+1]) { swap(&arr[j],&arr[j+1]); swapped=1; }
        if (!swapped) break;       /* optimisation: stop if already sorted */
    }
}

/* Selection Sort: O(n²) — find min, place at front */
void selectionSort(int arr[], int n) {
    for (int i=0; i<n-1; i++) {
        int minIdx = i;
        for (int j=i+1; j<n; j++)
            if (arr[j] < arr[minIdx]) minIdx = j;
        if (minIdx != i) swap(&arr[i], &arr[minIdx]);
    }
}

/* Insertion Sort: O(n²) worst, O(n) for nearly sorted */
void insertionSort(int arr[], int n) {
    for (int i=1; i<n; i++) {
        int key = arr[i], j = i-1;
        while (j >= 0 && arr[j] > key) {
            arr[j+1] = arr[j];
            j--;
        }
        arr[j+1] = key;
    }
}

int main() {
    int a[] = {64,25,12,92,43};
    int b[] = {64,25,12,92,43};
    int c[] = {64,25,12,92,43};

    bubbleSort(a,5);    printf("Bubble:    "); printArr(a,5);
    selectionSort(b,5); printf("Selection: "); printArr(b,5);
    insertionSort(c,5); printf("Insertion: "); printArr(c,5);
    return 0;
}
terminal
output
Bubble:    12 25 43 64 92
Selection: 12 25 43 64 92
Insertion: 12 25 43 64 92
IIT comparison: All three are O(n²) worst-case. But bubble sort with the swapped flag becomes O(n) on already-sorted input. Insertion sort makes fewer comparisons and is stable — equal elements keep their original order. Selection sort always makes exactly n-1 swaps regardless of input.
example 4
4

Fibonacci — Recursive vs Iterative vs Memoised

O(2ⁿ) vs O(n)
Concepts: recursion, iteration, static memoisation, call counting

Call tree for fib(5) — recursive makes 15 calls, iterative makes 5 steps

fib(5)
fib(4) + fib(3)
→ fib(3) called AGAIN inside fib(4)! — wasteful
fib(4)
fib(3) + fib(2)
→ fib(2) called 3 times total in fib(5)
fib(1)
return 1 ← base
→ base case: called 5 times in fib(5)
fibonacci_three.c
C
#include <stdio.h>
#include <string.h>

int callCount = 0;   /* count recursive calls */

/* Method 1: Naive recursive — O(2^n) calls */
int fibRec(int n) {
    callCount++;
    if (n <= 1) return n;
    return fibRec(n-1) + fibRec(n-2);
}

/* Method 2: Iterative — O(n) time, O(1) space */
long fibIter(int n) {
    if (n <= 1) return n;
    long a=0, b=1, c;
    for (int i=2; i<=n; i++) { c=a+b; a=b; b=c; }
    return b;
}

/* Method 3: Memoised recursive — O(n) time via cache */
#define MAXN 50
long memo[MAXN];

long fibMemo(int n) {
    if (n <= 1) return n;
    if (memo[n] != -1) return memo[n];  /* already computed! */
    return memo[n] = fibMemo(n-1) + fibMemo(n-2);
}

int main() {
    printf("Fibonacci Comparison (n=10):\n");
    printf("%-10s %-10s %-12s %s\n","n","Recursive","Iterative","Memo");
    printf("--------------------------------------------\n");

    for (int n=0; n<=10; n++) {
        callCount = 0;
        memset(memo, -1, sizeof(memo));
        int r = fibRec(n);
        printf("%-10d %-10d %-12ld %ld  (calls=%d)\n",
               n, r, fibIter(n), fibMemo(n), callCount);
    }
    return 0;
}
terminal — recursive call count grows exponentially
output
n          Recursive  Iterative    Memo
--------------------------------------------
0          0          0            0   (calls=1)
1          1          1            1   (calls=1)
5          5          5            5   (calls=15)
8          21         21           21  (calls=67)
10         55         55           55  (calls=177)
Key takeaway: fib(10) needs 177 recursive calls but only 10 iterative steps. fib(40) needs over 300 million calls recursively. Always use iterative or memoised for Fibonacci in real programs.
example 5
5

Pascal's Triangle Using Recursive Combination

nCr recursion
Concepts: nCr recursion, 2D array building, triangle display
pascal_triangle.c
C
#include <stdio.h>

/* nCr = n! / (r! * (n-r)!) — computed recursively
   Base: nC0 = 1, nCn = 1
   Rule: nCr = (n-1)C(r-1) + (n-1)Cr               */
long nCr(int n, int r) {
    if (r == 0 || r == n) return 1;     /* base: edges are 1 */
    return nCr(n-1, r-1) + nCr(n-1, r);  /* Pascal's rule */
}

void printPascal(int rows) {
    for (int n = 0; n < rows; n++) {
        /* Print leading spaces for triangle shape */
        for (int sp = 0; sp < rows-n-1; sp++) printf("   ");
        for (int r = 0; r <= n; r++)
            printf("%5ld ", nCr(n, r));
        printf("\n");
    }
}

/* Binomial expansion: (a+b)^n coefficients */
void binomialExpand(int n) {
    printf("(a+b)^%d = ", n);
    for (int r = 0; r <= n; r++) {
        long coef = nCr(n, r);
        if (r > 0) printf(" + ");
        if (coef > 1) printf("%ld", coef);
        if (r < n) printf("a^%d", n-r);
        if (r > 0 && r < n) printf("b^%d", r);
        if (r == n) printf("b^%d", n);
    }
    printf("\n");
}

int main() {
    printf("Pascal's Triangle (6 rows):\n\n");
    printPascal(6);
    printf("\nBinomial Expansions:\n");
    binomialExpand(3);
    binomialExpand(4);
    return 0;
}
terminal
output
Pascal's Triangle (6 rows):

                    1
                 1     1
              1     2     1
           1     3     3     1
        1     4     6     4     1
     1     5    10    10     5     1

Binomial Expansions:
(a+b)^3 = a^3 + 3a^2b^1 + 3a^1b^2 + b^3
(a+b)^4 = a^4 + 4a^3b^1 + 6a^2b^2 + 4a^1b^3 + b^4
example 6
6

String Processing Functions — Full Utility Set

char* parameters
Concepts: char pointer parameters, in-place modification, boolean returns
string_utils.c
C
#include <stdio.h>
#include <ctype.h>

int  myLen(char *s)    { int i=0; while(s[i]) i++; return i; }
void toUpper(char *s)  { for(int i=0;s[i];i++) s[i]=toupper(s[i]); }
void toLower(char *s)  { for(int i=0;s[i];i++) s[i]=tolower(s[i]); }

/* Reverse string in-place using two-pointer swap */
void reverse(char *s) {
    int l=0, r=myLen(s)-1;
    while(l<r) { char t=s[l]; s[l++]=s[r]; s[r--]=t; }
}

/* Palindrome check — compare from both ends */
int isPalindrome(char *s) {
    int l=0, r=myLen(s)-1;
    while(l<r) if(tolower(s[l++])!=tolower(s[r--])) return 0;
    return 1;
}

/* Count occurrences of a character */
int countCh(char *s, char c) {
    int cnt=0;
    for(int i=0;s[i];i++) if(tolower(s[i])==tolower(c)) cnt++;
    return cnt;
}

/* Find first occurrence, return index or -1 */
int findCh(char *s, char c) {
    for(int i=0;s[i];i++) if(s[i]==c) return i;
    return -1;
}

/* Remove all spaces from string */
void removeSpaces(char *s) {
    int i=0, j=0;
    while(s[i]) { if(s[i]!=' ') s[j++]=s[i]; i++; }
    s[j]='\0';
}

/* Count words (sequences separated by spaces) */
int wordCount(char *s) {
    int cnt=0, inWord=0;
    for(int i=0;s[i];i++){
        if(s[i]!=' '){ if(!inWord){ cnt++; inWord=1; }}
        else inWord=0;
    }
    return cnt;
}

int main() {
    char s1[] = "Hello World";
    char s2[] = "racecar";
    char s3[] = "Hello  Ananta  Code";

    printf("len(\"%s\")       = %d\n", s1, myLen(s1));
    printf("words(\"%s\") = %d\n", s1, wordCount(s1));
    printf("isPalin(\"%s\")  = %d\n", s2, isPalindrome(s2));
    printf("isPalin(\"%s\") = %d\n", s1, isPalindrome(s1));
    printf("countCh l in \"%s\" = %d\n", s1, countCh(s1,'l'));
    printf("findCh 'W'       = %d\n", findCh(s1,'W'));
    toUpper(s1);
    printf("toUpper: %s\n", s1);
    reverse(s2);
    printf("reverse: %s\n", s2);
    removeSpaces(s3);
    printf("noSpaces: %s\n", s3);
    return 0;
}
terminal
output
len("Hello World")       = 11
words("Hello World")     = 2
isPalin("racecar")       = 1
isPalin("Hello World")   = 0
countCh l in "Hello World" = 3
findCh 'W'               = 6
toUpper: HELLO WORLD
reverse: racecar
noSpaces: HelloAnantaCode
example 7
7

Multiple Return Values via Output Pointers

Pointer output params
Concepts: output pointer parameters, void return, multiple results

C functions can only return one value directly. When you need multiple results, pass output pointers as parameters and write results into them. This is exactly how scanf works — it receives addresses and writes values at those addresses.

multi_return.c
C
#include <stdio.h>
#include <math.h>

/* Returns min AND max in one call using output pointers */
void findMinMax(int arr[], int n, int *minOut, int *maxOut) {
    *minOut = *maxOut = arr[0];
    for (int i=1; i<n; i++) {
        if (arr[i] < *minOut) *minOut = arr[i];
        if (arr[i] > *maxOut) *maxOut = arr[i];
    }
}

/* Returns sum AND average together */
void sumAvg(int arr[], int n, int *sumOut, float *avgOut) {
    *sumOut = 0;
    for (int i=0; i<n; i++) *sumOut += arr[i];
    *avgOut = (float)*sumOut / n;
}

/* Quadratic formula: returns root count, writes roots to r1, r2 */
int quadratic(float a, float b, float c,
               float *r1, float *r2) {
    float disc = b*b - 4*a*c;
    if (disc < 0) return 0;       /* no real roots */
    if (disc == 0) {
        *r1 = *r2 = -b / (2*a);
        return 1;                    /* one repeated root */
    }
    *r1 = (-b + sqrt(disc)) / (2*a);
    *r2 = (-b - sqrt(disc)) / (2*a);
    return 2;                        /* two distinct roots */
}

int main() {
    int   arr[] = {40,12,75,3,58,29};
    int   mn, mx, s; float av;

    findMinMax(arr, 6, &mn, &mx);
    sumAvg(arr, 6, &s, &av);
    printf("Min=%d  Max=%d  Sum=%d  Avg=%.1f\n", mn, mx, s, av);

    float r1, r2;
    int roots = quadratic(1, -5, 6, &r1, &r2);  /* x²-5x+6=0 */
    printf("x²-5x+6: roots=%d  r1=%.1f r2=%.1f\n", roots, r1, r2);

    roots = quadratic(1, 2, 5, &r1, &r2);          /* x²+2x+5=0 */
    printf("x²+2x+5: roots=%d  (imaginary)\n", roots);
    return 0;
}
terminal
output
Min=3  Max=75  Sum=217  Avg=36.2
x²-5x+6: roots=2  r1=3.0 r2=2.0
x²+2x+5: roots=0  (imaginary)
example 8
8

Recursive Patterns — Stars, Numbers, Binary

Print recursion
Concepts: print recursion, binary conversion, flood fill idea
recursive_patterns.c
C
#include <stdio.h>

/* Countdown then countup — output BEFORE and AFTER recursion */
void countDown(int n) {
    if (n == 0) { printf("0 "); return; }
    printf("%d ", n);            /* print BEFORE recursion → countdown */
    countDown(n - 1);
    printf("%d ", n);            /* print AFTER recursion → countup */
}

/* Decimal to binary — recursion prints most-significant bit first */
void toBinary(int n) {
    if (n == 0) return;
    toBinary(n / 2);            /* recurse FIRST — MSB printed last */
    printf("%d", n % 2);         /* print on RETURN — so left to right */
}

/* Sum of array recursively */
int arrSum(int arr[], int n) {
    if (n == 0) return 0;
    return arr[n-1] + arrSum(arr, n-1);  /* peel off last element */
}

/* Check if array is sorted recursively */
int isSorted(int arr[], int n) {
    if (n <= 1) return 1;          /* 0 or 1 element — always sorted */
    if (arr[0] > arr[1]) return 0; /* first pair unsorted → false */
    return isSorted(arr+1, n-1);    /* check rest of array */
}

/* Recursive print of digits (rightmost first) */
void printDigits(int n) {
    if (n < 10) { printf("%d\n", n); return; }
    printDigits(n / 10);
    printf("%d\n", n % 10);
}

int main() {
    printf("countDown(4): "); countDown(4); printf("\n");

    printf("toBinary(42)  = "); toBinary(42);  printf("\n");
    printf("toBinary(255) = "); toBinary(255); printf("\n");

    int a[] = {10,20,30,40};
    int b[] = {10,5,30};
    printf("arrSum={10,20,30,40} = %d\n", arrSum(a,4));
    printf("isSorted(a) = %d\n", isSorted(a,4));
    printf("isSorted(b) = %d\n", isSorted(b,3));

    printf("digits of 9875:\n"); printDigits(9875);
    return 0;
}
terminal
output
countDown(4): 4 3 2 1 0 1 2 3 4
toBinary(42)  = 101010
toBinary(255) = 11111111
arrSum={10,20,30,40} = 100
isSorted(a) = 1
isSorted(b) = 0
digits of 9875:
9
8
7
5
Why toBinary works: Recursing first delays printing until the call unwinds — so the most-significant bits (computed last, n/2 is smaller) are printed first when the stack unwinds. Printing before recursion would reverse the output.
example 9
9

Advanced Array Functions — Rotate, Merge, Remove Dups

In-place + pointer operations
Concepts: array mutation via pointers, two-pointer technique
array_functions.c
C
#include <stdio.h>

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

/* Left rotate array by k positions */
void rotateLeft(int arr[], int n, int k) {
    k %= n;   /* handle k > n */
    for (int i=0; i<k; i++) {
        int t=arr[0];
        for(int j=0;j<n-1;j++) arr[j]=arr[j+1];
        arr[n-1]=t;
    }
}

/* Remove duplicates from sorted array, return new length */
int removeDups(int arr[], int n) {
    if (n==0) return 0;
    int j=0;
    for(int i=1;i<n;i++)
        if(arr[i]!=arr[j]) arr[++j]=arr[i];
    return j+1;
}

/* Merge two sorted arrays into result[] */
int mergeSorted(int a[], int na, int b[], int nb, int res[]) {
    int i=0, j=0, k=0;
    while(i<na && j<nb) res[k++]=(a[i]<b[j])?a[i++]:b[j++];
    while(i<na) res[k++]=a[i++];
    while(j<nb) res[k++]=b[j++];
    return na+nb;
}

/* Find majority element (appears > n/2 times) — Boyer-Moore */
int majorityElem(int arr[], int n) {
    int candidate=arr[0], count=1;
    for(int i=1;i<n;i++){
        count += (arr[i]==candidate) ? 1 : -1;
        if(count==0){ candidate=arr[i]; count=1; }
    }
    return candidate;
}

int main() {
    int a[] = {1,2,3,4,5};
    printf("Original: "); print(a,5);
    rotateLeft(a,5,2);
    printf("Rotate L2: "); print(a,5);

    int d[] = {1,1,2,3,3,4,4,4,5};
    int len = removeDups(d,9);
    printf("RemoveDups: "); print(d,len);

    int b[]={1,3,5}, c[]={2,4,6}, merged[6];
    mergeSorted(b,3,c,3,merged);
    printf("Merged: "); print(merged,6);

    int m[] = {3,3,4,2,3};
    printf("Majority elem = %d\n", majorityElem(m,5));
    return 0;
}
terminal
output
Original:   1 2 3 4 5
Rotate L2:  3 4 5 1 2
RemoveDups: 1 2 3 4 5
Merged:     1 2 3 4 5 6
Majority elem = 3
example 10
10

Complete Student Grade System — All Techniques Combined

Real program
Concepts: all function types, 2D array params, string arrays, pointers

A complete academic program that combines every function technique: void functions for display, float-returning functions for averages, char-returning functions for grades, pointer parameters for statistics, sorting using function-based bubble sort, and string arrays for names.

student_system.c
C
#include <stdio.h>
#include <string.h>
#define STU  5
#define SUB  4

char names[STU][20] = {"Ananta","Priya","Rahul","Vikram","Sneha"};
int  marks[STU][SUB]= {{92,85,98,88},{78,82,75,90},
                        {60,55,70,65},{88,90,85,92},{95,93,97,96}};

/* Return average marks for one student */
float getAvg(int idx) {
    int sum=0;
    for(int j=0;j<SUB;j++) sum+=marks[idx][j];
    return (float)sum/SUB;
}

/* Return grade char based on average */
char getGrade(float avg) {
    if(avg>=90) return 'A';
    if(avg>=75) return 'B';
    if(avg>=55) return 'C';
    return 'F';
}

/* Find class topper and average — output pointers */
void classStats(int *topperIdx, float *classAvg) {
    float total=0; *topperIdx=0;
    float best = getAvg(0);
    for(int i=0;i<STU;i++){
        float a=getAvg(i);
        total+=a;
        if(a>best){ best=a; *topperIdx=i; }
    }
    *classAvg = total/STU;
}

/* Sort students by average descending (bubble sort) */
void sortByAvg() {
    for(int i=0;i<STU-1;i++)
        for(int j=0;j<STU-i-1;j++)
            if(getAvg(j)<getAvg(j+1)){
                /* swap entire rows of marks and names */
                int tmpM[SUB]; char tmpN[20];
                memcpy(tmpM,marks[j],sizeof(tmpM));
                memcpy(marks[j],marks[j+1],sizeof(tmpM));
                memcpy(marks[j+1],tmpM,sizeof(tmpM));
                strcpy(tmpN,names[j]);
                strcpy(names[j],names[j+1]);
                strcpy(names[j+1],tmpN);
            }
}

/* Print formatted report card */
void printReport() {
    printf("%-10s %4s %4s %4s %4s  Avg   Grade\n",
           "Name","M1","M2","M3","M4");
    printf("-------------------------------------------\n");
    for(int i=0;i<STU;i++){
        float avg=getAvg(i);
        printf("%-10s %4d %4d %4d %4d  %4.1f  %c\n",
               names[i],marks[i][0],marks[i][1],marks[i][2],marks[i][3],
               avg,getGrade(avg));
    }
}

int main() {
    int topIdx; float clsAvg;

    printf("=== ORIGINAL REPORT ===\n");
    printReport();
    classStats(&topIdx, &clsAvg);
    printf("Class Average: %.1f\n", clsAvg);
    printf("Topper: %s (%.1f)\n", names[topIdx], getAvg(topIdx));

    printf("\n=== SORTED BY AVERAGE (HIGH TO LOW) ===\n");
    sortByAvg();
    printReport();
    return 0;
}
terminal
output
=== ORIGINAL REPORT ===
Name        M1   M2   M3   M4  Avg   Grade
-------------------------------------------
Ananta      92   85   98   88  90.8  A
Priya       78   82   75   90  81.3  B
Rahul       60   55   70   65  62.5  C
Vikram      88   90   85   92  88.8  B
Sneha       95   93   97   96  95.3  A
Class Average: 83.7
Topper: Sneha (95.3)

=== SORTED BY AVERAGE (HIGH TO LOW) ===
Name        M1   M2   M3   M4  Avg   Grade
-------------------------------------------
Sneha       95   93   97   96  95.3  A
Ananta      92   85   98   88  90.8  A
Vikram      88   90   85   92  88.8  B
Priya       78   82   75   90  81.3  B
Rahul       60   55   70   65  62.5  C
examples checklist

Examples Mastery Checklist

  • E1 — I understand fast power O(log n) using repeated squaring
  • E1 — I can explain Newton-Raphson sqrt without math.h
  • E2 — I can write isPrime using i*i <= n loop (O(√n))
  • E2 — I know Armstrong number: sum of digit^numDigits == n
  • E3 — I can write bubble, selection, and insertion sort as functions
  • E3 — I know which sort is best for nearly-sorted arrays (insertion)
  • E4 — I understand why recursive Fibonacci is O(2ⁿ) — repeated subproblems
  • E4 — I can implement memoised Fibonacci using a static cache array
  • E5 — I know Pascal's rule: nCr = (n-1)C(r-1) + (n-1)Cr
  • E6 — I can write in-place string functions using char pointer parameters
  • E7 — I can use output pointer parameters to return multiple values
  • E8 — I understand print-before vs print-after recursion gives different outputs
  • E9 — I can implement rotate, removeDups, merge sorted arrays as functions
  • E10 — I can combine all function types in one complete program