EECS 2031 Software Tools, Winter 2014

Lab 5 (lab open during first 30 minutes, then closed in labtest mode)

Cellphones and other electronic devices must be off while you are in the lab.

Background Scenario

This lab uses the same bathroom scale data transmission scenario as lab2 to lab4. However, this time you have to adapt your solution for the previous labs to output an overview of the weight change of the last valid user at the end of the input.

In the following and for ease of reading, the changes relative to lab5 have been marked below with '***'. As before, each line of input contains the following information:

timestamp userID weight

There are one more space characters separating the three pieces of information, except that the userID itself may now contain one or more spaces (as in "1000 John Jack Smith 123.45"). The fields are defined as follows:

This protocol can be parsed deterministically, as the weight is the first numeric field after a sequence of text fields, e.g. as in timestamp userIDa userIDb userIDc userIDd weight and none of the parts of the userID can start with a digit or '.'.

Objective

Now create a new ANSI-C program that does the following.

Requirements

Your program must the input read line by line from standard input. For the purpose of this lab, you do not need to worry about overflow. In other words, you can safely assume that timestamps are guaranteed to fit in 32 bit integers, userID's will not be longer than 1000 characters including spaces, and floating point numbers will fit into a ANSI-C float variable. You can also safely assume that there is always at least one (or more) space characters between the fields and between each part of the userID. Moreover, each line of input is guaranteed to be less than 1024 characters long.

Assuming that the program is started with lab5, and given the following input, which is also provided for convenience as a file input.txt:

3600  godzilla's kid 30.0
36000 godzilla 299
36001 godzilla's kid 30.1
36002 godzilla's  kid 30.2
46002 godzilla's       kid 30.1
46999 godzilla     30.1
60000 john jack       andrew wolfgang jiang rami      tom bob robert frank richard smith 123.5
500000 godzilla's       kid 60
1000000 godzilla's       kid 100
3000000 godzilla's kid 300
5000000 godzilla's kid 89
your program should create the following output, provided for convenience as a file expectedoutput.txt (file and example output updated, 2 times):
OK newuser
OK newuser
OK
Suspiciously large weight change
OK
Suspiciously large weight change
OK newuser
OK
OK
OK
OK
|      * 
|      * 
|      * 
|      * 
|      * 
|      * 
|      * 
|     ** 
|    ****
|********
+--------

Hints:

Additional hints:

Added: How to quickly identify the cause of a Segmentation violations

To identify the very likely cause of an illegal memory access, first (re-)compile your program with the "-g" flag and start in the debugger as follows:
gcc -g -o lab5 lab5.c
gdb lab5
Now you will get the debugger prompt. Type in one of the two the following commands:
run
run < input.txt
depending if you want to use predefined input or provide input yourself. Once your program stops due to a segmentation violation you will see where it stopped. To get a bit more information, use the following command:
where
which will show you a stack trace, similar to a Java exception. This will identify the line currently executing in the program. If you see multiple lines, that may mean the program crashed inside a function, e.g., because you passed a NULL pointer to strcmp(). In that case look for the line that lists your source file (lab4.c). Note the number at the beginning of that line and then "jump" to that location via
frame number
E.g., "frame 1". Now use the
list
command to see the code around this location. Then use
print expression
to look at the value of a variable, e.g. "print p". If you see the value of a pointer being zero, then the likely problem is a dereference of null pointer. Otherwise, you are likely indexing with the statement identified above into a memory location that was not malloc()'ed by the program, typically because you are indexing beyond the end of an array/memory region. A good indication for that is that if a given print command fails, then the pointer or array index itself is invalid. Note that the print command permits (most) C expressions, including "print *p", "print p->next" and "print a[i]", which gives you several options to diagnose a problem.
quit
will quit the debugger. You can now fix your program according to the insight you gained.