Week 11 Laboratory — Sample Solutions

  1. pruneTree.c

    // pruneTree.c: input and print a BST, then prune its leaves
    #include <stdio.h>
    #include <stdlib.h>
    #include <assert.h>
    
    typedef struct node {
       int value;
       struct node *left;
       struct node *right;
    } Node;
    typedef Node *Tree;
    
    Node *newNode(int v);              // make a new node, from lecture
    Tree insert(Tree t, int v);        // insert a node 'v' into a BST, from lecture
    void printTree(Tree t, int level); // pretty-print a BST, from Week 10 Lab
    void freeTree(Tree t);             // free the tree, from Week 10 Lab
    
    Tree pruneLeaves(Tree t);          // prune the leaves on a tree
    
    int main(int argc, char **argv) {
       Tree t = NULL;
       int i;
       int retval = EXIT_SUCCESS;
    
       if (argc == 1) {
          fprintf(stderr, "Usage: %s integers ...\n", argv[0]);
          retval = EXIT_FAILURE;
       } else {
          int dataGood = 1;
          for (i=1; i<argc && dataGood; i++) {
             int num;
             if (sscanf(argv[i], "%d", &num) != 1) {
                fprintf(stderr, "Usage: %s integers ...\n", argv[0]);
                freeTree(t);
                dataGood = 0;
                retval = EXIT_FAILURE;
             } else {
                t = insertTree (t, num);
             }
          }
          if (dataGood) {
             printTree(t, 0);
             printf("Pruned tree:\n");
             t = pruneLeaves(t);
             printTree(t, 0);
             freeTree(t);
          }
       }
       return retval;
    }
    
    Tree pruneLeaves(Tree t){ // delete leaf nodes
       if (t != NULL) {
          if (t->left==NULL && t->right==NULL) {
             free(t);
             t = NULL;
          } else {
             t->left = pruneLeaves(t->left);
             t->right = pruneLeaves(t->right);
          }
       }
       return t;
    }
    

  2. merge3.c

    // merge3.c: merge the lines in 3 files, line by line
    #include <stdio.h>
    #include <stdlib.h>
    
    int main (int argc, char *argv[]) {
       int retval = EXIT_SUCCESS;
       FILE *fp1, *fp2, *fp3;
       char line[BUFSIZ];
       if (argc == 4) {
          int fin1, fin2, fin3;
          if ((fp1 = fopen(argv[1], "r")) != NULL &&
              (fp2 = fopen(argv[2], "r")) != NULL &&
              (fp3 = fopen(argv[3], "r")) != NULL) {
             fin1 = 0;      // assume no file is at end
             fin2 = 0;
             fin3 = 0;
             while (!fin1 || !fin2 || !fin3) { // check whether any still going
                if (fgets(line, BUFSIZ, fp1) == NULL) {
                   fin1 = 1;                   // file 1 is at end
                } else {
                   fputs(line, stdout);
                }
                if (fgets(line, BUFSIZ, fp2) == NULL) {
                   fin2 = 1;                   // file 2 is at end
                } else {
                   fputs(line, stdout);
                }
                if (fgets(line, BUFSIZ, fp3) == NULL) {
                   fin3 = 1;                   // file 3 is at end
                } else {
                   fputs(line, stdout);
                }
             }
             fclose(fp1);
             fclose(fp2);
             fclose(fp3);
          } else {
             fprintf(stderr, "Error in opening file\n");
             retval = EXIT_FAILURE;
          }
       } else {
          fprintf(stderr, "Usage: %s <fname1> <fname2> <fname3>\n", argv[0]);
          retval = EXIT_FAILURE;
       }
       return retval;
    }
    

    1. randword.c

      // randword.c: generate a random word. The size of the
      // word and the seed of the random number generator used to
      // generate the word are specified on the command line.
      #include <stdio.h>
      #include <stdlib.h>
      #include <assert.h>
      #include <string.h>
      
      int main(int argc, char *argv[]) {
         int retval = EXIT_SUCCESS;
         char *alphabet = "abcdefghijklmnopqrstuvwxyz";
         int size = strlen(alphabet); // compute the size of the alphabet
         int length;
         int seed;
         if (argc == 3 &&
             sscanf(argv[1], "%d", &length) &&
             sscanf(argv[2], "%d", &seed)) {
            srandom(seed); // seed comes from the command line
            char *string;
            string = (char *)malloc((length+1) * sizeof(char)); // +1 for the \0
            assert(string != NULL);
            int i;
            for (i=0; i<length; i++) {
               int ran = random()%size;      // size=26, so 0<=rn<=25
               string[i] = alphabet[ran];
            }
            string[length] = '\0';
            printf("%s\n", string);
            free(string);
         } else {
            fprintf(stderr, "Usage: %s wordlength randomseed\n", argv[0]);
            retval = EXIT_FAILURE;
         }
         return retval;
      }
      

    2. llrandword.c

      // llrandword.c: generate a linked list from random word, then reverse the list.
      #include <stdio.h>
      #include <stdlib.h>
      #include <assert.h>
      #include <string.h>
      
      typedef struct _node {
         char data;
         struct _node *next;
      } NodeT;
      typedef NodeT *List;
      
      List reverseList(List);
      List buildList(char *);
      void printList(List);
      void freeList(List);
      
      int main(int argc, char *argv[]) {
         int retval = EXIT_SUCCESS;
         List head;
         char *alphabet = "abcdefghijklmnopqrstuvwxyz";
         int size = strlen(alphabet); // compute the size of the alphabet
         int length;
         int seed;
         if (argc == 3 &&
             sscanf(argv[1], "%d", &length) &&
             sscanf(argv[2], "%d", &seed)) {
            srandom(seed); // start with this seed
            char *string;
            string = (char *)malloc((length+1) * sizeof(char)); // +1 for the \0
            assert(string != NULL);
            int i;
            for (i=0; i<length; i++) {
               int ran = random()%size;
               string[i] = alphabet[ran];
            }
            string[length] = '\0';
            head = buildList(string);
            free(string);
            printList(head);
            head = reverseList(head);
            printList(head);
            freeList(head);
         } else {
            fprintf(stderr, "Usage: %s length seed\n", argv[0]);
            retval = EXIT_FAILURE;
         }
         return retval;
      }
      
      List reverseList(List head) {
         NodeT *prev = NULL;
         NodeT *cur = head;
         NodeT *temp;
      
         while (cur != NULL) {
            temp = cur->next;
            cur->next = prev;  // reverse current pointer
            prev = cur;        // move to ...
            cur = temp;        // ... next element
         }   
         return prev;
      }
      
      List buildList(char *string) { // string had better be null terminated
         NodeT *head = NULL;
         NodeT *prev = NULL;
         char *p;
         for (p = string; *p != '\0'; p++) {
            NodeT *n = (NodeT *)malloc(sizeof(NodeT));
            assert(n != NULL);
            n->data = *p;
            n->next = NULL;
            if (p == string) {     // if first iteration ...
               head = n;           // ... it is the head
            } else {
               prev->next = n; // back-patch the prev node
            }
            prev = n;          // this node becomes prev
         }
         return head;
      }
      
      void printList(List head) {
         NodeT *n;
         for (n = head; n != NULL; n = n->next) {
            if (n != head) {
               printf("->");
            }
            printf("%c", n->data);
         }
         putchar('\n');
      }
      
      void freeList(List head) {
         NodeT *n = head;
         while (n != NULL) {
            NodeT *m = n->next; // remember next node before freeing this node
            free(n);
            n = m;
         }
      }