Browse papers
A

Section A: Long Answer Questions

Attempt all / any as specified.

4 questions
1long12 marks

(a) Explain the basic structure of a C program with the help of a suitable example, clearly identifying the preprocessor directives, the main() function, declaration section and the executable statements. (6)

(b) Differentiate between the following pairs of data types in C, stating the typical size and range of each on a 32-bit system: (i) int vs unsigned int and (ii) float vs double. Explain what is meant by type conversion and distinguish between implicit and explicit (type-casting) conversion with one example each. (6)

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

Every C program is built from a few well-defined sections. A minimal example:

#include <stdio.h>          /* 1. Preprocessor directive */
#define PI 3.14159          /* symbolic constant */

int main(void)              /* 2. main() function  */
{
    float r, area;          /* 3. Declaration section */

    printf("Enter radius: "); /* 4. Executable statements */
    scanf("%f", &r);
    area = PI * r * r;
    printf("Area = %f\n", area);

    return 0;               /* return value to OS */
}
  • Preprocessor directives (#include, #define): processed before compilation. #include <stdio.h> pulls in the standard I/O header so printf/scanf can be used; #define creates symbolic constants/macros.
  • main() function: the entry point where execution begins. Every C program must have exactly one main().
  • Declaration section: variables (e.g. float r, area;) are declared with their data types before use.
  • Executable statements: the actual instructions (input, processing, output) ending with return 0; which signals successful termination.

(b) Data types, sizes and type conversion (6)

(i) int vs unsigned int (typically 4 bytes / 32 bits each):

TypeSizeRange
int4 bytes231-2^{31} to 23112^{31}-1 = 2147483648-2147483648 to 21474836472147483647
unsigned int4 bytes00 to 23212^{32}-1 = 00 to 42949672954294967295

int is signed (stores negatives using the sign bit); unsigned int has no sign bit, so all bits represent magnitude, doubling the positive range.

(ii) float vs double:

TypeSizeRange (approx.)Precision
float4 bytes±3.4×1038\pm 3.4 \times 10^{38}~6–7 digits
double8 bytes±1.7×10308\pm 1.7 \times 10^{308}~15–16 digits

double (double precision) stores more bits, giving greater range and accuracy than float (single precision).

Type conversion means converting a value of one data type into another.

  • Implicit conversion (type promotion): done automatically by the compiler, usually from a lower to a higher type to avoid data loss.
    int i = 5; float f;
    f = i + 2.5;   /* i promoted to float automatically -> 7.5 */
    
  • Explicit conversion (type casting): done manually by the programmer using a cast operator (type).
    float x = 7.9;
    int y = (int)x;  /* x explicitly cast to int -> 7 (fraction dropped) */
    
program-structuredata-typesoperators
2long14 marks

(a) What is recursion? Differentiate between recursion and iteration in terms of memory usage and execution speed. (4)

(b) Write a C program using a recursive function to compute the factorial of a non-negative integer n entered by the user. Show how the recursive calls are placed on and removed from the stack for the input n = 4. (6)

(c) Explain call by value and call by reference with a C example of a swap() function for each, and state which one actually exchanges the values of the caller's variables and why. (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 sub-problems, until a base case stops the calls.

AspectRecursionIteration
Memory usageHigh — each call pushes a new stack frame (parameters, locals, return address)Low — uses a single set of variables
Execution speedSlower — overhead of function calls and stack managementFaster — no call overhead
RiskStack overflow if too deepNo such risk
CodeCompact, elegantOften longer but efficient

(b) Recursive factorial + stack trace (6)

#include <stdio.h>

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

int main(void) {
    int n;
    printf("Enter a non-negative integer: ");
    scanf("%d", &n);
    printf("%d! = %ld\n", n, factorial(n));
    return 0;
}

Stack behaviour for n = 4 — calls are pushed until the base case, then popped as they return:

Pushing (winding):

factorial(4) -> 4 * factorial(3)
factorial(3) -> 3 * factorial(2)
factorial(2) -> 2 * factorial(1)
factorial(1) -> 1            (base case reached)

Popping (unwinding) — each frame returns its result to the one below it:

factorial(1) returns 1
factorial(2) returns 2 * 1  = 2
factorial(3) returns 3 * 2  = 6
factorial(4) returns 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; changes inside the function do not affect the caller's variables.

void swap(int x, int y) {       /* copies */
    int t = x; x = y; y = t;
}                                /* a, b in main remain unchanged */

Call by reference: the addresses of the variables are passed (via pointers); the function works on the originals.

void swap(int *x, int *y) {      /* addresses */
    int t = *x; *x = *y; *y = t;
}
int main(void){ int a=3,b=5; swap(&a,&b); /* now a=5, b=3 */ }

Call by reference actually exchanges the caller's values, because the function dereferences the passed addresses and modifies the original memory locations, whereas call by value only modifies local copies.

functionsrecursioncontrol-flow
3long14 marks

(a) What is a pointer? Explain the & (address-of) and * (dereference) operators with a short program that prints the address and value of a variable using a pointer. (5)

(b) Explain the relationship between arrays and pointers in C. Given the declaration int a[5];, show how a[i] can be accessed using pointer notation. (4)

(c) Describe the use of the functions malloc(), calloc(), realloc() and free() for dynamic memory management. Write a C program that dynamically allocates memory for n integers, reads them, and prints their sum. (5)

(a) Pointers and the & / * operators (5)

A pointer is a variable that stores the memory address of another variable rather than a data value itself.

  • & (address-of) gives the memory address of a variable.
  • * (dereference / indirection) accesses the value stored at the address held by a pointer.
#include <stdio.h>
int main(void) {
    int x = 10;
    int *p = &x;          /* p holds the address of x */
    printf("Address of x : %p\n", (void*)p);   /* same as &x */
    printf("Value of x   : %d\n", *p);          /* dereference -> 10 */
    return 0;
}

(b) Arrays and pointers (4)

In C, an array name acts as a constant pointer to its first element: a is equivalent to &a[0]. Pointer arithmetic accounts for element size, so a + i points to element i.

For int a[5];, element a[i] can be accessed equivalently as:

a[i](a+i)(p+i)where p=aa[i] \equiv *(a + i) \equiv *(p + i) \quad \text{where } p = a
int a[5] = {10,20,30,40,50};
int *p = a;
printf("%d", a[2]);     /* 30 */
printf("%d", *(a + 2)); /* 30 */
printf("%d", *(p + 2)); /* 30 */

Thus a[i], *(a+i), *(p+i) and p[i] are all equivalent.

(c) Dynamic memory management (5)

  • malloc(size) — allocates a block of size bytes; memory is uninitialised (garbage). Returns void* or NULL on failure.
  • calloc(n, size) — allocates memory for n elements of size bytes each and initialises all bytes to zero.
  • realloc(ptr, newsize) — resizes a previously allocated block to newsize bytes, preserving existing data.
  • free(ptr) — releases memory previously allocated, preventing memory leaks.
#include <stdio.h>
#include <stdlib.h>
int main(void) {
    int n, i, sum = 0;
    printf("Enter n: ");
    scanf("%d", &n);

    int *arr = (int*)malloc(n * sizeof(int));
    if (arr == NULL) { printf("Allocation failed\n"); return 1; }

    for (i = 0; i < n; i++) {
        scanf("%d", &arr[i]);
        sum += arr[i];
    }
    printf("Sum = %d\n", sum);

    free(arr);   /* release memory */
    return 0;
}
pointersdynamic-memoryarrays
4long10 marks

(a) Define a structure Student containing the members roll (integer), name (character array) and marks (float). Write a C program that reads the records of n students and writes them to a file named students.dat, then reads the records back from the file and displays them. (7)

(b) Differentiate between a structure and a union in C with respect to memory allocation, using a suitable example. (3)

(a) Student structure with file I/O (7)

#include <stdio.h>

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

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

    printf("How many students? ");
    scanf("%d", &n);

    /* ---- write records to file ---- */
    fp = fopen("students.dat", "wb");
    if (fp == NULL) { printf("Cannot open file\n"); return 1; }
    for (i = 0; i < n; i++) {
        printf("Roll, Name, Marks: ");
        scanf("%d %s %f", &s.roll, s.name, &s.marks);
        fwrite(&s, sizeof(struct Student), 1, fp);
    }
    fclose(fp);

    /* ---- read records back and display ---- */
    fp = fopen("students.dat", "rb");
    if (fp == NULL) { printf("Cannot open file\n"); return 1; }
    printf("\nRoll\tName\tMarks\n");
    while (fread(&s, sizeof(struct Student), 1, fp) == 1) {
        printf("%d\t%s\t%.2f\n", s.roll, s.name, s.marks);
    }
    fclose(fp);
    return 0;
}

The records are written in binary mode with fwrite() and read back with fread() until end of file.

(b) Structure vs Union (3)

Aspectstructunion
MemoryAllocates separate memory for every member; total size = sum of member sizes (plus padding)Allocates memory equal to the size of its largest member; all members share it
AccessAll members hold valid values simultaneouslyOnly one member holds a valid value at a time
struct S { int a; char b; float c; };  /* size ~ 12 bytes */
union  U { int a; char b; float c; };  /* size = 4 bytes (largest) */

In a union, writing to one member overwrites the others because they occupy the same memory location, so unions save memory when only one member is needed at a time.

structuresunionsfile-handling
B

Section B: Short Answer Questions

Attempt all / any as specified.

8 questions
5short6 marks

Differentiate between while and do-while loops. Write a C program using a loop to check whether a given integer is a prime number.

while vs do-while

while loopdo-while loop
Entry-controlled — condition tested before the bodyExit-controlled — condition tested after the body
Body may execute zero times if the condition is false initiallyBody always executes at least once
Syntax: while(cond){ ... }Syntax: do{ ... }while(cond);

C program to check whether a number is prime

#include <stdio.h>
int main(void) {
    int n, i, isPrime = 1;
    printf("Enter an integer: ");
    scanf("%d", &n);

    if (n <= 1)
        isPrime = 0;
    else {
        for (i = 2; i <= n / 2; i++) {
            if (n % i == 0) { isPrime = 0; break; }
        }
    }

    if (isPrime) printf("%d is a prime number\n", n);
    else         printf("%d is not a prime number\n", n);
    return 0;
}

A number n>1n>1 is prime if it is not divisible by any integer from 22 to n/2n/2.

control-flowloops
6short6 marks

Evaluate the following C expressions, given int a = 5, b = 2, c; and state the value of the result and of any modified variable in each case:

(a) c = a++ + ++b;

(b) c = a % b + a / b;

(c) c = (a > b) ? a : b;

Also explain the difference between the = and == operators.

Given int a = 5, b = 2, c; (each part evaluated independently from these initial values):

(a) c = a++ + ++b;

  • a++ is post-increment: uses 5, then a becomes 6.
  • ++b is pre-increment: b becomes 3, value used is 3.
  • c=5+3=8c = 5 + 3 = 8.
  • Result: c = 8, a = 6, b = 3.

(b) c = a % b + a / b; (with a = 5, b = 2)

  • a % b = 5mod2=15 \bmod 2 = 1 (remainder).
  • a / b = 5/2=25 / 2 = 2 (integer division).
  • c=1+2=3c = 1 + 2 = 3.
  • Result: c = 3.

(c) c = (a > b) ? a : b; (with a = 5, b = 2)

  • Condition a > b i.e. 5 > 2 is true, so the value before : (a) is chosen.
  • Result: c = 5.

= vs ==

  • = is the assignment operator: it stores the value on its right into the variable on its left, e.g. x = 5.
  • == is the equality (relational) operator: it compares two operands and yields 1 (true) or 0 (false), e.g. x == 5.

Using = where == is intended (e.g. if (x = 5)) is a common bug — it assigns instead of comparing and the condition becomes true for any non-zero value.

operatorsexpressions
7short6 marks

Write a C program that reads a string from the user and counts the number of vowels, consonants and spaces in it without using any built-in string library function.

C program to count vowels, consonants and spaces (no string library)

#include <stdio.h>
int main(void) {
    char str[200], ch;
    int i = 0, vowels = 0, consonants = 0, spaces = 0;

    printf("Enter a string: ");
    fgets(str, sizeof(str), stdin);   /* reads line incl. spaces */

    for (i = 0; str[i] != '\0'; i++) {
        ch = str[i];
        /* convert uppercase to lowercase manually */
        if (ch >= 'A' && ch <= 'Z')
            ch = ch + 32;

        if (ch == 'a' || ch == 'e' || ch == 'i' ||
            ch == 'o' || ch == 'u')
            vowels++;
        else if (ch >= 'a' && ch <= 'z')
            consonants++;
        else if (ch == ' ')
            spaces++;
    }

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

The loop walks the array until the null terminator '\0'. Each character is classified using ASCII range checks only (no strlen, isalpha, etc.). Uppercase letters are folded to lowercase by adding 32 so a single set of comparisons suffices.

arraysstrings
8short6 marks

Write a C program to find the largest and the second largest element in a one-dimensional array of n integers entered by the user.

C program to find largest and second largest elements

#include <stdio.h>
#include <limits.h>
int main(void) {
    int n, i, a[100];
    int largest = INT_MIN, second = INT_MIN;

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

    for (i = 0; i < n; i++) {
        if (a[i] > largest) {
            second  = largest;   /* old largest becomes second */
            largest = a[i];
        } else if (a[i] > second && a[i] != largest) {
            second = a[i];
        }
    }

    printf("Largest        = %d\n", largest);
    if (second == INT_MIN)
        printf("No distinct second largest element\n");
    else
        printf("Second largest = %d\n", second);
    return 0;
}

The array is scanned once. Whenever a new maximum is found, the previous maximum slides down to second; otherwise an element larger than second (but not equal to the largest) updates second. This single-pass approach runs in O(n)O(n) time.

arrays
9short6 marks

Differentiate between the break and continue statements with a suitable example of each. Write a C program using nested loops to print the following pattern:

1
1 2
1 2 3
1 2 3 4

break vs continue

  • break immediately terminates the nearest enclosing loop (or switch) and transfers control to the statement after it.
    for (i = 1; i <= 10; i++) {
        if (i == 5) break;   /* loop stops at 5; prints 1 2 3 4 */
        printf("%d ", i);
    }
    
  • continue skips the rest of the current iteration and jumps to the loop's next iteration (condition/update).
    for (i = 1; i <= 5; i++) {
        if (i == 3) continue;  /* skips 3; prints 1 2 4 5 */
        printf("%d ", i);
    }
    

C program to print the pattern

#include <stdio.h>
int main(void) {
    int i, j;
    for (i = 1; i <= 4; i++) {          /* one row per i */
        for (j = 1; j <= i; j++)        /* print 1..i */
            printf("%d ", j);
        printf("\n");
    }
    return 0;
}

Output:

1
1 2
1 2 3
1 2 3 4

The outer loop controls the row number, and the inner loop prints numbers 1 to i on that row.

control-flowloops
10short6 marks

Explain how a two-dimensional array is stored in memory in C (row-major order). Write a C program to read a 3 x 3 matrix and find the sum of its diagonal elements.

Storage of a 2-D array (row-major order)

C stores a two-dimensional array in row-major order: the elements of the first row are stored contiguously, followed by the second row, and so on (memory is one-dimensional). For an array int a[R][C], the address of element a[i][j] is:

address(a[i][j])=base+(i×C+j)×sizeof(int)\text{address}(a[i][j]) = \text{base} + (i \times C + j) \times \text{sizeof(int)}

Example for int a[2][3] — storage order is: a[0][0], a[0][1], a[0][2], a[1][0], a[1][1], a[1][2].

C program: sum of diagonal elements of a 3 x 3 matrix

#include <stdio.h>
int main(void) {
    int a[3][3], i, j, sum = 0;

    printf("Enter 9 elements of 3x3 matrix:\n");
    for (i = 0; i < 3; i++)
        for (j = 0; j < 3; j++)
            scanf("%d", &a[i][j]);

    for (i = 0; i < 3; i++)
        sum += a[i][i];      /* main diagonal: row index == column index */

    printf("Sum of main diagonal = %d\n", sum);
    return 0;
}

The main-diagonal elements are those where the row index equals the column index, i.e. a[0][0], a[1][1], a[2][2].

stringsarrays
11short4 marks

List the different file opening modes in C (r, w, a, r+, w+, a+) and explain the purpose of each. State the difference between a text file and a binary file.

File opening modes in C

ModePurpose
rOpen an existing file for reading only. Fails (returns NULL) if the file does not exist.
wOpen for writing. Creates the file if absent; if it exists, its contents are truncated (erased).
aOpen for appending. Writes are added at the end; file created if absent; existing data preserved.
r+Open existing file for reading and writing. File must already exist; contents not erased.
w+Open for reading and writing; creates/truncates the file (existing contents lost).
a+Open for reading and appending; created if absent, writes always go to the end.

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

Text file vs Binary file

Text fileBinary file
Stores data as human-readable characters (ASCII)Stores data in the same internal byte format as in memory
Newlines may be translated (e.g. \n\r\n)No character translation occurs
Numbers stored as digit charactersNumbers stored as raw bytes (e.g. 4-byte int)
Read/written with fprintf, fscanf, fgetsRead/written with fwrite, fread
file-handling
12short6 marks

Write short notes on any THREE of the following:

(a) Storage classes in C (auto, register, static, extern)

(b) The C preprocessor and #define macros

(c) Difference between getchar()/putchar() and scanf()/printf()

(d) Enumerated data type (enum)

Short notes on any THREE:

(a) Storage classes in C

A storage class defines a variable's scope, lifetime, default initial value and storage location.

  • auto — default for local variables; scope is local to the block, lifetime ends when the block exits, stored in stack, garbage initial value.
  • register — requests the variable be stored in a CPU register for faster access (e.g. loop counters); & (address) cannot be taken.
  • static — preserves a local variable's value between function calls (lifetime = whole program); initialised once to 0 by default; scope still local.
  • extern — declares a global variable defined in another file/translation unit, giving it external linkage so it can be shared across files.

(b) The C preprocessor and #define macros

The preprocessor runs before compilation and handles all lines beginning with #. #include inserts header files and #define creates macros. A #define macro performs simple textual substitution:

#define PI 3.14159          /* object-like (symbolic constant) */
#define SQ(x) ((x)*(x))     /* function-like macro */
area = PI * SQ(r);          /* expands to ((r)*(r)) */

Macros have no type checking and are not actual functions; parentheses are used to avoid precedence errors.

(c) getchar()/putchar() vs scanf()/printf()

  • getchar() / putchar() read/write a single character at a time from/to standard I/O; they are simple and fast for character processing.
  • scanf() / printf() are formatted I/O functions that handle multiple values of different data types using format specifiers (%d, %f, %s, …). They are more flexible but heavier than the single-character functions.

(d) Enumerated data type (enum)

An enum defines a user-defined type whose values are named integer constants, improving readability.

enum Weekday { MON, TUE, WED, THU, FRI };  /* MON=0, TUE=1, ... */
enum Weekday today = WED;   /* today holds 2 */

By default the first constant is 0 and each subsequent one increases by 1; values may also be assigned explicitly (e.g. enum {LOW=1, HIGH=10};).

preprocessorprogram-structurefunctions

Frequently asked questions

Where can I find the BE Computer Engineering (Pokhara University) Programming in C (PU, CMP 124) question paper 2079?
The full BE Computer Engineering (Pokhara University) Programming in C (PU, CMP 124) 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 Programming in C (PU, CMP 124) 2079 paper come with solutions?
Yes. Every question on this Programming in C (PU, CMP 124) 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 (Pokhara University) Programming in C (PU, CMP 124) 2079 paper?
The BE Computer Engineering (Pokhara University) Programming in C (PU, CMP 124) 2079 paper carries 100 full marks and is meant to be completed in 180 minutes, across 12 questions.
Is practising this Programming in C (PU, CMP 124) past paper free?
Yes — reading and attempting this Programming in C (PU, CMP 124) past paper on Kekkei is completely free.