Browse papers
A

Section A: Long Answer Questions

Attempt all / any as specified.

4 questions
1long12 marks

(a) Describe the basic structure of a C program with the help of a suitable diagram, clearly explaining the role of preprocessor directives, the main() function, declarations, and statements. [6]

(b) What are the fundamental (primitive) data types available in C? Write a program that reads the radius of a circle from the user and prints its area and circumference, using an appropriate symbolic constant for the value of π. [6]

(a) Basic structure of a C program [6]

A C program is organised into the following sections (top to bottom):

+---------------------------------------------+
| 1. Preprocessor directives  (#include, #define) |
+---------------------------------------------+
| 2. Global declarations                      |
+---------------------------------------------+
| 3. int main(void) {                          |
|       3a. Local declarations                |
|       3b. Statements / executable code      |
|       return 0;                              |
|    }                                         |
+---------------------------------------------+
| 4. User-defined functions (optional)        |
+---------------------------------------------+
#include <stdio.h>        /* preprocessor directive */
#define PI 3.14159         /* symbolic constant      */

int main(void) {           /* main() function        */
    int n = 5;             /* declaration            */
    printf("%d\n", n);    /* statement              */
    return 0;
}

Role of each part

  • Preprocessor directives — lines beginning with #. They are handled by the preprocessor before compilation. #include pastes header files (e.g. stdio.h for I/O prototypes) into the source; #define creates symbolic constants and macros.
  • main() function — the mandatory entry point. Program execution always begins in main(). It returns an int status code to the operating system (return 0; means success).
  • Declarations — introduce variables/constants and their types before they are used, telling the compiler how much memory to reserve and how to interpret it.
  • Statements — the executable instructions (assignments, function calls, loops, conditions) that carry out the program's logic, each terminated by a semicolon.

(b) Fundamental data types and circle program [6]

The fundamental (primitive) data types in C are:

TypeTypical sizeStores
char1 bytea single character
int2 or 4 bytesintegers
float4 bytessingle-precision real numbers
double8 bytesdouble-precision real numbers
voidabsence of a value/type

Modifiers (short, long, signed, unsigned) extend these.

#include <stdio.h>
#define PI 3.14159   /* symbolic constant for pi */

int main(void) {
    float radius, area, circumference;

    printf("Enter the radius of the circle: ");
    scanf("%f", &radius);

    area = PI * radius * radius;          /* A = pi r^2 */
    circumference = 2 * PI * radius;       /* C = 2 pi r */

    printf("Area = %.2f\n", area);
    printf("Circumference = %.2f\n", circumference);
    return 0;
}

For r=7r = 7: area =πr2153.94=\pi r^2 \approx 153.94 and circumference =2πr43.98=2\pi r \approx 43.98.

program-structuredata-typescontrol-statements
2long12 marks

(a) What is recursion? Differentiate between a recursive function and an iterative function with respect to memory usage and execution. [4]

(b) Write a recursive C function to compute the factorial of a non-negative integer n, and trace the sequence of recursive calls and returns for n = 4. [4]

(c) Explain the difference between call by value and call by reference with a program that swaps the values of two variables. [4]

(a) Recursion vs iteration [4]

Recursion is a technique in which a function calls itself (directly or indirectly) to solve a problem by reducing it to smaller instances of the same problem, until a base case stops the calls.

AspectRecursive functionIterative function
MemoryUses extra memory — each call pushes a new stack frame; deep recursion can cause stack overflowUses a fixed amount of memory (loop variables only)
ExecutionUsually slower due to function-call overhead (saving/restoring state)Usually faster, no call overhead
CodeShorter, closer to mathematical definitionOften longer but more efficient
TerminationStops at the base caseStops when the loop condition becomes false

(b) Recursive factorial and trace for n = 4 [4]

long factorial(int n) {
    if (n == 0 || n == 1)   /* base case */
        return 1;
    return n * factorial(n - 1);  /* recursive case */
}

Trace for factorial(4) — calls go down, returns come back up:

factorial(4) = 4 * factorial(3)
  factorial(3) = 3 * factorial(2)
    factorial(2) = 2 * factorial(1)
      factorial(1) = 1           <-- base case returns 1
    factorial(2) = 2 * 1 = 2
  factorial(3) = 3 * 2 = 6
factorial(4) = 4 * 6 = 24

Final result: 4!=244! = 24.

(c) Call by value vs call by reference [4]

  • Call by value: a copy of the argument is passed to the function. Changes made inside the function affect only the copy, not the caller's original variables.
  • Call by reference: the address of the argument is passed (via pointers in C). The function can dereference the pointer and modify the caller's original variables.
#include <stdio.h>

void swapByValue(int a, int b) {        /* does NOT swap caller's data */
    int t = a; a = b; b = t;
}

void swapByRef(int *a, int *b) {        /* swaps caller's data */
    int t = *a; *a = *b; *b = t;
}

int main(void) {
    int x = 5, y = 10;

    swapByValue(x, y);
    printf("After call by value : x=%d, y=%d\n", x, y);  /* 5, 10 */

    swapByRef(&x, &y);
    printf("After call by reference: x=%d, y=%d\n", x, y); /* 10, 5 */
    return 0;
}

The value version leaves x and y unchanged; the reference version actually swaps them.

functionsrecursionarrays
3long12 marks

(a) What is a pointer? Explain the relationship between arrays and pointers in C, and show how the expression *(arr + i) is equivalent to arr[i]. [6]

(b) Write a C program that uses a pointer to traverse a character array and counts the number of vowels, consonants, and digits in a string entered by the user. [6]

(a) Pointers and the array–pointer relationship [6]

A pointer is a variable that stores the memory address of another variable. It is declared with *, e.g. int *p;, and &x gives the address of x while *p dereferences the pointer to access the value it points to.

Relationship between arrays and pointers: the name of an array, used in an expression, decays into a pointer to its first element. So for int arr[5];, the name arr is equivalent to &arr[0].

Because array elements are stored contiguously, adding i to the base pointer advances it by i elements (pointer arithmetic scales by sizeof(element)):

arr+i    &arr[i](arr+i)    arr[i]arr + i \;\equiv\; \&arr[i] \quad\Longrightarrow\quad *(arr + i) \;\equiv\; arr[i]

For example, if arr starts at address 1000 and sizeof(int) = 4:

ExpressionAddress computedValue
arr + 01000arr[0]
arr + 11004arr[1]
arr + 21008arr[2]

Thus arr[i] is just syntactic sugar that the compiler translates into *(arr + i). (Indeed i[arr] is also legal and identical.)

(b) Count vowels, consonants and digits using a pointer [6]

#include <stdio.h>

int main(void) {
    char str[100];
    char *p;
    int vowels = 0, consonants = 0, digits = 0;

    printf("Enter a string: ");
    fgets(str, sizeof(str), stdin);

    for (p = str; *p != '\0'; p++) {     /* traverse via pointer */
        char c = *p;
        if (c >= 'A' && c <= 'Z') c = c + 32;  /* to lowercase */

        if (c == 'a' || c == 'e' || c == 'i' || c == 'o' || c == 'u')
            vowels++;
        else if (c >= 'a' && c <= 'z')
            consonants++;
        else if (c >= '0' && c <= '9')
            digits++;
    }

    printf("Vowels = %d\n", vowels);
    printf("Consonants = %d\n", consonants);
    printf("Digits = %d\n", digits);
    return 0;
}

The loop uses the pointer p (not array indexing) to walk through each character until the null terminator '\0'.

pointersarraysstrings
4long12 marks

(a) Distinguish between a structure and a union in C with respect to memory allocation, giving a suitable example of each. [4]

(b) Define a structure Student containing fields for roll number, name, and marks in three subjects. Write a program that reads records for n students, computes the total and percentage for each, and writes all records to a text file named students.txt. [8]

(a) Structure vs union [4]

Aspectstructunion
MemoryAllocates memory for every member; total size = sum of all members (+ padding)Allocates memory equal to its largest member only; all members share the same memory
MembersAll members can hold values simultaneouslyOnly one member holds a valid value at a time
UseWhen all fields are needed togetherTo save memory when only one field is active at a time
struct S { int i; char c; double d; };  /* size ~ 16 bytes  */
union  U { int i; char c; double d; };  /* size = 8 bytes (largest = double) */

In the union, writing u.i and then reading u.d is invalid because they overlap in the same storage.

(b) Student records to a file [8]

#include <stdio.h>

struct Student {
    int roll;
    char name[50];
    float marks[3];
};

int main(void) {
    int n, i;
    struct Student s;
    FILE *fp;

    printf("Enter number of students: ");
    scanf("%d", &n);

    fp = fopen("students.txt", "w");
    if (fp == NULL) {
        printf("Error opening file!\n");
        return 1;
    }

    fprintf(fp, "Roll\tName\tTotal\tPercentage\n");

    for (i = 0; i < n; i++) {
        float total;
        float percentage;

        printf("\nStudent %d\n", i + 1);
        printf("Roll number: ");
        scanf("%d", &s.roll);
        printf("Name: ");
        scanf("%s", s.name);
        printf("Marks in 3 subjects: ");
        scanf("%f %f %f", &s.marks[0], &s.marks[1], &s.marks[2]);

        total = s.marks[0] + s.marks[1] + s.marks[2];
        percentage = total / 3.0f;

        fprintf(fp, "%d\t%s\t%.2f\t%.2f\n",
                s.roll, s.name, total, percentage);
    }

    fclose(fp);
    printf("\nRecords written to students.txt successfully.\n");
    return 0;
}

Each record's total is the sum of the three marks and percentage is total/3; all records are written to students.txt using fprintf, and the file is closed with fclose.

structuresunionsfile-handling
B

Section B: Short Answer Questions

Attempt all / any as specified.

8 questions
5short6 marks

(a) Differentiate between the increment operators in the expressions x = i++ and x = ++i. [2]

(b) Evaluate the following expression step by step, assuming int a = 5, b = 2, c; and state the final value of c:

c = a + b * 4 / 2 - a % b;

[4]

(a) x = i++ vs x = ++i [2]

  • x = i++ (post-increment): the old value of i is assigned to x first, then i is incremented. If i = 5, then x = 5 and i = 6.
  • x = ++i (pre-increment): i is incremented first, then the new value is assigned to x. If i = 5, then x = 6 and i = 6.

(b) Step-by-step evaluation [4]

Given int a = 5, b = 2; and

c = a + b * 4 / 2 - a % b;

Apply C operator precedence: *, /, % (left to right) before +, -.

  1. b * 4 =2×4=8= 2 \times 4 = 8
  2. 8 / 2 =4= 4 (integer division)
  3. a % b =5%2=1= 5 \% 2 = 1 (remainder)
  4. Expression becomes c = a + 4 - 1 =5+41= 5 + 4 - 1
  5. =8= 8

Final value: c = 8.

operatorsexpressions
6short6 marks

Write a C program using a switch statement that reads a single arithmetic operator (+, -, *, /) and two operands from the user, performs the corresponding operation, and prints the result. Handle the case of division by zero appropriately.

Calculator using switch [6]

#include <stdio.h>

int main(void) {
    char op;
    double a, b;

    printf("Enter an operator (+ - * /): ");
    scanf(" %c", &op);
    printf("Enter two operands: ");
    scanf("%lf %lf", &a, &b);

    switch (op) {
        case '+':
            printf("%.2lf + %.2lf = %.2lf\n", a, b, a + b);
            break;
        case '-':
            printf("%.2lf - %.2lf = %.2lf\n", a, b, a - b);
            break;
        case '*':
            printf("%.2lf * %.2lf = %.2lf\n", a, b, a * b);
            break;
        case '/':
            if (b == 0)
                printf("Error: division by zero is not allowed.\n");
            else
                printf("%.2lf / %.2lf = %.2lf\n", a, b, a / b);
            break;
        default:
            printf("Invalid operator!\n");
    }
    return 0;
}

Note the leading space in " %c" to skip whitespace, the break after every case, the division-by-zero check, and the default case for invalid operators.

control-statements
7short6 marks

Write a C program that reads n integers into a one-dimensional array and finds the largest and smallest elements without using any built-in library functions.

Largest and smallest element in an array [6]

#include <stdio.h>

int main(void) {
    int n, i;
    int arr[100];
    int max, min;

    printf("Enter number of elements: ");
    scanf("%d", &n);

    printf("Enter %d integers:\n", n);
    for (i = 0; i < n; i++)
        scanf("%d", &arr[i]);

    max = min = arr[0];          /* assume first element is both */

    for (i = 1; i < n; i++) {
        if (arr[i] > max)
            max = arr[i];
        if (arr[i] < min)
            min = arr[i];
    }

    printf("Largest  = %d\n", max);
    printf("Smallest = %d\n", min);
    return 0;
}

Logic: initialise both max and min to the first element, then scan the rest of the array, updating max whenever a larger value is found and min whenever a smaller value is found. No library functions are used.

arrayscontrol-statements
8short6 marks

Write a C program to check whether a string entered by the user is a palindrome or not (for example, madam is a palindrome). You may use standard string library functions where appropriate.

Palindrome check [6]

A string is a palindrome if it reads the same forwards and backwards (e.g. madam, level).

#include <stdio.h>
#include <string.h>

int main(void) {
    char str[100];
    int i, len, isPalindrome = 1;

    printf("Enter a string: ");
    scanf("%s", str);

    len = strlen(str);

    for (i = 0; i < len / 2; i++) {
        if (str[i] != str[len - 1 - i]) {
            isPalindrome = 0;
            break;
        }
    }

    if (isPalindrome)
        printf("\"%s\" is a palindrome.\n", str);
    else
        printf("\"%s\" is NOT a palindrome.\n", str);
    return 0;
}

Logic: compare the character at position i from the front with the character at position len-1-i from the back. If any pair differs, the string is not a palindrome; only the first half (len/2 comparisons) needs to be checked.

stringsarrays
9short6 marks

(a) What is a dangling pointer? How does it arise? [2]

(b) Explain the use of the functions malloc() and free() for dynamic memory allocation, and write a code fragment that dynamically allocates an array of n integers. [4]

(a) Dangling pointer [2]

A dangling pointer is a pointer that still holds the address of a memory location that has been freed or has gone out of scope, so it points to memory that is no longer valid.

It typically arises when:

  • memory is released with free(p) but p is still used afterwards;
  • a function returns the address of one of its local (automatic) variables, which is destroyed when the function returns;
  • a pointer points to a block whose lifetime has ended.

Dereferencing a dangling pointer is undefined behaviour. (Setting p = NULL after free avoids it.)

(b) malloc() and free() [4]

  • malloc(size) — declared in <stdlib.h>, it allocates size bytes from the heap at run time and returns a void* to the first byte (or NULL if allocation fails). The memory is uninitialised.
  • free(ptr) — returns a previously allocated block back to the heap so it can be reused, preventing memory leaks. Every successful malloc should be matched by exactly one free.
#include <stdlib.h>

int n;
int *arr;

scanf("%d", &n);
arr = (int *) malloc(n * sizeof(int));  /* allocate array of n ints */
if (arr == NULL) {
    printf("Memory allocation failed!\n");
    return 1;
}

/* ... use arr[0] .. arr[n-1] ... */

free(arr);     /* release the memory */
arr = NULL;    /* avoid dangling pointer */
pointersfunctions
10short6 marks

(a) List the different file opening modes (r, w, a, etc.) available in C and state the purpose of each. [3]

(b) Write a C program that opens an existing text file in read mode and counts the total number of characters and lines in it. [3]

(a) File opening modes [3]

ModePurpose
"r"Open an existing text file for reading. Fails (returns NULL) if the file does not exist.
"w"Open for writing. Creates the file if absent; truncates (erases) existing contents.
"a"Open for appending. Creates the file if absent; writes are added at the end, keeping existing data.
"r+"Open existing file for reading and writing.
"w+"Create/truncate for reading and writing.
"a+"Open/create for reading and appending.

Appending b (e.g. "rb", "wb") opens the file in binary mode.

(b) Count characters and lines in a file [3]

#include <stdio.h>

int main(void) {
    FILE *fp;
    int ch;
    int chars = 0, lines = 0;

    fp = fopen("input.txt", "r");
    if (fp == NULL) {
        printf("Cannot open file!\n");
        return 1;
    }

    while ((ch = fgetc(fp)) != EOF) {
        chars++;
        if (ch == '\n')
            lines++;
    }

    fclose(fp);

    printf("Total characters = %d\n", chars);
    printf("Total lines = %d\n", lines);
    return 0;
}

The program reads one character at a time with fgetc until EOF, counting every character and incrementing the line count at each newline '\n'.

file-handling
11short6 marks

(a) Differentiate between #define and const for defining constants in C. [2]

(b) What is type conversion? Distinguish between implicit type conversion and explicit type casting with an example of each. [4]

(a) #define vs const [2]

#define PI 3.14const float PI = 3.14;
Preprocessor directive — simple text substitution before compilationA real variable with a type, processed by the compiler
No data type, no type checkingHas a type, so the compiler performs type checking
Occupies no memory of its own (text is replaced inline)Occupies memory like a normal variable
No scope rules (replaced everywhere after definition)Obeys normal scope rules (block/file)

(b) Type conversion [4]

Type conversion is the process of converting a value from one data type to another.

  • Implicit type conversion (type promotion): done automatically by the compiler when operands of different types are mixed; the smaller type is promoted to the larger to avoid loss of data.
int   i = 5;
float f = i + 2.5;   /* i is promoted int -> float; f = 7.5 */
  • Explicit type casting: done manually by the programmer using the cast operator (type) to force a conversion.
float avg = (float) total / n;   /* force float division */
int   x   = (int) 3.99;          /* x = 3, fractional part truncated */

Implicit conversion happens by itself; explicit casting is requested by the programmer and may cause deliberate truncation/loss.

data-typesoperators
12short8 marks

(a) Differentiate between break and continue statements with a short example showing the effect of each inside a loop. [4]

(b) Write a user-defined function isPrime(int n) that returns 1 if n is prime and 0 otherwise, and use it in main() to print all prime numbers between 1 and 50. [4]

(a) break vs continue [4]

  • break — immediately terminates the nearest enclosing loop (or switch); control jumps to the statement after the loop.
  • continueskips the rest of the current iteration and jumps to the loop's next iteration (condition/update); the loop is not terminated.
for (i = 1; i <= 5; i++) {
    if (i == 3) break;       /* prints 1 2, then stops */
    printf("%d ", i);
}
/* Output: 1 2 */

for (i = 1; i <= 5; i++) {
    if (i == 3) continue;    /* skips 3 only */
    printf("%d ", i);
}
/* Output: 1 2 4 5 */

(b) isPrime function and primes 1–50 [4]

#include <stdio.h>

int isPrime(int n) {
    int i;
    if (n < 2)                 /* 0 and 1 are not prime */
        return 0;
    for (i = 2; i * i <= n; i++) {
        if (n % i == 0)
            return 0;          /* found a divisor -> not prime */
    }
    return 1;                  /* no divisor -> prime */
}

int main(void) {
    int num;
    printf("Prime numbers between 1 and 50:\n");
    for (num = 1; num <= 50; num++) {
        if (isPrime(num))
            printf("%d ", num);
    }
    printf("\n");
    return 0;
}

Output: 2 3 5 7 11 13 17 19 23 29 31 37 41 43 47.

The function checks divisibility only up to n\sqrt{n} (i*i <= n), which is sufficient to determine primality.

control-statementsfunctions

Frequently asked questions

Where can I find the BE Computer Engineering (IOE, TU) Computer Programming in C (IOE, CT 401) question paper 2079?
The full BE Computer Engineering (IOE, TU) Computer Programming in C (IOE, CT 401) 2079 (regular) question paper is available free on Kekkei. You can read every question online and attempt the paper under timed exam conditions.
Does the Computer Programming in C (IOE, CT 401) 2079 paper come with solutions?
Yes. Every question on this Computer Programming in C (IOE, CT 401) past paper includes a step-by-step solution, plus instant AI feedback when you attempt it on Kekkei.
How many marks is the BE Computer Engineering (IOE, TU) Computer Programming in C (IOE, CT 401) 2079 paper?
The BE Computer Engineering (IOE, TU) Computer Programming in C (IOE, CT 401) 2079 paper carries 80 full marks and is meant to be completed in 180 minutes, across 12 questions.
Is practising this Computer Programming in C (IOE, CT 401) past paper free?
Yes — reading and attempting this Computer Programming in C (IOE, CT 401) past paper on Kekkei is completely free.