Logbook query program

This is your first graded lab. You should work on this lab together with a partner, being sure that it accomplishes all of the tasks that we set forth here. In grading this lab, we will check for correctness, robustness, documentation, and that you make good usage of procedures.

When lab monitors work in the computer lab, a ``logbook'' program records the times they work. This program was the final project for one programming team in MC39 (Software development) a few years ago. They actually wrote a collection of several related programs, one for logging in and out, one for printing out the records, etc. The interface between these programs is certain file formats that convey data between them. In this problem, you will write an additional program that allows an MCS lab monitor to determine how many hours he or she has worked so far this month.

There is a file that contains all the data from the month, with one line per monitoring shift. Each line contains three numbers with colons between them. The first is the user identification number, or uid, of the monitor; the second is the starting time; and the third is the ending time. The times are measured in seconds since an uninteresting reference point. So, for example, the line

  9041:3000:6600
would indicate that the monitor with uid 9041 worked a shift that lasted for 3600 seconds, i.e., exactly one hour, starting at time 3000 and ending at time 6600.

What you need to do is read these lines in one by one, until end of file is reached, and for each check whether the uid is the one you are looking for. If so, the difference between the start and end times should be added to a running sum. At the end, this running sum can be divided by 3600.0 to get the number of hours the monitor worked, and this can be output.

As described in the book, you can check for end of file by testing when the input operation, such as cin >> uid, has a false value. Since the times are quite large, the uid and start and end times should be input into variables of type long, and a long should also be used for the running total time.

One detail is how to know what the uid of the monitor running the program is; what you can do is put the line

  #include <unistd.h>
at the top of your program file and then use the getuid() procedure to get the uid of the user running the program. (It'd be most efficient to do this only once, rather than for each line.)

I have made a sample data file, which is located at:

      ~mc38/labs/logbook/files/logbook.data
Assuming your program is called myHours and that you are running it in the directory containing the data, you can use the < feature of the shell, as in
      ./myHours < logbook.data
which runs the myHours program with its standard input coming from logbook.data. Since this is an MCS lab logbook file that does not contain any of your uids, you are going to have to figure out what your uid is and insert it at several places in the datafile. How many hours did you work? (Be sure to also test your program with inputs simple enough for you to easily check the answer.)

One thing we will be looking for in your program is that it does appropriate checks for valid input. By this, we mean that it checks for the following:

If your program detects an error on a given line, it should stop processing the line, discard the line, and resume processing on the following line. It should tell the user line number where the error was encountered, and some information about the nature of the error. (Note that additional data or characters anywhere in a line should count as an error, as well as missing data.)

It's best to send errors to cerr rather than cout:

  cerr << "Line 2412:  Missing colon\n";

The test input file has no errors; be sure to introduce errors in your short test file to be sure your program is handling errors properly.

Helpful commands

A few commands will help you do error checking:
  1. You can peek at the next character without reading it in char c = cin.peek().
  2. You can find out if a character is a digit using isdigit(c). (You need to #include <ctype.h>
  3. A newline is the character '\n'. (Single quotes denote characters, double quotes are strings.)
  4. You can read (and skip over) the colons by using cin.get(c).
  5. You can detect end of file by first peeking past the end of file and then checking if cin.eof() returns true.
  6. Lazy evaluation of and and or on page 156 will help keep your code clean.

Note that you need to either include only one of the following:

  #include "ccc_ansi.h"   //  Defines and, or, not
  #include <string>       //  You must use &&, ||, !
Both define the string class, so you cannot include both. If you include the first, don't forget to compiles with -I/usr/local/lib/cccfiles.

In the gdb debugger you can type

  (gdb) run < logbook.data 
to make gdb redirect input from file logbook.data.

PostScript

Incidentally, once you've successfully completed this problem, the only minor detail standing in the way of it being a useful addition to the logbook system is getting it to automatically access the real data file, rather than needing input fed to it with <. Although we haven't dealt with this yet this yet, it is a very simple matter. So, this problem is a good example of the fact that even a minor amount of custom programming can be useful to someone, particularly when used together with other existing programs.