EE150 - Spring 1996

Solution To
Final Exam


Jump To Solution For Problem: [1 | 2 | 3 | 4 | 5]
------

Problem #1

Looking at the specific example, we see that we have to copy A[0] through A[3] to B[3] through B[7], and we have to copy A[4] through A[6] to B[0] through B[2].

We have seen examples of array copying in class and in some of the assignments. To copy an entire array A of n elements into an array B, we use

for (i = 0; i < n; i++)
  B[i] = A[i];

The catch is that here we don't want to copy the entire array, exactly. Instead we want to do two partial copies. The first has to copy the first set of 4 elements of A (or, in general, the first n - k elements) to 3 spaces later in B (or, in general, to k spaces over). So we can use our usual copying loop to do this, but we use i + k for the subscript of the destination element, and we have to be careful not to do n elements, but instead n - k elements. The second loop is similar, but has to copy the last 3 (or k) elements of A to the beginning elements of B. So we use our usual loop, but we only do k elements instead of n, and we copy the n - k + ith element of A. (And, here the parameters are x instead of A and y instead of B.

void rotate(int x[], int y[], int n, int k)
{
  int i;

  for (i = 0; i < n - k; i++)   /* copy elements that are moved */
    y[i + k] = x[i];              /*    to the right */
  for (i = 0; i < k; i++)       /* copy elements that are actually */
    y[i] = x[n - k + i];          /*    rotated back to the left */
}
There are other ways to do this problem as well. One common one is with a single loop and an if that decides where the copied element goes.
void rotate(int x[], int y[], int n, int k)
{
  int i;

  for (i = 0; i < n; i++)   
    if (i < n - k)       
      y[i + k] = x[i];              /* move it to the right */
    else
      y[i - n - k] = x[i];          /* rotate it to the left */
}

The problem.

Problem #2

Part A

Here's the output you get if you trace through it by hand (there are three spaces in front of each line).
   *
   **
   ***
Here's how we got this.
height is 4 (read in)
i is 1 (from loop)
i is less than height
so we write "height - 1" or 3 spaces
and follow that with "i" or 1 star
and a newline
i becomes 2 (from i++)
i is less than height
so we write "height - 1" or 3 spaces
and follow that with "i" or 2 stars
and a newline
i becomes 3 (from i++)
i is less than height
so we write "height - 1" or 3 spaces
and follow that with "i" or 3 stars
and a newline
i becomes 4 (from i++)
the loop stops

The problem.

Part B

From this trace, we can see three problems.

Let's fix these in order. The first problem is because it is writing height - 1 spaces each time. We actually want it to write 3 spaces for line 1, 2 spaces for line 2, 1 space for line 1, and 0 spaces for line 4. So the number of spaces is height - i, and we should write spaces with:

writeN(' ', height - i);
If we make this fix, the program writes the correct spaces, but our output is:
   *
  **
 ***

The second problem is that we aren't writing enough stars. For the second line we want to write 3 instead of 2, and for the third line we want to write 5 instead of 3. If we view the number of stars as a function of line number (i), it seems like it is 2 times i minus - 1. So the number of stars is 2 * i - 1, and we should write stars with:

writeN('*', 2 * i - 1);

The final problem is it isn't writing enough lines. It's stopping one early, which we can fix with:

for (i = 1; i <= height; i++)

The problem.

------

Problem #3

Part A

Here's the output you get if you trace through it by hand:
zeros=0 ones=0 others=0
Here's how we got this.
zeros, ones, and others are 0 (from their declarations)
in countem, s is "001x01"
in countem, p0 points to zeros
in countem, p1 points to ones
in countem, po points to others
also in countem, cnt0, cnt1, and cnto start at 0
and i is 0
s[i] is s[0] which is a '0' not a '\0', so it goes into the loop
it doesn't match either test (with the number 0 or 1)
so it does the else, which updates cnt0 (now 1)
i is incremented (now 1)
s[i] is s[1] which is a '0' not a '\0', so it goes into the loop
it doesn't match either test (with the number 0 or 1)
so it does the else, which updates cnt0 (now 2)
i is incremented (now 2)
s[i] is s[2] which is a '1' not a '\0', so it goes into the loop
it doesn't match either test (with the number 0 or 1)
so it does the else, which updates cnt0 (now 3)
i is incremented (now 3)
s[i] is s[3] which is a 'x' not a '\0', so it goes into the loop
it doesn't match either test (with the number 0 or 1)
so it does the else, which updates cnt0 (now 4)
i is incremented (now 4)
s[i] is s[4] which is a '0' not a '\0', so it goes into the loop
it doesn't match either test (with the number 0 or 1)
so it does the else, which updates cnt0 (now 5)
i is incremented (now 5)
s[i] is s[5] which is a '1' not a '\0', so it goes into the loop
it doesn't match either test (with the number 0 or 1)
so it does the else, which updates cnt0 (now 5)
i is incremented (now 6)
s[i] is s[5] which is a '\0', so it stops the loop and returns
the main then prints zeros, ones, and others, which are all 0

The problem.

Part B

From this trace, we can see two problems.

We can fix the first problem by adding these lines at the end of the function:
*p0 = cnt0;
*p1 = cnt1;
*po = cnto;
We can fix the second problem by putting the 0 and the 1 in quotes (so that they are characters rather than numbers).
if (s[i] == '0')
and
if (s[i] == '1')

The problem.

------

Problem #4

Part A

The array would look like this:
+--------------------------------------+
+ 'a' | 'l' | 'e' | 'x' | \0 |   ...   |
+--------------------------------------+
+ 'w' | 'a' | 's' | \0  |    ...       |
+--------------------------------------+
+ 'h' | 'e' | 'r' | 'e' | \0 |   ...   |
+--------------------------------------+
+   ...                                +
+--------------------------------------+

The problem.

Part B

One solution is to read everything a character at a time. Normally we put a character in the next column in the current row, except when we hit a newline, in which case we store a '\0' and update things so we start storing at the beginning of the next row.

int fillTwoD(char table[][21])
{
  int row = 0, col = 0;
  int c;

  while ((c = getchar()) != EOF)
    if (c != '\n')
      table[row][col++] = c;
    else
    {
      table[row][col] = '\0';
      row++; col = 0;
    } 
  return row;
}

A more clever solution uses getline, realizing that each row of a two-dimensional array is an array its own right that getline can fill.

int fillTwoD(char table[][21])
{
  int row = 0;

  while (getline(&table[row][0]) != -1)
    row++;
  return row;
}

Part C

Printing out a line in reverse is very similar to how to print a regular string in reverse. You need to find the '\0' at the end of the string and then start printing backwards. You can find the '\0' by using strlen or by writing a little loop to run through the current row trying to find it. You then write a loop to print the columns, in reverse order, of the current row.

void printRevLine(char table[][21], int lineno)
{
  int len = strlen(&table[0][lineno]);   /* determine length */
  int col;

  for (col = len - 1; col >= 0; col--)
    printf("%c\n", table[lineno][col]);
}

The problem.

Part D

Printing out the array is simply a matter of printing each row in reverse order, except that you start from the last row and wind up with the first. To print each row, you use the printRevLine function.

void printRevTwoD(char table[][21], int lines)
{
  int row;

  for (row = lines - 1; row >= 0; row--)
    printRevLine(table, row)
}

The problem.

Part E

The main program has three tasks: declare the array, read values into the array, and print the array in reverse order. The two actions correspond to function calls.

main()
{
  char table[10][21];
  int lines;
  
  lines = fillTwoD(table);
  printRevTwoD(table, lines);
}

The problem.

Problem #5

Part A

For this part, you need to use getline to read the artist and again to read the title, and you need scanf to read the price and the quantity. The only real twist is that you read them directly into structure fields, rather than reading them into regular arrays.

int readTable(struct CD table[])
{
  int cnt = 0;

  while (getline(table[cnt].artist, MAX_NAME) != -1)
  {
    getline(table[cnt].title, MAX_NAME);
    scanf("%lf %d\n", &table[cnt].price, &table[cnt].quantityInStock);
    cnt++;
  }
  return cnt;
}

The problem.

Part B

For this part, you need to run through the table of structures, comparing each artist field to the artist you are looking up (using strcmp, since you are comparing arrays). When you have a match, you print the title field of that table entry.

void printArtist(struct CD table[], int n, char artistName)
{
  int i;

  for (i = 0; i < n; i++)
    if (strcmp(table[i].artist, artistName) == 0)
      printf("%s\n", table[i].title);
}

The problem.

Part C

For this part, you have to run through the original table, looking at the quantityInStock, and when it's zero, copy the current table entry into the next available entry in the new table. This involves copying all of the fields, which for the strings, involves calling strcpy.

void outOfStock(struct CD table[], int n, struct CD newtable[])
{
  int i;
  int cnt = 0;

  for (i = 0; i < n; i++)
    if (table[cnt].quantityInStock == 0)
    {
      strcpy(newtable[cnt].title, table[i].title);
      strcpy(newtable[cnt].artist, table[i].artist);
      newtable[cnt].price = table[i].price;
      newtable[cnt].quanityInStock = table[i].quantityInStock;
      cnt++;
    }
}

If you read the book, howveer, you'll see there's a shortcut: we can simply do the copy by assigning structures.

void outOfStock(struct CD table[], int n, struct CD newtable[])
{
  int i;
  int cnt = 0;

  for (i = 0; i < n; i++)
    if (table[cnt].quantityInStock == 0)
      newtable[cnt++] = table[i];
}

The problem.

[Top Of Page | EE150 Exam Information Page | EE150 Home Page]