p. 2 of 9 Q1. [5 marks] The following program compiles and runs with no problems. Indicate what the output of the program is going to be (no explanation necessary). 1 #include <stdio.h> 2 main() { 3 int i; int j; 4 int *p; int *q; 5 6 p = &i; 7 q = &j; 8 i = 1; 9 j = 2; 10 p = q; 11 *q = 3; 12 printf("%d %d %d %d\n", i, j, *p, *q); 13 } The output will be: 1 3 3 3. 5 marks all or nothing.
p. 3 of 9 Q2. [10 marks] The following program compiles and runs with no problems. Indicate what the output will be if the input is the number 1. Explain why. 1 #include <stdio.h> 2 #define clone(x) x;x 3 #define remove 4 main() 5 { 6 int i; 7 scanf("%d",&i); 8 clone(i++); 9 switch (i) 10 { 11 case 1: printf("one\n"); 12 case 2: printf("two\n"); 13 #ifdef remove 14 case 3: printf("three\n"); 15 #endif 16 default: printf("other\n"); 17 } 18 } The output will be: THREE OTHER clone(i++); will expand to i++;i++;. statement will be 3. As a result, the value of i at the switch Since remove is defined, the preprocessor directives do not have any effect. As a result, the code after case 3 will execute. Since there is no break;, the code after default will execute as well. No marks if there is no explanation. Partial marks for correct output with incomplete explanation. Even less partial marks for incorrect output, but partially correct explanation.
p. 4 of 9 Q3. [15 marks] The following program attempts to read a string, save it in memory, and then reproduce it on the screen. It compiles with no problems. However, when run it produces a segmentation fault. Your task is to: (a) Explain the reason for the segmentation fault. (b) Describe how you would fix the problem. 1 #include <stdio.h> 2 #include <stdlib.h> 3 4 void allocate(char* p) { 5 p = (char *) malloc (30 * sizeof(char)); 6 } 7 8 int main() 9 { 10 int i; 11 char *str; 12 allocate(str); 13 for (i = 0; i < 20; i++) str[i] = getchar(); 14 str[20] = \0 ; 15 printf("%s", str); 16 } The reason for the segmentation fault is that the str pointer does not point to allocated memory, so even after only one character is entered there will be a segmentation fault in line 13. The allocate function appears to perform the necessary memory allocation. However, due to call-by-value, it only has a copy of the str pointer, and it cannot change where it points to. As a result, the allocated memory becomes garbage as soon the execution of the allocate function finishes. The problem can be fixed by either inlining the allocate function, i.e. copying its code to the main function, or by passing a char ** to it, such as &str. 10 marks for a correct explanation of the problem, 5 marks for the fix. Partial marks are possible if the explanation is incomplete but hints at an understanding of the problem.
p. 5 of 9 Q4. [20 marks] The following program attempts to read 40 lines of text, where each line is guaranteed to be exactly 20 characters (including the newline). It compiles with no errors, but produces a segmentation fault when run because it has not allocated any memory. In your answer, indicate what lines of code you would add and where to fix this problem. For example, say something like: I would add the line i++; between lines 9 and 10. 1 #include <stdio.h> 2 #include <stdlib.h> 3 #define LINESNO 40 4 #define CHARNO 20 5 6 int main() 7 { 8 int i,j; 9 char **lines; 10 for (i = 0; i < LINESNO; i++) 11 { 12 char *line = lines[i]; 13 for (j = 0; j < CHARNO; j++) line[j] = getchar(); 14 line[charno] = \0 ; 15 } 16 for (i = 0; i < LINESNO; i++) printf("%s", lines[i]); 17 } The lines string array must be allocated by adding the following line between lines 9 and 10: lines = (char **) malloc (LINESNO * sizeof(char *)); Each string must also be allocated. This can be done by adding the following line between lines 11 and 12: lines[i] = (char *) malloc ((CHARNO + 1) * sizeof(char)); The + 1 in the above line is to ensure enough room for the null character. 10 marks for each added line. Other ways to allocate the memory may be possible and should receive full marks if correct. Partial marks are possible for incorrect solutions that demonstrate an understanding of the issue at hand. No marks for changing the program to use arrays.
p. 6 of 9 Q5. [20 marks] The following program is split across three different files as shown below. Assuming that we attempt to compile it with cc q5.c q5fun.c, indicate which one of the following is true: (a) There is a compile-time error. If so, describe what the problem is (you don t have to describe a fix). (b) There is a runtime error. If so, describe why this happened (you don t have to describe a fix). (c) The program compiles and runs with no problems. If so, indicate what the output will be. q5.c 1 #include <stdio.h> 2 #include "q5.h" 3 int number; 4 main() { 5 number = 2; 6 printf("%d\n",fun(5)); 7 printf("%d\n",number); 8 } 1 extern int number; 2 int fun(int); 1 #include "q5.h" 2 int fun(int x) { 3 return x + number++; 4 } q5.h q5fun.c The program compiles and runs with no problems. The output will be: 7 3 20 marks, all or nothing.
p. 7 of 9 Q6. [30 marks] Recall the following linked list data structure that we saw in class. struct list { int data; struct list *next; }; Assume that a program has used this structure to build the following linked list. head 1 2 NULL For each of the code segments below and in the following pages, draw a diagram that shows what the list will look like after its execution. If some list element has become garbage, indicate that clearly. The type of variable head is struct list *. Segment 1 head = head->next; 6 points, all or nothing, per each segment. Garbage must be shown for full marks. Garbage shown here in green. head 1 2 NULL
head->next = head; Segment 2 p. 8 of 9 head 1 2 NULL head->next->next = head; head = head->next; head->next->next = NULL; Segment 3 head 2 1 NULL
head->next = NULL; Segment 4 p. 9 of 9 head 1 NULL 2 NULL head->next->next = head; Segment 5 head 1 2
p. 6 of 11 Q4. [20 marks] Consider the following C function that compiles and runs with no problems. 1 void q4(char *s, char *t) 2 { 3 while(*s) s++; 4 while(*s++ = *t++); 5 } In the following, describe what this function accomplishes and why. You must also provide the smallest main() function you can think of to show how to properly use this function. The main() function must provide some input to the function and produce some output to demonstrate the function s functionality. [10 marks] The function adds string t to the end of string s (assuming s and t are well formed strings. i.e. they end with a null character). The first loop advances the s pointer until it points to the null character. The second loop advances both pointers s and t in parallel, while copying the character t points to. When the null character at the end of t is copied, the loop ends. [10 marks] Following is an example of a main function. Many other possibilities exist. It is important to ensure that string s has enough memory allocated to fit all the characters of t. If that is not the case, then no marks are given. 1 # i n c l u d e < s t d i o. h> 2 # i n c l u d e < s t d l i b. h> 3 4 void q4 ( char * s, char * t ) 5 { 6 while ( * s ) s ++; 7 while ( * s++ = * t ++); 8 } 9 10 i n t main ( ) 11 { 12 char s [ 3 0 0 ] = " abc " ; 13 char t [ 3 0 0 ] = " def " ; 14 q4 ( s, t ) ; 15 p r i n t f ( "%s ", s ) ; 16 }
p. 7 of 11 Q5. [15 marks] Consider the three C programs below. Notice that they are indeed different. q5a.c 1 #include<stdio.h> 2 int main() 3 { 4 char x = 0; 5 x = C ; 6 printf("%c", x); 7 } 1 #include<stdio.h> 2 int main() 3 { 4 char x = 0; 5 *x = C ; 6 printf("%c", x); 7 } 1 #include<stdio.h> 2 int main() 3 { 4 char *x = 0; 5 *x = C ; 6 printf("%c", *x); 7 } q5b.c q5c.c For each one of the programs, indicate on the next page which one of the following is true: (a) There is a compile-time error. If so, describe what the problem is (you don t have to describe a fix). (b) There is a runtime error. If so, describe why this happened (you don t have to describe a fix). (c) The program compiles and runs with no problems. If so, indicate what the output will be.
[5 marks] q5a.c compiles and runs ok. The output will be C. p. 8 of 11 [5 marks] q5b.c does not compile. x is declared as char, so the expression *x does not make sense. [5 marks] q5c.c compiles but will cause a runtime error. x is initialized as a null pointer, but on line 5 there is an attempt to dereference it. No marks are given without explanation.
p. 9 of 11 Q6. [30 marks] Consider the following linked list data structure. In addition to a pointer to the next element in the list, it also contains a pointer to the previous element in the list. struct list { struct list *prev; int data; struct list *next; }; Assume that a program has used this structure to build the following linked list. In the diagram, the prev links are shown as dashed lines, while the next links are solid. head NULL 1 2 3 NULL For each of the code segments below and in the following pages, draw a diagram that shows what the list will look like after its execution. The type of variables head and p is struct list *. Each code segment is independent of the others, i.e. for each one you start with the list above. You do not have to provide an explanation for your answer. Segment 1 head = head->next; head = head->prev; [6 marks] The result is the same as the original list. head NULL 1 2 3 NULL
p = head->next; head->prev = head; head->next = head; Segment 2 p. 10 of 11 [6 marks] The list becomes as below. p head 1 2 3 NULL Segment 3 head->next->next->next = head; head->prev = head->next->next; [6 marks] The list becomes circular as below. head 1 2 3
1 p = head->next->next; 2 p->next = p->prev; 3 p->prev = NULL; 4 p = head->next; 5 p->prev = p->next; 6 p->next = head; 7 head->prev = head->next; 8 head->next = NULL; 9 head = head->prev->prev; Segment 4 p. 11 of 11 [12 marks] The list is reversed as below. head NULL 3 2 1 NULL