CPSC 223: Homework 1. A Gentle Introduction to C

Due 2:00 AM, Friday, 27 January 2017

P R E L I M I N A R Y S P E C I F I C A T I O N

REMINDER: Do not under any circumstances copy another student's code or give a copy of your code to another student. After discussing the assignment with another student, you may not take any written or electronic record away. Moreover, you must engage in a full hour of mind-numbing activity before you work on it again. Such discussions must be noted in your log file.

A previous version of this assignment was based on the following. The pianist and comedian, Victor Borge, proposed an inflationary language, in which numbers and their homophones in words would be incremented by one.

See https://www.youtube.com/watch?v=bcGA4alhPas

For example, "Anyone for tennis?" becomes "Anytwo five elevennis?"

Reading

Program Specification

(40 points) Write a filter "Total" that reads a text from the standard input, keeps a running total of the integers, and prints that total to standard output. You do not need to handle fractions or scientific notation. These will not be tested. It should process integers in decimal, binary, octal, and hexadecimal.

Here are some examples of Total in action.

% echo 23 -20 | ./Total
Total: 3
% echo 023 -020 | ./Total
Total: 3
% echo 023 020 | ./Total
Total: 35
% echo 0X1A -0xa | ./Total
Total: 16
% echo 0B101 077 | ./Total
Total: 68
The staff solution includes a debug option which prints out intermediate results. The debug option is, well, optional. You will not be tested on it.
% cat t1
-9 "4 56" 011 0b11 0x11 "3 \" 4" 5
% ./Total -debug < t1
n: -9 total: -9
n: 9 total: 0
n: 3 total: 3
n: 17 total: 20
n: 5 total: 25
Total: 25
% cat t2
---9
0\
b11
0b\
11
0\
xff
0x\
ff
0\
77
-\
x
% ./Total -debug < t2
n: -9 total: -9
n: 3 total: -6
n: 3 total: -3
n: 255 total: 252
n: 255 total: 507
n: 63 total: 570
Total: 570
Finally, note that you can pipe the output from another program into Total.
% echo sbs5 cs223ta | ./Total
Total: 228
% ll
total 40
-rw-r--r-- 1 sbs5 cs223ta 5582 Jan  3 11:00 Makefile
-rw-rw-r-- 1 sbs5 cs223ta   35 Jan  3 12:21 t1
-rw-rw-r-- 1 sbs5 cs223ta   44 Jan  3 11:56 t2
-rwxrwxr-x 1 sbs5 cs223ta 9040 Jan  3 12:10 Total
-rw-rw-r-- 1 sbs5 cs223ta 2508 Jan  3 12:10 Total.c
-rw-rw-r-- 1 sbs5 cs223ta 4152 Jan  3 12:10 Total.o
% ll | ./Total
Total: 22973

Here is a plan of attack

The major strategy is divide and conquer. Break the problem / program down into discrete elements that can be solved and tested sequentially and independently.
  1. Do the reading until you are confident about writing code.
  2. Look at the files on the zoo in /c/cs223/hw1. Specifically, check out /c/cs223/hw1/Makefile and the sample file /c/cs223/hw1/Total.c
  3. The sample Total.c simply counts the number of characters in the input, like the unix wc command. Modify it to add the following.
  4. Process integers (using atoi() from K&R) and add them up. You want to use isdigit() from the ctype library.
  5. Once you get decimal numbers working, implement octal (which start with a leading 0), binary (which start with a leading "0b" or "0B"), and hexadecimal (which start with a leading "0x" or "0X"). You may want to use isxdigit() from the ctype library.
  6. Throw away line splices. (You may do this in mygetchar() in the Total.c sample file.)
  7. Ignore numbers inside strings delimited by double quotes. Note that an escaped double quote (\") does not start or end a string. Actually, you can ignore all escaped characters, including digits like "\6".
  8. Finish the reading. You will learn something.
  9. Submit your code. See below.

You must submit

Use the submit command (see below) to turn in the source file(s) for Total, a Makefile, and your log file (see below).

YOU MUST SUBMIT YOUR FILES (INCLUDING THE LOG FILE) AT THE END OF ANY SESSION WHERE YOU SPEND AT LEAST ONE-HALF HOUR WRITING OR DEBUGGING CODE, AND AT LEAST ONCE EVERY HOUR DURING LONGER SESSIONS. (All submissions are retained.)

Notes

  1. When available, the public grading script will be /c/cs223/hw1/Tests/test.Total (and my solution will be /c/cs223/hw1/Totalx). To run it, type
    % /c/cs223/hw1/Tests/test.Total
    
    (here % is the shell prompt). The script uses make to create Total. To run each test it redirects the test file (e.g., /c/cs223/hw1/Tests/t01.c for Test #01) to the standard input of Total and redirects the standard output to a temporary file. Then it compares this file with the expected output for that input (e.g., /c/cs223/hw1/Tests/t01.cs for Test #01). Your program passes the test only if the two files are identical.

    To run your program on the file for Test #01, type

    % ./Total < /c/cs223/hw1/Tests/t01.c
    
    To compare the output from your program with the expected output, type
    % ./Total < /c/cs223/hw1/Tests/t01.c | cmp - /c/cs223/hw1/Tests/t01.cs
    
    (cmp outputs the first character where the files differ) or
    % ./Total < /c/cs223/hw1/Tests/t01.c | diff - /c/cs223/hw1/Tests/t01.cs
    
    (diff outputs the lines where they differ but uses a looser definition for "identical") or
    %  /c/cs223/hw1/Tests/test.Total 01
    
    (you may specify more than one test here).

    If your output looks the same as what is expected, but your program still fails the test, there are probably some invisible characters in your output. To make all characters visible (except blanks), type

    % ./Total < /c/cs223/hw1/Tests/t01.c | cat -vet
    
    or
    % ./Total < /c/cs223/hw1/Tests/t01.c | od -bc
    
  2. Keep track of how you spend your time in completing this assignment. Your log file should be of the general form (that below is fictitious):
         ESTIMATE of time to complete assignment: 10 hours
    
               Time     Time
         Date  Started  Spent Work completed
         ----  -------  ----  --------------
         1/13  10:15pm  0:45  Read assignment and relevant material in K&R
         1/16   4:45pm  1:15  Sketched solution using a finite-state machine with
                                one-character look-ahead
         1/19   9:00am  2:20  Wrote the program and eliminated compile-time errors;
                                code passes eight tests
         1/20   7:05pm  2:00  Discovered and corrected two logical errors; code now
                                passes eleven tests
         1/23  11:00am  1:35  Finished debugging; program passes all public tests
                        ----
                        7:55  TOTAL time spent
    
         I discussed my solution with: Peter Salovey, Ben Polak, Tamar Gendler,
         and Jonathan Holloway (and watched four episodes of The Simpsons).
    
         *A brief discussion of the major difficulties encountered*
    
    but MUST contain This log will generally be worth 5-10% of the total grade.

    N.B. To facilitate analysis, the log file MUST be the only file submitted whose name contains the string "log" and the estimate / total MUST be on the only line in that file that contains the string "ESTIMATE" / "TOTAL".

  3. The submit program can be invoked in eight different ways:
    % /c/cs223/bin/submit  1  Makefile Total.c time.log
    
    submits the named source files as your solution to Homework #1;
    % /c/cs223/bin/check  2
    
    lists the files that you submitted for Homework #2;
     % /c/cs223/bin/unsubmit  3  error.submit bogus.solution
    
    deletes the named files that you submitted previously for Homework #3 (which is useful if you rename a file or accidentally submit the wrong one);
    % /c/cs223/bin/makeit  4  Total
    
    runs "make" on the files that you submitted previously for Homework #4;
    % /c/cs223/bin/testit  5  Total
    
    runs the public test script for Total using the files that you submitted previously for Homework #5; This may not be working. Use the testing instructions given above.
    % /c/cs223/bin/protect  6  Total.c time.log
    
    protects the named files that you submitted previously for Homework #6 (so they cannot be deleted accidentally);
    % /c/cs223/bin/unprotect  7  util.c time.log
    
    unprotects the named files that you submitted previously for Homework #7 (so they can be deleted); and
    % /c/cs223/bin/retrieve  8  common.c time.log
    
    and
    % /c/cs223/bin/retrieve  8  -d"2017/01/21 20:00" util.c
    
    retrieve copies of the named files that you submitted previously for Homework #8 (in case you accidentally delete your own copies). The day and hour are optional and request the latest submission prior to that time (see the -d flag under "man co" for how to specify times).
  4. When assignments are style graded, EVERY source file found in the submit directory will be reviewed. Thus prudence suggests using unsubmit to remove a file from the directory when you change its name or it ceases to be part of your solution. See http://zoo.cs.yale.edu/classes/cs223/doc/Style

    Prudence (and a 5-point penalty for code that does not make) suggests that you run makeit ("makeit 1 Total") after you have submitted the final version of your source files. Better yet, run testit ("testit 1 Total").

    Total is easier to write if you can peek at the next character in the standard input without reading it. The macro

    #define ungetchar(c) ungetc(c,stdin)   // Unread char read from stdin
    
    allows you to push a character back onto the standard input. That is, the character C "unread" will be the next character returned by getchar(). The value returned by ungetchar() is its argument, or EOF if the operation was unsuccessful. Note: Every ungetchar() must be preceded by a getchar(), and you can only do one ungetchar() between successive getchar()'s.

    You may find this macro useful in writing Total since it allows you to read the next character and then decide that you should not have.

    Example:

            while ((c = getchar()) != EOF) {
                if (c == 'C') {
                    c = getchar();
                    if (c == 'S')
                        printf ("I found a CS in the standard input!\n");
                    else
                        ungetchar(c);
                }
            }
    

  5. The function exit() allows your program to stop immediately, without having to terminate any surrounding loops or to return to main() from a function. (To use it you must #include the header file <stdlib.h>.)
  6. Total reads from stdin and writes to stdout but does no other input/output.
  7. You may wish to use atoi() which is defined in K&R on page 61.
  8. Features of C99 (but not ANSI C) that may be useful:
  9. Correct handling of line splices will be worth at most 10 points.
  10. My first solution was 140 lines long (90 lines ignoring comments, blank lines, brace-only, and else-only lines. If your solution looks to be much larger than this, you should talk to one of the instructional staff about your approach.