Purdue CS24000 Fall 2018 Midterm I Solutions

Purdue University CS24000 is an undergraduate-level course that teaches students programming principles and techniques for problem-solving in the C programming language. Here are the solution and study notes for the Fall 2018 Midterm 1 exam.

CS24000 Syllabus

Below are extracted from the Spring 2024 CS24000 course syllabus:

Disclosure: This blog site is reader-supported. When you buy through the affiliate links below, as an Amazon Associate, I earn a tiny commission from qualifying purchases. Thank you.

  • Reference: Beej’s Guide to C Programming; Brian “Beej” Hall; 2007
  • Course Outcomes: A student who successfully fulfills the course requirements will have the ability to:
    • write quality code that is readable, maintainable, and well commented
    • create, compile, and execute C programs using industry standard tools including the GNU Compiler Collection
    • apply debugging techniques to analyze, identify, and fix errors
    • assess and address security-related issues in code bases written in C
    • produce code that appropriately and properly utilizes pointers
    • solve problems through the application of explicit memory management
    • design and implement programs in C that utilize dynamic data structures such as linked lists and trees
  • Lectures:

Fall 2018 Midterm 1 Exam

Exam Solutions and Notes

Problem 1 (20 pts)

  • (a) gcc -Wall -Werror -g -c abc.c -o xyz.o
    Explanation of the options used:

    • -Wall: Enable all warnings.
    • -Werror: Treat warnings as errors.
    • -g: Include debugging information in the output file.
    • -c: Compile or assemble the source files, but do not link.
    • abc.c: The source file to be compiled.
    • -o xyz.o: Specify the output file name (xyz.o).

    📝Notes: This output file xyz.o is not executable since it is just the object file for a single c source file. We need to link to the standard library to make a executable file. If we force to run this xyz.o, it will return something like exec format error.

  • (b) gcc xyz.o abc.o def.c -o prog
    Explanation:

    • xyz.o, abc.o: Object files to be linked.
    • def.c: Source file to be compiled and linked.
    • -o prog: Specify the output file name (prog).
  • (c) It advises gcc to include all warnings that help detect potentially problematic code.

  • (d) Many functions found in the string library (declared in string.h) rely on null-terminated strings to operate correctly. Null-terminated strings are sequences of characters followed by a null character ('\0'), which indicates the end of the string. Functions like strlen, strcpy, strcat, strcmp, and others expect null-terminated strings as input and produce null-terminated strings as output.

  • (e) In C, memory for a variable is allocated during its definition, not during its declaration.

    Declaration is announcing the properties of variable (no memory allocation), definition is allocating storages for a variable. Put pure declaration (struct, func prototype, extern) outside of the func, put definition inside func.

  • (f) size = 32 (There are 8 integer elements in this array, so 4 * 8.)

  • (g) 5 (Because ptr is given the address of the 3rd element. So *(ptr - 1) is the value of the 2nd element.)

  • (h) 12 (This is equal to *(ptr - *(ptr + 3)), then *(ptr - 2). So finally it points to the 1st element of the array.)

  • (i) 8 (Because it mentions "64-bit architecture", so all addresses are of size 64-bit)

Problem 2 (20 pts)

  • (a) The answer is shown below: (remember to define ID_LEN first and add ';' after the '}')

    1
    2
    3
    4
    5
    6
    7
    #define ID_LEN (5)

    struct resistor {
    char id[ID_LEN];
    float max_power;
    int resistance;
    };

  • (b) The answer is shown below:

    1
    typedef struct resistor resistor_t;

  • (c) The answer is shown below: (remember to define ID_LEN first and add ';' after the '}')

    1
    2
    3
    4
    5
    6
    #define CNAME_LEN (24)

    struct circuit_struct {
    char name[CNAME_LEN];
    resistor_t resistors[10];
    };

  • (d) It will print sizeof = 920. Explanation: 5 * (24 + 10 * (8 + 4 + 4)) = 920. This is because the id inside the resistor will occupy 8 bytes after padding to a multiple of 4.

    1
    struct circuit_struct circuit_board[5];

  • (e) The function can be written like the following:

    1
    2
    3
    int find_voltage(resistor_t r, int c) {
    return (c * r.resistance);
    }

Problem 3 (40 pts)

The complete program is shown below

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
#include <stdio.h>

#define ID_LEN 5
#define CNAME_LEN 24

struct resistor {
char id[ID_LEN];
float max_power;
int resistance;
};

typedef struct resistor resistor_t;

struct circuit_struct {
char name[CNAME_LEN];
resistor_t resistors[10];
};

int blown_resistors(char* infile, char* outfile, float voltage) {

FILE *in = fopen(infile, "r");
if(!in) return -1;

FILE *out = fopen(outfile, "w");
if(!out) {
fclose(in);
in = NULL;
return -1;
}

// First pass - calculate total resistance
int total_resistance = 0;
int items;
char id[ID_LEN];
int resistance;
float max_power;

fseek(in, 0, SEEK_SET);

while (fscanf(in, "%[^,],%d,%f\n", id, &resistance, &max_power) == 3) {
total_resistance += resistance;
}

if (!feof(in)) {
// Input format error
fclose(in);
in = NULL;
fclose(out);
out = NULL;
return -1;
}

// Calculate current
float current = voltage / total_resistance;

// Second pass - check for blown resistors
int blown_count = 0;

fseek(in, 0, SEEK_SET);

while (fscanf(in, "%[^,],%d,%f\n", id, &resistance, &max_power) == 3) {
float power = current * current * resistance;
if (power > max_power) {
blown_count++;
fprintf(out, "%s, %.2f\n", id, power);
}
}

fclose(in);
in = NULL;
fclose(out);
out = NULL;

return blown_count;
}

int main(void) {
printf("return is %d\n", blown_resistors("input", "output", 100));
return 0;
}

Problem 4 (20 pts)

The solution can be like this: (the include and struct definition are not necessary)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
#include <stdio.h>

struct coord {
float x;
float y;
};

struct coord find_center(FILE *file_ptr) {
struct coord center = {0.0, 0.0};
struct coord temp;
int count = 0;

if (file_ptr == NULL) {
fprintf(stderr, "Error: NULL file pointer\n");
return center;
}

// Set file position indicator to the beginning
rewind(file_ptr);

while (fread(&temp, sizeof(struct coord), 1, file_ptr) == 1) {
center.x += temp.x;
center.y += temp.y;
count++;
}

if (count > 0) {
center.x /= count;
center.y /= count;
}

return center;
}