Tutorial exercises #7: Functions, pointers Before this tute, please have a look at the wikipedia article on "Conway's game of life", and compile and run the program conway.c in /home/subjects/20006/local/tutorials, whose source code is shown in the last question for this tutorial. QUESTION 1 Walk through the execution of the following program, keeping track of the values of all the variables. For each reference to the variable x, say *which* of the several xs in the program is being referred to. Either before or after the tutorial, try compiling this program (which is available as /home/subjects/20006/local/tutorials/visibility.c) with gcc and with gnuc. int x = 3; int f(int x) { int y; x++; y = x; return x + y; } int g(void) { return f(x + 1) + f(x + 2); } int h(int z) { int x; x = z * 2; return x; } int main(void) { printf("%d\n", g()); printf("%d\n", h(x)); printf("%d\n", x); return 0; } QUESTION 2 Last week's workshop exercises asked you to write a program to test your implementation of the functions that implement the push and pop operations on stacks. This program involved several variables, including at least these: - One variable, stack, is the array that implements the stack. - One variable, sp, holds the stack pointer. - One variable holds the number that you read in from the user. For each of these variables, say whether it should be a global variable or a local variable, and if the latter, which function it should be local to. Give your reasons. QUESTION 3 Given an array of floats "a" whose number of elements is stored in the variable "n", you can compute the mean and standard deviation of the numbers in the array with this code: sum = 0.0; sum_sq = 0.0; for (i = 0; i < n; i++) { sum += a[i]; sum_sq += a[i] * a[i]; } mean = sum / n; stddev = sqrt((sum_sq / n) - mean * mean); If you had to write a function to compute the mean and standard deviation of the numbers in an array, you could use this code as the (bulk of) the function body, but how would you declare the function, and how would you return its results? You should ensure that your function works even if n = 0. QUESTION 4 Write a function that reads a line of input into a buffer (a character array), and then checks whether the contents of the line fits one particular pattern of dates: a day within a month, the 3-letter abbreviation of the name of a month, and a four-digit year number. For example, 2 Sep 1945 20 Jul 1969 1 Jan 2001 all fit this pattern. Your function should return an indication of whether the input line matches this pattern. If it does, it should also return three integers: the day number within the month, the number of the month (january being month 1) and the year number. You should decide on every detail of the interface between the function and its callers, including the comment describing the function. However, you do NOT need to flesh out all the details in the body of the function, at least not during the tutorial. However, you may wish to consider how to use the values returned by the function to figure out *which* day of its year the provided date represents, with 1 Jan being day 1 and 31 Dec being either day 365 or day 366, depending on whether the year is a leap year. QUESTION 5 Read and then discuss the following program, which plays Conway's game of life. Some of the things you can talk about are - How does the program work? - What do the individual functions do? - Is the overall task of each individual function documented properly? - Is the detailed operation of each individual function documented properly? - How could any of this code be improved? // vim: ts=4 sw=4 et // Conway's Game of Life // Author: Matt Giuca #include #include #define BOARD_WIDTH 40 #define BOARD_HEIGHT 24 extern void showboard(void); extern int count_neighbours(int x, int y); extern void step(void); extern void reset(void); char board[BOARD_HEIGHT][BOARD_WIDTH] = { " ", " ", " X X ", " X ", " X X ", " XXXX ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", " ", }; void showboard(void) { int row, col; for (row = 0; row < BOARD_HEIGHT; row++) { for (col = 0; col < BOARD_WIDTH; col++) { putchar(board[row][col]); } putchar('\n'); } } // Return the number of live neighbours of the cell at (x,y). int count_neighbours(int x, int y) { int row, col; int count; count = 0; for (row = y - 1; row <= y + 1; row++) { for (col = x - 1; col <= x + 1; col++) { // A cell is not its own neighbour. if (row == y && col == x) { continue; } // Check whether the neighbour exists on the board. if (0 <= row && row < BOARD_HEIGHT && 0 <= col && col < BOARD_WIDTH) { if (board[row][col] != ' ') { count++; } } } } return count; } // Perform one "step" of the game. // Updates board to reflect the successor state of board. void step(void) { char next_board[BOARD_HEIGHT][BOARD_WIDTH]; int row, col; int neighbours; for (row = 0; row < BOARD_HEIGHT; row++) { for (col = 0; col < BOARD_WIDTH; col++) { neighbours = count_neighbours(col, row); if (board[row][col] != ' ') { /* Alive */ if (neighbours < 2 || neighbours > 3) { /* Dies */ next_board[row][col] = ' '; } else { /* Lives */ next_board[row][col] = 'X'; } } else { /* Dead */ if (neighbours == 3) { /* Born */ next_board[row][col] = 'X'; } else { /* Stay dead */ next_board[row][col] = ' '; } } } } // Copy next_board back to board. for (row = 0; row < BOARD_HEIGHT; row++) { for (col = 0; col < BOARD_WIDTH; col++) { board[row][col] = next_board[row][col]; } } } void reset(void) { printf("\x1b[H"); } int main(void) { int iterations; system("clear"); iterations = 0; while (iterations < 10000) { iterations++; reset(); showboard(); step(); // Sleep for a second. sleep(1); } return 0; }