Overview
In this project, you will work toward developing a program C calledtime_calcwhich is a simple, interactive time converter and calculator. The functionality of the program is described below.
Functional Requirements
Thetime_calcprogram is executed as a command from the LINUX/UNIX command line. Its usage pattern is:
time_calc conv time
time_calc {add,subt,comp} time1 time2
where each of time, time1, and time2 is a "time value". A time value is either a number of seconds (an unsigned integer) less than 3155760000, or a "time specification". A time specification is a string of the form
n1y n2n n3d n4h n5m n6s
where n1 through n6 are unsigned integers (i.e. greater than 0). There can be arbitrary amounts of white space between the fields of a time spec (including none), but the fields must all be present, and must appear in the order given above. A time specification may also be called a "time spec". For a time spec to be legal or valid, n1 through n6 must be within the following bounds:
n1 < 100, n2 < 12, n3 < 31, n4 < 24, n5 < 60, n6 < 60
time_calccan perform five commands based on a "command keyword" given as the first argument:
convert between a number of seconds and a time spec (conv command);
add two time values and output the result as a time spec (add command);
subtract two time values (i.e. time1 − time2) and output the result as a time spec (subt command); and
compare two time values and output a result string (comp command).
issue a help or usage message (help command).
In the case of comp, the program produces "greater" if time1 > time2, "equal" if time1 = time2, and "less" if time1 < time2. All output on successful operation is produced on the standard output.
time_calcdiagnoses various potential errors with input or calculated results, and generates error messages on stderr. Input time values must be less than 3155760000 seconds, or a time spec of 99y11n30d10h30m00s. On add the resultant time value must be within these same bounds. On sub the resultant time value must be non-negative.
Internally, for converting between numbers of seconds and a time spec, the following conversion factors must be used:
seconds in a minute 60
seconds in a hour 3600
seconds in a day 86400
days in a year 365.25
days in a month 30.4375
seconds in a month 2629800
seconds in a year 31557600
These numbers are reasonable approximations to the true values. (See note below.) The above numbers are simpler to work with than more modern values, and "close enough" for our purposes.
The limits on n1 through n6 and the conversion units above result in some ambiguity to time specifications. This is best illustrated by an ple.
% ./time_calc conv 0y11n30d10h30m0s
31557600
% ./time_calc conv 31557600
1y 0n 0d 0h 0m 0s
We therefore define a "reduced time specification" to be one in which the number of years is maximized, and once that is done, the number of months is maximized. Output from add and subt commands is always a reduced time spec. The same is true for a conv command converting from a number of seconds. For ple, converting 2629800 seconds to a time spec will produce 0y1n0d0h0m0s rather than 0y0n30d10h30m0s.
The filesfailing_cases_log.txtandsucceeding_cases_log.txtthat accompany this project specification are sample logs of a completedtime_calcprogram in operation. Note that adequate system testing would go beyond the cases shown in these files. Also note that a student's error messages (on diagnosing an error) may be different than what is shown in these log files.
project Requirements
For this project you must implement the following data types, functions, and unit tests for the functions in a single file calledtime_calc.c.
Data Types
You must implement the following data types:
bool– same as anunsigned chardata type. Two symbols or constants are associated with this data type,TRUE(value of1) andFALSE(value of0).
time_spec_t– astructfor holding a time spec. It consists of six fields of typeuint8_t. The fields hold the year, month, day, etc. of a time spec.
num_seconds_t– the same as theuint32_tdatatype.
Any and all types and constants supporting the two types above or the functions below that you think are required.
Supporting Functions
You must implement and make use of the following functions. In each case, the function name is designed to be suggestive of the module's functionality. An additional statement is given to help explain the functionality. A partial function header is given sufficient to describe the input and return data types. Any functions with return type oftime_spec_t *may returnNULLon error.
bool is_legal_time_spec( char * )— returnTRUEif the string given as the input argument is a valid time spec; otherwise produce diagnostic messages on stderr and returnFALSE. Errors diagnosed include extraneous characters and field values exceeding limits.
bool is_legal_seconds( char * )— returnTRUEif the string given as the input argument is a valid number of seconds; otherwise produce diagnostic messages on stderr and returnFALSE. Errors diagnosed include extraneous characters and field values exceeding the limit on the number of seconds.
num_seconds_t string_to_seconds( char * )— return the number of seconds specified by the string passed as the argument to the function. The string is known to contain a valid "number of seconds" specification.
time_spec_t *string_to_time_spec( char * )— return a pointer to a dynamically allocatedstructcontaining the fields of a time spec specified by the string passed as the argument to the function. The string is known to contain a valid time spec. If memory for thestructcannot be allocated, the function returnsNULL.
time_spec_t *seconds_to_time_spec( num_seconds_t )— convert a valid number of seconds to a time spec, and store the fields of the time spec in a dynamically allocatedtime_spec_tstructure. On success, a pointer to the newly allocated structure is returned. If memory for thestructcannot be allocated, the function returnsNULL.
num_seconds_t time_spec_to_seconds( time_spec_t *)— convert a valid time spec to the corresponding number of seconds and return that number of seconds.
void print_time_spec( time_spec_t *time_spec )— output a valid time spec on stdout.
bool get_time_arg( char *in_str, num_seconds_t *seconds_p )— the function returnsTRUEif it was able to convert the string pointed to byin_strto a number of seconds. In this case the number of seconds is stored in the location pointed to byseconds_p. The string pointed to byin_strcould be a time spec or it could specify a number of seconds. The function returnsFALSEif it was not able to convert the string pointed to byin_strto a number of seconds; for ple, the string was neither a legal time spec nor a legal number of seconds. It also returnsFALSEif the number of seconds is not less than the limit of 3155760000. In the latter two cases an appropriate error message is generated on stderr. If the input pointed to byin_stris neither a legal time spec nor a legal number of seconds, then no operation should be performed on the location pointed to byseconds_p.
You may need other functions as well, depending on your program design. They will be in addition to the above supporting functions.
You will also need a function
int main( int argc, char *argv[])
that analyses the command-line arguments are calls appropriate functions to complete the functionality of time_calc.
Finally, code for the following function is already provided for you. Copy it into yourtime_calc.cfile. You can modify it, if you wish, to output tostderrrather thanstdout.
void usage( void ) {
puts( "Usage: time_calc help" );
puts( " time_calc conv " );
puts( " time_calc {add,subt,comp} " );
}
Documentation
Internal documentation must be present throughout yourtime_calc.csource file. Make sure the comments are informative, clear, and attractively laid out.
Also prepare external documentation in the style of a "programmer's manual" or "reference manual" describing the program. Remember that this external documentation will be helping the marker understand your program. Therefore make sure it is clear, well-organized, and well-written. If the marker is confused and cannot understand what you have done, your grade may suffer accordingly.
In the external documentation students may end up repeating some of what they have as internal documentation. However, the internal documentation should be discussing each function, datatype, constant, and data structure in isolation (in a "local context"). The external documentation will give the opportunity to discuss a function, data structure, data type, or constants in a more global context, in relation to the other functions, data structures, data types, and constants, and how they all fit together into a completed piece of code. External documentation should also discuss design decisions made, assumptions made, or known limitations.
The external documentation may be in any of the following forms: (plain) text, RTF, HTML, or PDF. Other types of files, included MS Word files, are not acceptable.
Use an appropriate name for the file containing your external documentation. Make sure your name, student number, and NSID appear at the beginning of the file.
Compilation Instructions
Your program must compile, without errors or warnings, with the commands
gcc -Wall -Wextra -o time_calc time_calc.c
on tuxworld.
Testing
Perform system testing on your finaltime_calcprogram. That testing should go beyond what is shown in the files succeeding_cases_log.txt and failing_cases_log.txt (which were used to generate the logs mentioned much earlier in the "Functional Requirements" portion of this project specification). Devise a (system) test plan. In composing the test plan consider how the integration of the various aspects of the program can be tested, what test cases will be used, what those cases will exercise, and what the correct results should be. Pay particular attention to testing the functions within When running your tests, consider whether the results are what they should be.
Your final testing documentation should consist of either (1) a test plan and run logs, or (2) annotated test log(s) where the annotations describe your test plan.
Verification
The marker may confirm the output shown in your log files.
Notes
There are different measures of year length. For simplicity, we are using a Julian year, 365.25 days. There are also:
A Gregorian year, 365.2425 days.
A tropical year, which tracks the amount of time it takes to get from spring equinox to spring equinox — about 365d, 5h, 48m, and 46s, or 365.242196 days. Another source says 365.242199 days. In both cases it works out to 31,556,926 seconds. A third source says 365d, 5h, 48m, 45s (365.24219 days) which is 31,556,925 seconds. Google says 365.242 days. Looks like Google doesn't know everything.
An anomalistic year, which is the number of days it takes for the Earth to return to its perihelion, the point at which it is closest to the sun. It works out to about 365.259636 days (365d 6h 13m 52.6s) per year.
A sidereal year, the amount of time it takes for the earth to return to the same position relative to the fixed (most distant) stars. This year is 365.256363004 days (365d 6h 9m 9.76s)
All lines in yourtime_calc.cfile are to be no more than 80 columns wide. Also remember the class material material on not intermixing tabs and spaces when formatting with white space, and the utility ofexpand(1).
If you use theassert()macro and it causes your program to abort, you may get a "core dump" created. This is a file with a name of the formcore.PIDon LINUX, wherePIDwas the PID of the process which executed anabort(). These files can be used for post-mortem debugging. However, they can also clutter up your directories. You may wish to "garbage collect" (delete) them.
You may (or may not) find the following C library functions of use in writing your code:fputs(3),fprintf(3),sscanf(3),strpbrk(3),strsep(3),strcmp(3),strchr(3),isdigit(3),atoi(3),atol(3),strtoul(3), andstrtoumax(3).
Even though the due date for this project appears to be far in the future, do not put off getting started on this project. It may take you longer than you think, and project 4 (where you will be modifying yourtime_calcprogram, will be coming right on its heels.
Submission Instructions
All of your code must be fully contained in a single file calledtime_calc.c. At the beginning of this file include your name, student number, and NSID in a comment block.
Upload yourtime_calc.cfile, and external documentation and testing documentation through the moodle pages for the class.