Practice Midterm Answers

I: Produce Output

Treat each of the following problems independently. For each one assume the file is compiled with the executable named a.out and then executed as indicated in the problem.

For these, just run them to see what the output is. Also we did them in class.

II: Write a C Program

Treat each of the following problems independently. For each one write a C program meeting the specification. If the program is called a command, you are to write a main() program (and possibly other functions). If it is not called a command, some other main program will call your function(s).

II.1: Swapping Various Data Types

II.1A Swapping Integers

Write a function void swapInt(int *A, int *B); that swaps the values in two integer variables. Upon return, A should be the integer formerly in B and vice versa.

Answer

The main program is not required on the exam. I thought it might be helpful for you if you wanted to try other solutions.

#include <stdio.h>
void swapInt(int *A, int *B){
    int T;
    T = *A;
    *A = *B;
    *B = T;
}

int main(int argc, char **argv) {
    int A = 22;
    int B = 11;
    printf("A=%d\nB=%d\n\n", A, B);
    swapInt(&A, &B);
    printf("A=%d\nB=%d\n\n", A, B);
}

II.1A Swapping Strings

Write a function void swapStr(char **A, char **B); that swaps the values in the two strings. Upon return, A should be the string formerly in B and vice versa.

Do not use any library functions

Answer

#include <stdio.h>
void swapStr(char **A, char **B){
    char *T;
    T = *A;
    *A = *B;
    *B = T;
}

int main(int argc, char **argv) {
    char *str1 = "A short string";
    char *str2 = "A much longer string";
    printf("str1=\"%s\"\nstr2=\"%s\"\n\n", str1, str2);
    swapStr(&str1,&str2);
    printf("str1=\"%s\"\nstr2=\"%s\"\n\n", str1, str2);
    return 0;
}

II.2: Inspect and Report

The following ins-rep.h file is available in the current directory.

struct bookType {
    int   ID;
    char  *book;   // the book itself might be huge
    // other large components (reviews, etc)
};

Write two functions

    void inspect(struct bookType *);
    char *report(void);
  
inspect() is called multiple times and finally report() is called once.

report() is to return the char *book pointing to the book with the largest ID that inspect() has seen.

Since the books are of unknown and presumed huge size, you cannot copy an entire book. Similarly, since the other large components are of unknown and presumed huge size, you cannot copy a struct bookType either. (A comment that would not appear on the real exam is that pointers to huge objects are small and hence may be copied.)

You may assume all ID's are unique and that inspect() is called at least once.

Answer

#include <stdio.h>
#include <stdlib.h>  // needed by main
#include "ins-rep.h"
static struct bookType *bigID = NULL;

void inspect(struct bookType *b) {
    if (bigID == NULL || b->ID > bigID->ID)
	bigID = b;
    return;
}

char *report(void) {
    return bigID->book;
}

int main (int argc, char *argv[argc]) {
    struct bookType *bk[3];
    int i;
    for (i=0; i<3; i++)
	bk[i] = (struct bookType *) malloc(sizeof(struct bookType));
    bk[0]->ID = 3;
    bk[0]->book = "book0";
    bk[1]->ID = 33;
    bk[1]->book = "book1";
    bk[2]->ID = 82;
    bk[2]->book = "book 2";
    for (i=0; i<3; i++)
	inspect(bk[i]);
    printf ("The book with the biggest ID is \"%s\"\n", report());
    return 0;
}

II.3: Double Space at Sentence End

Write a very primitive version of a program that copies standard input to standard output leaving an extra space after a sentence. This primitive version should just add a blank after each period.

Answer

#include <stdio.h>
int main(int argc, char *argv[argc]) {
    int c;
    while ( (c = getchar()) != EOF) {
	putchar(c);
	if (c == '.')
	    putchar(' ');
    }
    return 0;
}

II.4: Reversing Arguments

Write a program that prints out its arguments in reverse order. So, if the executable was a.out, then the command

    ./a.out  a1 a2 a3 a4
  
would produce
    a4 a3 a2 a1
  

Answer (Actually 3 Answers)

#include <stdio.h>
int main(int argc, char *argv[argc]) {

    int i;       // used in array version
    char **p;    // used in pointer version

    // array version
    for (i=argc-1; i>0; i--)
	printf("%s ", argv[i]);

    printf("\n\n");

    // Fancy: don't print trailing blank
    for (i=argc-1; i>0; i--)
	printf("%s%s", argv[i], (i==1) ? "" : " ");

    printf("|<-- look ma, no blank!\n\n");

    // pointer version
    p = &argv[argc-1];
    while (p!=argv)
	printf("%s ", *(p--));

    return 0;
}

III: What is Wrong?

III.1: Doubling Arguments

The following function is supposed to double its arguments. Why doesn't it work? Fix it.

    void doubleIt(int *x, float *y) {
        x *= 2;
        y *= 2.0
        return;
    }
  

Answer

C is call by value so the arguments aren't changed

  void doubleIt (int *x, float *y) {
      *x *= 2;
      *y *= 2.0;
      return;
  

III.2: Limiting x to a Small Range

The following code snippet is supposed to raise negative values to 0 and lower large values to 10. Why doesn't it work? Fix it.

    if (x >= 0)
        if (x > 10)
            x = 10;
    else
        x = 0;
  

Answer

The infamous C dangling-else problem. Don't believe the indenting; the else goes with the inner if, which is not what you want.

    if (x >= 0) {
        if (x > 10)
            x = 10;
        }
    else
        x = 0;
  

III.3: Finding the Max

The following function is supposed to return the max an array of n integers. Why doesn't it work? Fix it.

    int max (int n, int A[n]) {
        int m = 0;
        int i;
        for (i=0; i<n; i++)
            if (A[i] > m)
                m = A[i];
        return m;
    }
  

Answer

It assumes A[i]>=0;. You would not be expected to know about INT_MIN. If you use something like -2,000,000,000, that would be fine

    #include <limits.h>
    int max (int n, int A[n]) {
        int m = INT_MIN;
        int i;
        for (i=0; i<n; i++)
            if (A[i] > m)
                m = A[i];
        return m
    }
  

Allan Gottlieb