CS360 Midterm Exam #2. March 10, 2016. James S. Plank

Answers and Grading


Question 1: 24 Points

Here are the three problems:

Here's are the fixes: If you want to see the performance difference, the input file q1-c.txt has 3,212,537 lines, each of which is 15 characters and a newline. The 10,000-th line with an 'A' is line number 3,085,399, so this file will stress all three problems. The programs q1-fix-A.c, q1-fix-B.c and q1-fix-C.c fix each problem individually, and q1-fix-all.c fixes all of them. As you can see (Macbook Pro, 2.4 Ghz processor), each of the problems is significant:
UNIX> time q1 < q1-c.txt > /dev/null
1.577u 2.882s 0:04.46 99.7%	0+0k 0+1io 0pf+0w
UNIX> time q1-fix-A < q1-c.txt > /dev/null
0.982u 0.113s 0:01.09 100.0%	0+0k 0+1io 0pf+0w
UNIX> time q1-fix-B < q1-c.txt > /dev/null
1.320u 2.742s 0:04.06 100.0%	0+0k 0+1io 0pf+0w
UNIX> time q1-fix-C < q1-c.txt > /dev/null
1.008u 2.859s 0:03.87 99.4%	0+0k 0+0io 0pf+0w
UNIX> time q1-fix-all < q1-c.txt > /dev/null
0.162u 0.030s 0:00.19 100.0%	0+0k 0+0io 0pf+0w
UNIX> 

Grading


Question 2: 15 Points

There were two correct approaches to solving this problem. The first is more efficient: The second approach is correct, but less efficient:
  • Use opendir() and readdir() to read all of the files in the current directory.
  • Use stat() to determine which files are directories. For all of those that are neither "." nor "..", use opendir() and readdir() to figure out the names of all of the files in that directory. If any are named "f1.txt", print them out.
  • You also need to keep track of whether you printed anything, so you can print "None Found" at the end if you haven't printed anything. Here it each solution. I printed each file on its own line, even though the example I gave printed two files on one line. I gave full credit to either approach. The first solution is in q2-1.c:

    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    #include <sys/stat.h>
    #include <dirent.h>
    
    main()
    {
      DIR *d;
      char *filename;
      struct dirent *de;
      struct stat buf;
      int any;
    
      any = 0;
      
      d = opendir(".");
      if (d == NULL) { perror("opendir ."); exit(1); }
      for (de = readdir(d); de != NULL; de = readdir(d)) {
        if (stat(de->d_name, &buf) == 0) {
          if (S_ISDIR(buf.st_mode) && strcmp(de->d_name, ".") != 0 &&
                                      strcmp(de->d_name, "..") != 0) {
            filename = (char *) malloc(sizeof(char) + (strlen(de->d_name) + 10));
            sprintf(filename, "%s/f1.txt", de->d_name);
            if (stat(filename, &buf) == 0) {
              printf("%s\n", filename);
              any = 1;
            }
            free(filename);
          }
        }
      }
      closedir(d);
      if (!any) printf("None Found\n");
      exit(0);
    }
    

    And the second is in q2-2.c:

    #include <stdio.h>
    #include <stdlib.h>
    #include <sys/stat.h>
    #include <dirent.h>
    
    main()
    {
      DIR *d1, *d2;
      struct dirent *de1, *de2;
      struct stat buf;
      int any;
    
      any = 0;
      
      d1 = opendir(".");
      if (d1 == NULL) { perror("opendir ."); exit(1); }
      for (de1 = readdir(d1); de1 != NULL; de1 = readdir(d1)) {
        if (stat(de1->d_name, &buf) == 0) {
          if (S_ISDIR(buf.st_mode) && strcmp(de1->d_name, ".") != 0 &&
                                      strcmp(de1->d_name, "..") != 0) {
            d2 = opendir(de1->d_name);
            if (d2 == NULL) { perror(de1->d_name); exit(1); }
            for (de2 = readdir(d2); de2 != NULL; de2 = readdir(d2)) {
              if (strcmp(de2->d_name, "f1.txt") == 0) {
                printf("%s/%s\n", de1->d_name, de2->d_name);
                any = 1;
              }
            }
            closedir(d2);
          }
        }
      }
      closedir(d1);
      if (!any) printf("None Found\n");
      exit(0);
    }
                
    

    A large number of you tried a recursive solution that printed out all files reachable from the current directory whose names are "f1.txt". That does not fit the problem description.

    Grading

    If you solved it in the first way: If you solved it in the second way: If you gave a recursive solution, then the following points were available to you:


    Question 3: 18 Points

    The program is in q3.c.

    Let's draw memory, in four-byte chunks from address 0x100130 to 0x10016c:

    0x100130 | 0x100140 | p[0]
    0x100134 | 0x100150 | p[1]
    0x100138 | 0x100160 | p[2]
    0x10013c | unknown  | 
    0x100140 | 0x100    | p[0][0]
    0x100144 | 0x101    | p[0][1]
    0x100148 | 0x102    | p[0][2]
    0x10014c | unknown  | 
    0x100150 | 0x110    | p[1][0]
    0x100154 | 0x111    | p[1][1]
    0x100158 | 0x112    | p[1][2]
    0x10015c | unknown  | 
    0x100160 | 0x120    | p[2][0]
    0x100164 | 0x121    | p[2][1]
    0x100168 | 0x122    | p[2][2]
    0x10016c | unknown  | 
    
    From that, we know that: We can verify this on my Macintosh, which is how I generated the problem:
    UNIX> gcc -m32 q3.c
    UNIX> a.out
    p:    0x100130
    p[0]: 0x100140
    p[1]: 0x100150
    p[2]: 0x100160
    
    A: 0x100134
    B: 0x100154
    C: 0x111
    D: 0x112
    E: 0x100140
    F: 0x121
    UNIX> 
    

    Grading

    Three points per part, again with partial credit given.


    Question 4: 18 Points

    Here's the assembler that proc compiles to:

    proc:
        push #12
        mov #15 -> %r0
        st %r0 > [sp]--
        ls [fp+16] -> %r0
        st %r0 -> [sp]--
        jsr d
        pop #8
        mov #4 -> %r0
        ret
    

    So, given that:

    Grading

    Two points per line, with partial credit given.


    Question 5: 18 Points

    Nothing much subtle here, except you have to use r2 to store the return value of c() while you call d(). Since you use r2, you have to spill it after you allocate room for i .

    a:
        push #4               // Allocate i
        st %r2 -> [sp]--      // Spill r2
    l1:
        jsr c                 // Do (c() + d())
        mov %r0 -> %r2
        jsr d
        add %r2, %r0 -> %r0
        cmp %r0, %g0          // > 0
        ble l2
        ld [fp+12] -> %r0     // b += 5
        mov #5 -> %r1
        add %r0, %r1 -> %r0
        st %r0 -> [fp+12]
        b l1
    l2:
        ld [fp+12] -> %r0     // return b
        ld ++[sp] -> %r2
        ret
    

    Grading

    As always, there was partial credit given.


    Question 6: 14 Points

    This comes from the lecture notes, more or less:

      ld [fp] -> %r0            // Load i into r0
      mov #4 -> %r1             // Load 4 into r1
      mul %r0, %r1 -> %r0       // Multiply i by 4, product in r0
      ld [fp+12] -> %r1         // Load p into r0
      add %r0, %r1 -> %r0       // Add i*4 to p.  This is &(p[i])
      ld [r0] -> %r0            // Get p[i]
      ld [r0] -> %r0            // Get *p[i]
      ret
    

    Grading

    Two points for each of these, with partial credit: