CS-220 Spring 2018 Test 1 Version A Feb. 28, 2018 Name: 1. (10 points) For the following, Check T if the statement is true, the F if the statement is false. (a) T F : Every function definition in C must specify either void return, a single return type, or a comma separated list of return types. Either void or a single return type is OK, but a list of return types is not allowed. (b) T F : When you invoke a C function, the values of the argument expressions are copied to the parameters of the function. (c) T F : Variables declared in a function can be accessed after the function ends. Automatic variables are deleted when a function ends. Static local variables remain, but are not in scope outside the function. (d) T F : There may be several return statements in a function, but only one return statement will be executed in a single invocation of that function. (e) T F : Upside down code can be avoided by putting function declarations at the top of a C file. However doing so requires specification of the return type, function name, and argument list twice. (f) T F : The main function should return a true value (e.g. 1) if it ends successfully, and a false value (0) if there is a problem. The operating system interprets any non-zero return value from main as an error, and a zero return value as successful program completion. (g) T F : The same bits in memory are always interpreted to be the same value, no matter what type is associated with those bits. (h) T F : An if/else statement is an example of sequential control flow in the C language. An if/else statement is an example of control flow other than the default sequential control flow. (i) T F : In an assignment statement, C will convert the value of the expression on the right hand side of the equals sign to the type of the left hand side, even if this causes the value of the expression to change. (j) T F : The scope of a variable defines when bytes in memory are reserved for that variable, and when the memory for that variable is returned to the operating systsem. The scope defines where a variable can be updated. A local variable has local scope, even if it is static and lasts the lifetime of the program. For the following questions, check the best answer. 2. (5 points) What does the following snippet of code print to stdout? int x []={3, 1, 1, 4, 2 ; char y []={ cat, dog, turkey, ant, owl ; p r i n t f ( %s \n, y [ x [ x [ 4 ] ] ] ) ; cat dog turkey ant owl y[x[x[4]]]==y[x[2]]==y[1] which contains the address of the literal string dog. Page 1 of 8
3. (10 points) In the following snippet of code, what does the function f do? struct node { struct node next ; int val ; ; int f ( struct node n ) { i f ( n==null) return 0 ; return 1+f (n >next ) ; Does not do anything meaningful. Counts the number of elements in the list starting at node n. Sums the values of the list starting at node n. Constructs a list whose first node is n. Checks if the list starting with node n is empty. struct node is a structure for a singly linked list. f is a recursive function which counts the number of nodes in the linked list, which is terminated by a NULL next link. As long as the the next pointer is not NULL, the length of the list is one greater than the length of the sub-list that starts with the next pointer. 4. (5 points) What is does the following code snippet print? int x=2; int y=4; i f ( x==1) i f ( y==2) x=6; else y=9; p r i n t f ( x=%d y=%d\n, x, y ) ; x=2 y=4 x=6 y=9 x=6 y=4 x=2 y=9 Compiler error. An ambiguous else statement is associated with the closest if statement even though the indentation suggests otherwise. Page 2 of 8
5. (10 points) What does the following code snippet print? char buf=c a l l o c ( 1 0 0, 1 ) ; s t r c p y ( buf, Good s t u f f here! ) ; f r e e ( buf ) ; p r i n t f ( Buf c o n t a i n s : %s \n, buf ) ; Buf contains: Buf contains: 0 May print Buf contains: Good stuff here!, but may print Buff contains: followed by garbage Buf contains: Good Stuff here! Compiler error. After memory is freed, other programs may modify that memory. If no other program has used the memory, it will print corretly, but if other programs have modified the memory, garbage will get printed. Note... there was a typo in the correct answer... should have read Buf, not Buff. Answer the following questions by filling in the blanks. 6. (10 points) Given the following snippet of code, what will get printed to stdout? int x [ 6 ] ; x[6]=1+(x[5]=1+(x[4]=1+(x [ 3 ] = 1 ) ) ) ; x[2]=1+(x[1]=1+(x [ 0 ] = 0 ) ) ; p r i n t f ( x[4]=%d\n, x [ 4 ] ) ; x[4]=2 This problem demonstrates assignment expressions. x[3]=1, x[4]=1+1=2, x[5]=1+2=3, x[6]=3+1=4, x[0]=0, x[1]=1+0=1, x[2]=1+1=2. There is a typo in this problem... I should have declared int x[7] in order to assign x[6], but if the four bytes of memory after the x array are in memory that you can read and write (which is a very high probability), then no error will occur, even though you write pass array bounds. If not, you will get a segmentation violation on the last assignment. 7. (10 points) Given the following snippet of code, what will get printed to stdout? char buf []= I deserve a D but w i l l get a C ; buf [12]=0 x00 ; s t r c a t ( buf, B ) ; buf [13]= ; p r i n t f ( %s \n, buf ) ; I deserve a B but will get a C The first line inserts a null terminator at index 12, which is the location of the letter D. The strcat function replaces the null terminator with a B, but adds a null terminator after the B, overwritting the space before the b in but. The next line then overwrites that null terminator, and restores the blank after B. The original null terminator after the C character at has never been touched, so when the code is done, the string becomes I deserve a B but will get a C. Page 3 of 8
8. (10 points) Given the following snippet of code, what will get printed to stdout? int mat [ 2 ] [ 3 ] = { 1 0, 1 1, 2 0, 2 1, 3 0, 3 1 ; int i, j ; for ( i =0; i <2; i ++) { for ( j =0; j <3; j++) { p r i n t f ( %d, mat [ i ] [ j ] ) ; p r i n t f ( \n ) ; 10 11 20 21 30 31 The initializer is in row major order, and the matrix mat has 3 columns and 2 rows, so the first row gets the first three values, 10, 11, and 20; and the second row gets the next three values, 21, 30, and 31. The print statement prints each column of row i, followed by a newline, so each output line contains an entire row of output. Note that the compiler will issue a warning message about the fact that the initializer does not have curly braces around the rows, but the program will still work as expected. Page 4 of 8
9. In lab yesterday, you studied a program called findmat.c. The code from that program is included on the last page for reference: (a) (5 points) It took some extra effort to create a binary tree from the elements of the input matrix. After the tree is built, does that effort make finding the closest element in the array faster than just walking through the array sequentially? Why? It is faster because, on average, we only look at log 2 (6) entries rather than 6 entries. (b) (5 points) In the findmat program, we only look up one value using the binary tree, so the time to make the binary tree is probably much more than the time we can save using the tree. Describe a situation where it would be worthwhile to spend the extra time to make a binary tree. If we had to look up many different values in the matrix, then the time to make the tree would be distributed over all the lookups. Also, the bigger the matrix, the bigger the benefit of the binary tree, but it also costs more to make a binary tree. The real benefit of the tree is mostly related to the number of times the tree is used. 10. (20 points) Write a new function called maketree to be added to the findmat program. Your new function should take three parameters. The first is a pointer to an int that represents the beginning of a two-dimensional integer matrix (assumed to be in row major order). The second parameter is an int number of rows, and the third parameter is an int number of columns in that matrix. The maketree function should return a struct tnode pointer that contains the root of a binary tree created from that array. Your new function may invoke any of the functions already defined in findmat. Once maketree is coded, we should be able to replace lines 24 through 31 of the findmat program with the following line of code: struct tnode root=maketree((int )mat,3,5); Solution: struct tnode maketree ( int array, int rows, int c o l s ) { struct tnode root=newnode ( array, 0, 0 ) ; int r ; int c ; for ( r =0; r<rows ; r++) { for ( c =0;c<c o l s ; c++) { i n s e r t T r e e ( root, ( array+r c o l s+c ), r, c ) ; return root ; Or... struct tnode maketree ( int array, int rows, int c o l s ) { struct tnode root=newnode ( array, 0, 0 ) ; int r ; int c ; for ( r =0; r<rows ; r++) { for ( c =0;c<c o l s ; c++) { i n s e r t T r e e ( root, array, r, c ) ; array++; return root ; Page 5 of 8
Note: In this solution, I depend on the fact that inserttree throws away duplicates, so that when I inserttree for row=0, col=0, it gets discarded; but the original program used this same feature. Page 6 of 8
Tear-off Page 1 #include <s t d i o. h> 2 #include <s t d l i b. h> 3 #define abs ( a ) ( a>=0? a : (a ) ) 4 5 struct tnode { 6 int val ; 7 int row ; int c o l ; 8 struct tnode l e f t ; struct tnode r i g h t ; 9 ; 10 11 struct tnode newnode ( int val, int row, int c o l ) ; 12 void i n s e r t T r e e ( struct tnode root, int val, int row, int c o l ) ; 13 void printsortedtree ( struct tnode root ) ; 14 void findtree ( struct tnode root, int val, struct tnode c l o s e s t ) ; 15 void f r e e T r e e ( struct tnode root ) ; 16 17 int main ( int argc, char argv ) { 18 int mat [ 3 ] [ 5 ] = { { 3 1, 4 5, 1 2, 1 6, 4 4, { 9 8, 7 5, 1 3, 4 2, 1 1, { 6, 1 4, 5 0, 1 0, 8 1 ; 19 20 i f ( argc!=2) { 21 p r i n t f ( Invoke as %s <value >\n, argv [ 0 ] ) ; 22 return 0 ; 23 24 struct tnode root=newnode (mat [ 0 ] [ 0 ], 0, 0 ) ; 25 int row ; 26 for ( row=0;row <3;row++) { 27 int c o l ; 28 for ( c o l =0; col <5; c o l++) { 29 i n s e r t T r e e ( root, mat [ row ] [ c o l ], row, c o l ) ; 30 31 32 printsortedtree ( root ) ; 33 int l o s t=a t o i ( argv [ 1 ] ) ; 34 findtree ( root, l o s t,null) ; 35 f r e e T r e e ( root ) ; 36 return 0 ; 37 38 39 struct tnode newnode ( int val, int row, int c o l ) { 40 struct tnode new = ( struct tnode ) malloc ( sizeof ( struct tnode ) ) ; 41 new >val=val ; 42 new >row=row ; new >c o l=c o l ; 43 new >l e f t=null; new >r i g h t=null; 44 return new ; 45 46 47 void i n s e r t T r e e ( struct tnode root, int val, int row, int c o l ) { 48 i f ( val==root >val ) return ; // Don t i n s e r t a v a l u e t h a t s a l r e a d y t h e r e 49 i f ( val < root >val ) { 50 i f ( root >l e f t==null) root >l e f t=newnode ( val, row, c o l ) ; 51 else i n s e r t T r e e ( root >l e f t, val, row, c o l ) ; 52 else { // must be val >root >v a l Page 7 of 8
53 i f ( root >r i g h t==null) root >r i g h t=newnode ( val, row, c o l ) ; 54 else i n s e r t T r e e ( root >r i g h t, val, row, c o l ) ; 55 56 57 58 void printsortedtree ( struct tnode root ) { 59 i f ( root >l e f t ) p rintsortedtree ( root >l e f t ) ; 60 p r i n t f ( mat[%d ][% d ] = %3d\n, root >row, root >col, root >val ) ; 61 i f ( root >r i g h t ) printsortedtree ( root >r i g h t ) ; 62 63 64 void findtree ( struct tnode root, int val, struct tnode c l o s e s t ) { 65 i f ( c l o s e s t==null) c l o s e s t=root ; 66 i f ( val==root >val ) { 67 p r i n t f ( Value %d i s in mat[%d][%d ] \ n, val, root >row, root >c o l ) ; 68 return ; 69 70 i f ( abs ( val root >val)<abs ( val c l o s e s t >val ) ) { 71 c l o s e s t=root ; 72 73 i f ( val<root >val ) { 74 i f ( root >l e f t==null) { 75 p r i n t f ( C l o s e s t value to %d i s in mat[%d][%d]=%d\n, 76 val, c l o s e s t >row, c l o s e s t >col, c l o s e s t >val ) ; 77 return ; 78 79 findtree ( root >l e f t, val, c l o s e s t ) ; 80 else { 81 i f ( root >r i g h t==null) { 82 p r i n t f ( C l o s e s t value to %d i s in mat[%d][%d]=%d\n, 83 val, c l o s e s t >row, c l o s e s t >col, c l o s e s t >val ) ; 84 return ; 85 86 findtree ( root >r i g h t, val, c l o s e s t ) ; 87 88 89 90 void f r e e T r e e ( struct tnode root ) { 91 i f ( root >l e f t ) f r e e T r e e ( root >l e f t ) ; 92 i f ( root >r i g h t ) f r e e T r e e ( root >r i g h t ) ; 93 f r e e ( root ) ; 94 Question: 1 2 3 4 5 6 7 8 9 10 Total Points: 10 5 10 5 10 10 10 10 10 20 100 Bonus Points: 0 0 0 0 0 0 0 0 0 0 0 Page 8 of 8