EECS 2031 Software Tools, Winter 2014
Lab 3 (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.
However, this time you have to adapt your solution for lab2 to deal with data
sent from a different bathroom scale, which transmits similar data
with slightly different properties. That bathroom scale was made and programmed by a different
manufacturer, who choose to interpret some parts in the protocol specification
differently. The issue was only discovered after thousands of devices had
already been shipped, so you now have to adapt the smartphone package that reads the data.
In the following and for ease of reading, the most important changes
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.
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
Objective
- Write an ANSI-C program called lab3.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.
- In the initial open lab, you are welcome to create a draft solution. You need to submit that using the command
submit 2031 pre3 lab3.c
With this, your initial work will be available to you in the closed part of the labtest.
You can submit other text files, such as files with input data, as well.
- Once the labtest starts, your work will be available to you in a subdirectory
called unsubmit in your home directory. This is a read-only location.
So you have to copy these files out first, e.g. via the following command
cp unsubmit/pre3/* ~
- 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 lab3 lab3.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 the spaces
in between) 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,
you must print Illegal weight, followed by a newline character.
- If the timestamp of a record not larger than the previous timestamp,
i.e., the current is in the past relative to the previous one or identical to it,
you must print Nonmonotonic timestamps, followed by a newline character.
- 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.
- Clarified: Data from lines that pass all above criteria are considered valid records.
If the weight change between two valid records exceeds 10 kg/day,
you must print Suspiciously large weight change, followed by a newline character.
This condition applies only if the userID matches the userID from
the last valid record. Note that different amounts of whitespace
between the parts of a userID should be ignored in the test for equality of userUI's. ***
- If the information supplied in each line is otherwise fine,
you must print OK, followed by a newline character.
- No other output must be produced.
***
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 lab3, 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
36999 godzilla 30.2
60000 john jack andrew wolfgang jiang rami tom bob robert frank richard smith 123.5
your program should create the following output:
OK
OK
OK
Suspiciously large weight change
OK
OK
Hints:
- Added: Remember that strings are represented as pointers to the first
character of the string (read the first one of an array of characters). Also, strings are
terminated by '\0' characters in C. All this was discussed repeatedly in class.
Thus, string manipulation functions return pointers to characters and take pointers to
characters as arguments.
- Please read the input line by line and then use
strtok() to process the various parts of the input. That makes it
easier to deal with the variable number of parts of the userID and the varying space
characters in between. Added: Similar to Java's StringTokenizer(), C's strtok()
returns only a (pointer to a) single token/part of the string at a time.
Moreover, there is no direct way to access the "remainder" of the string (as in Java).
- Other useful functions are strcmp() for comparisons, strcat() for
string concatenation, and strcpy() for
string copying. Please don't forget to allocate a character array large enough to serve
as the destination for the copy operation!
- In C, the continue statement will advance the loop to the next iteration, as in Java.
This can help you to improve the structure and readability of your code
for dealing with invalid records.
- 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.
- Remember to look up information related to this lab well in advance or (at the very latest) in the first 30 minutes of the lab.
E.g., you should look at strtok() before you come to the lab.
- Many of the test cases for lab2 are still valid for lab3. You can use those test cases to
test if your submission deals correctly with the unchanged aspects of the specification
(e.g., the limits on the weight change).
Additional hints:
- The instructions do not give a limit on the number of parts of the userID. That means that
for every line you need to use a loop that deals with the parts of the line by calling
strtok() repeatedly. See the code examples for strtok()!
- Another important fact is that the first token and the last token of interest are numeric.
That means, that after the first token, if you find another token that starts with a digit or '.'
you have found the weight. Speaking differently, the loop that calls strtok() repeatedly
should (also) end at that time.
- To convert a single string into an integer or float, just adapt the call to sscanf()
from lab2 accordingly.
- Added: I suggest the following strategy, if you have problems with solving this lab:
- first make sure that your code can do everything OK for userID's that have no spaces in them
- then modify your code to use strtok() to parse the line (with only 3 tokens).
- then modify your code to deal with userID's with whitespace in them. One easy way to do this is to start with an empty string and keep adding the strings returned by strtok() to it until you find a token that seems to be a number which is then the weight.