EECS 2031 Software Tools, Winter 2014
Lab 7 (closed in labtest mode), for Thursday section
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 lab6.
In this lab, you are building a solution relative to lab5.
However, this time you have to adapt your solution to handle input where the timestamps are
not increasing (i.e., unsorted).
Moreover, you have to handle weight records that are optionally given in pounds instead
of kilograms.
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:
- The timestamp is an integer with the number of seconds since 00:00, Jan 1, 1970 UTC,
which conforms to the standard specification of time in Unix/Linux systems.
- The userID is a string, which may contain spaces.
- The weight as a floating point number, specified to mean the weight in kilograms.
*** If the weight is followed directly by the lowercase 'p', the weight value
is in imperial pounds.
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
- Write an ANSI-C program called lab7.c that reads lines from standard input,
parses them, and classifies the input according to the context set out above and the requirements
specified below.
- Test that your program correctly implements the required functionality
- Finally, submit your solution electronically before the end of
the lab test using the command
submit 2031 lab7 lab7.c
- You may submit your solution more than once. Additional documentation about the submit
command can be viewed by typing man submit.
Now create a new ANSI-C program that does the following.
Requirements
Your program must the input read line by line from standard input.
- If the timestamp field is missing, is not an integer, or is zero,
you must print Invalid time, followed by a newline character.
- The userID consists of a sequence of text strings each of which cannot start with a
digit or '.' character.
If the userID is missing, or if the userID is longer than 179 characters (including single spaces in between the parts of the userID), you must print
Illegal userID, followed by a newline character.
- If the weight field is missing, or is less than 30.0 or more than 300.0 *** kilograms,
you must print Illegal weight, followed by a newline character.
- *** The timestamps for the records may be in any order.
You are required to handle each new record as if all previously read records had been
given in (increasing) sorted order. This also applies to printing the barchart.
- Additional text on the line after the last field should be silently ignored.
- If there are multiple problems with the line of input, you must print only
the message for the first field that does not follow the specification. Processing should
then continue with the next line. All rules need to be applied in the order specified here.
- Data from lines that pass all above criteria are considered valid records.
-
If the information supplied in each line is otherwise fine,
and the userID is new, i.e., has not been seen before, you must print OK newuser
followed by a newline character.
Different amounts of whitespace
between the parts of a userID should be ignored in the test for equality of userID's.
- Otherwise, the userID has been seen before.
If the weight change between the current record and the most recent valid record
for the same userID (*** as defined by the timestamps, not the order of records)
exceeds 10 kg/day,
you must print Suspiciously large weight change, followed by a newline character.
Otherwise, you must print OK, followed by a newline character.
*** In other words, for this comparison,
you must look for the record with the biggest timestamp that is
smaller than the time stamp of the new record.
-
When the processing reaches the end of the input, i.e., upon EOF, the program
must output a bar chart, using ASCII characters.
This bar chart must contain vertical and horizontal axes drawn with '|' and '-' characters,
respectively. The origin must be represented as a '+' character.
The "length" of the horizontal dimension needs to match the amount of data that can be shown,
as specified below.
The bar chart must always be 10 lines "high" (plus the line for the horizontal axis).
-
The bar chart must show the change of weight over time for the userID with the last valid record.
For this, you must scale the information so that
30kg and 300kg are represented by 1 and 10 '*' characters respectively as vertical bars.
You must truncate weight values, i.e., a weight of 59.999kg will still yield only a single star.
To simplify the lab, the time dimension on the horizontal axis must correspond only
to the sequence of weight records, and must not be spaced according to the time stamps themselves.
Thus, each record should be respresented by a single character in the horizontal dimension.
*** Note that the records need to be shown in order of increasing time, not in the order
in which they appeared in the input.
- No other output must be produced.
For the purpose of this lab, you do not need to worry about numeric overflow. In other words, you
can safely assume that timestamps are guaranteed to fit in 32 bit integers, 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.
***
You can also safely assume that there will not be records with equal time stamps.
Here is an example input, also provided as a file, input.txt.
1000000 godzilla's kid 100
36002 godzilla's kid 30.2
36001 godzilla's kid 30.1
46002 godzilla's kid 30.1
46999 godzilla 90.1p
50000 godzilla 299
500000 godzilla's kid 60
3000000 godzilla's kid 300
6000000 godzilla's kid 89p
60000 john jack andrew wolfgang jiang rami tom bob robert frank richard smith 123.5
3600 godzilla's kid 30.0
If you start your program with this, you should get the following output, also provided as
a file, expectedoutput.txt.
OK newuser
OK
OK
OK
OK newuser
Suspiciously large weight change
OK
OK
OK
OK newuser
OK
| *
| *
| *
| *
| *
| *
| *
| **
| ***
|********
+--------
Hints:
- You can build your solution based on lab7base.c, a solution
to lab7, where one of the error conditions has been disabled to enable you
to address the task for the lab.
- One kilogram is equal to 2.20462 pounds.
- The scanf() family of functions reads characters via the "%c" specifier.
- I suggest you insert each new record into the list as soon as you have created it,
so that a decreasing sorted order is maintained.
This will guarantee that your solution meets the specification.
- It is usually easier to address each individual requirement to your code only after
you have verified that the previous requirement is met by your program.
- Many of the test cases for previous labs are still valid for this lab.
You can use those test cases to test if your submission deals correctly with the
unchanged aspects of the specification.
Additional hints:
- Make sure that you handle the cases of inserting a record at the beginning of the list,
in the middle, as well as at the end correctly.