Programming Assignment #6

Review Questions:

  1. How many elements does the array
            int a[5];
    
    contain? Which is the first element? The last?
  2. What's wrong with this scrap of code?
            int a[5];
            for(i = 1; i <= 5; i = i + 1)
                    a[i] = 0;
    
  3. What is the difference between a defining instance and an external declaration?
  4. What are the four important parts of a function? Which three does a caller need to know?
  5. If we say
            int i = 5;
            int *ip = &i;
    
    then what is ip? What is its value?
  6. If ip is a pointer to an integer, what does ip++ mean? What does
            *ip++ = 0;
    
    do?
  7. How much memory does the call malloc(10) allocate? What if you want enough memory for 10 ints?
  8. The assignment in
            char c;
            int *ip = &c;               /* WRONG */
    
    is in error; you can't mix char pointers and int pointers like this. How, then, is is possible to write
            char *cp = malloc(10);
            int *ip = malloc(sizeof(int));
    
    without error on either line?



Tutorial Section

  1. Here is another nested-loop example, similar to exercise 4 of assignment 1. This one prints an addition table for sums from 1+1 to 10+10.
    /* print an addition table for 1+1 up to 10+10 */
    
    #include <stdio.h>
    
    int main()
    {
            int i, j;
            /* print header line: */
            printf("  ");
            for(j = 1; j <= 10; j = j + 1)
                    printf(" %3d", j);
            printf("\n");
            /* print table: */
            for(i = 1; i <= 10; i = i + 1)
                    {
                    printf("%2d", i);
                    for(j = 1; j <= 10; j = j + 1)
                            printf(" %3d", i + j);
                    printf("\n");
                    }
            return 0;
    }
    
    The first j loop prints the top, header row of the table. (The initial printf(" "); is to make it line up with the rows beneath, which will all begin with a value of i.) Then, the i loop prints the rest of the table, one row per value of i. For each value of i, we print that value (on the left edge of the table), and then print the sums resulting from adding that value of i to ten different values of j (using a second, inner loop on j).

    Make a simple modification to the program to print a multiplication table, or a subtraction table.
  2. Here is yet another nested-loop example. It is very similar to the one above, except that rather than printing the sum i+j, it determines whether the sum is even or odd, using the expression (i+j) % 2 . The % operator, remember, gives the remainder when dividing, and an even number gives a remainder of 0 when dividing by 2. Depending on whether the sum is even or odd, the program prints an asterisk or a space. Type in and run the program, and look at the pattern that results.
    #include <stdio.h>
    
    int main()
    {
            int i, j;
            for(i = 1; i <= 10; i = i + 1)
                    {
                    for(j = 1; j <= 10; j = j + 1)
                            {
                            if((i + j) % 2 == 0)
                                    printf("* ");
                            else    printf("  ");
                            }
                    printf("\n");
                    }
            return 0;
    }
    
    (Why are there parentheses around i + j in the expression (i + j) % 2 ? What if they were left out?)

    Modify the program to print a pattern of . and # characters, or X's and O's. If you wish, experiment by taking the remainder when dividing by 3 or 4, instead. Since the remainder when dividing by 3 can be 0, 1, or 2, you could use a cascaded if/else statement to print one of three characters for each sum (or one of four if taking the remainder when dividing by 4).
  3. Later in this assignment, you're asked to create a simple function to compute the squares of numbers. Sometimes, rather than writing a function which will compute a value each time it's called, it's useful to build an array containing all the values we might need. Here is a program which declares an array, then fills it with the squares of the numbers from 1 to 10:
    #include <stdio.h>
    
    int main()
    {
            int i;
            int squares[11];        /* [0..10]; [0] ignored */
            /* fill array: */
            for(i = 1; i <= 10; i = i + 1)
                    squares[i] = i * i;
            /* print table: */
            printf("n\tsquare\n");
            for(i = 1; i <= 10; i = i + 1)
                    printf("%d\t%d\n", i, squares[i]);
            return 0;
    }
    
    There's one slight trick in the declaration of the squares array. Remember that arrays in C are based at 0. So if we wanted an array to hold the squares of 10 numbers, and if we declared it as int squares[10]; the array's 10 elements would range from squares[0] to squares[9]. This program wants to use elements from squares[1] to squares[10], so it simply declares the array as having size 11, and wastes the 0th element.

    The program also uses the tab character, \t, in its printouts, to make the columns line up.

    Modify the program so that it also declares and fills in a cubes array containing the cubes (third powers) of the numbers 1-10, and prints them out in a third column.


Exercises

  1. Write code to sum the elements of an array of int. (Write it as a function, if you like.) Use it to sum the array
            int a[] = {1, 2, 3, 4, 5, 6};
    
    (The answer, of course, should be 21).
  2. Write a program to read lines and print only those containing a certain word. (For now, the word can be a constant string in the program.) The basic pattern is
            while(there's another line)
                    {
                    if(line contains word)
                            print the line;
                    }
    
    Use the strstr function (mentioned in the notes) to look for the word. Be sure to include the line
            #include <string.h>
    
    at the top of the source file where you call strstr.
  3. Write a program to read lines of text up to EOF, and then print them out in reverse order. You can use getline to read each line into a fixed-size array (as we have been doing all along), but you will have to call malloc and make a copy of each line before you read the next one. Also, you will have to use malloc and realloc to maintain the ``array'' of character pointers which holds all of the lines.

    Extra credit: remove the restriction imposed by the fixed-size array into which each line is originally read; allow the program to accept arbitrarily many arbitrarily-long lines. (You'll have to replace getline with a dynamically-allocating line-getting function which calls malloc and realloc.)