CS 3113: Project 0
Goals
The goals of this project are to:
- Develop your C/Linux programming and compiling skills,
especially related to standard I/O
- Ensure that your class VM is running correctly
- Ensure that your code submission procedures follow our specifications
Proper Academic Conduct
The code solution to this project must be done individually. Do not
copy solutions to this problem from the network and do not look at or
copy solutions from others. However, you may use the net for
inspiration and you may discuss your general approach with others.
Introduction
You will write a program that takes as input the textual representation of
a number and produces a numeric representation in one of several
formats (decimal, hexadecimal or octal).
Example input:
one thousand twenty three
Corresponding output (decimal format):
1023
Corresponding output (hexadecimal format):
3ff
Specification
Program Invocation
The command-line interface to your program is as follows:
./project0 [d|h|H|o]
- Your program must accept 0 or 1 arguments. The brackets above
indicate an optional parameter
- If no arguments are specified, then the output will be in
decimal
- If there is one argument, it specifies the output format:
- "d": decimal
- "h": hexadecimal (lower case letters)
- "H": hexadecimal (upper case letters)
- "o": octal
- For any other cases, your program must print an error message
to STDERR and terminate
Program Behavior
Your program will accept lines of input until an end-of-file (EOF) is
reached, at which point it will terminate.
- Each line of input is composed of the words that form up to
a 9-digit number, followed by a newline.
- After receiving each line, your program will translate the
string into the corresponding numeric value, and print this
value in the format specified when the program was started.
- Each line of inputs results in one line of output, terminated
by a newline character.
Possible string inputs adhere to a specific grammar:
DIGIT = one | two | ... | nine
TEENS = ten | eleven | ... | nineteen
TENS = twenty | thirty |... | ninety
DOUBLE = DIGIT | TEENS | TENS [DIGIT]
TRIPLE = DOUBLE | DIGIT hundred [DOUBLE]
INPUT = TRIPLE | TRIPLE thousand [TRIPLE] | TRIPLE million [TRIPLE thousand] [TRIPLE] | zero
where:
- lower case symbols are actual valid strings,
- the pipe symbol (|) is an OR,
- upper case symbols can take on one of several values,
and
- square brackets indicate optional elements.
Specifically:
- DIGIT is the set of all non-zero single-digit strings,
- TENS is the set of all 2-digit numbers with a "1" as the left
digit,
- TENS is the set of all 2-digit numbers with a "0" as the right
digit (excluding 10),
- DOUBLE is the set of all 1 or 2-digit numbers,
- TRIPLE is the set of all 1, 2 or 3-digit numbers, and
- INPUT represents all valid inputs to your program and is the
set of all 0 to 9-digit numbers.
Notes:
Examples
Program Invocation
./project0
Input Text
one hundred ninety two
eighteen
twenty three thousand four hundred
one hundred thousand one
Output Text
192
18
23400
100001
Program Invocation
./project0 H
Input Text
one hundred twenty three million four hundred fifty six thousand seven hundred eighty nine
twelve million eighteen
fourteen thousand
one hundred one
eleven
one
zero
Output Text
75BCD15
B71B12
36B0
65
B
1
0
Program Invocation
The following example invocations must result in an error message being printed and the program terminating:
./project0 a
./project0 h o
./project0 h o H
Hints
Misc
- Remember that characters use the ASCII encoding. You can take
advantage of this to make your implementation simple.
- For each triple of digits, the code to interpret the text is
the same, except for the suffix (million, thousand).
- Useful C functions:
- fgets()
Example:
char buf[100];
fgets(buf, 100, stdin);
This call will read at most 100 characters from the STDIN pipe (it stops when 100 characters are read, a newline is found or the end-of-file is reached). fgets() returns buf if something is read and NULL if the end-of-file marker is reached.
- printf()
Formatted printing of values.
- fprintf()
This function behaves like printf(), except you can specify which stream will receive the output (first parameter). stdout and stderr are valid choices here.
- strcmp()
This function compares two strings and returns 0 if they
are identical.
Remember that you cannot compare
two strings by comparing their pointers directly (you
will just be asking whether the two strings
are located at the same place in memory). The
strcmp() library function behaves very similarly to other
comparison functions that you are used to: it returns 0 when
you have an exact match (and a positive/negative value
depending on whether the first argument comes after/before the
second argument).
- You can ask your VM about any of the above functions. For example, type the following into your shell:
man fgets
- Useful libraries (which define the above functions):
- You can simulate an end-of-file marker (EOF) at the terimal by typing CTRL-d
Parsing Lines
There are lots of ways to parse a string into the individual tokens
(tokens are symbols that are separated by white space). Here, we will
use the string tokenizer provided in the string library in C.
The local data structures that you need are:
const char SEPARATORS[] = " \t\n"; // Possible separators between tokens
char in_buffer[INBUFSIZE]; // Input buffer from STDIN
char * args[MAX_ARGS]; // Array of pointers to strings
char ** arg; // Working pointer that steps through the args (a pointer to a pointer to a string)
After receiving an input line into in_buffer (e.g., using
fgets()), you can split the characters in the buffer into distinct
tokens as follows:
arg = args;
*arg++ = strtok(in_buffer,SEPARATORS); // tokenize input
while ((*arg++ = strtok(NULL,SEPARATORS)));
Here, SEPARATORS is a string that contains all of the characters that
are valid indicators for splitting the input string up. At the end, of
the loop, arg will be an array of strings (technically, it is
an array of pointers to characters). The arg in the array after the
last argument will be set to NULL.
Arrays of Strings
In C, you can declare an array of strings as follows:
const char * table[] = {"alpha", "bravo", "charlie", "delta", "echo", "END"};
Then, you can write code that uses this table. For example, the
following will print out all elements of the table and the lengths of
each string (except the last one that is being used as a marker):
for(int i = 0; strcmp(table[i], "END"); ++i) {
printf("%d: %s (%d)\n", i, table[i], strlen(table[i]);
}
Submitting Your Program
- Your submission is composed of the following files, named exactly as shown (including casing):
- project0.c: your source file
- Include your name and project number at the top of the file
- Makefile: the makefile that provides the
following functionality:
- all: compiles your program (this is the
default behavior), producing an executable file
named project0
- clean: deletes the executable file and any intermediate files (.o, specifically)
- README.txt: documentation
- Include your name and project number at the top of the file
- Document any Internet resources that you consulted (URLs)
- Document any peer class members that you
discussed your solution with. Note that you
may not look at or share code that solves this
specific problem
- Documentation requirements: function-level and inline
documentation are important components of writing code. They help
you to organize your thoughts while programming and help to
communicate the method and the intent of the code to your future
self or to collaborators (of course, you will not have collaborators
in this class). While we will not be specifically grading
documentation in this class, we will not be able to comment on your
code unless it is sufficiently documented. This will be true whether
you are asking for help before the submission deadline or looking
for feedback on your solution after the deadline. In short, you
should take the time to properly document your code as you develop
it.
- Submit your files:
- Create a zip file named project0.zip containing
your source code, Makefile and README.txt file. The
following Linux shell command will do this for you:
zip project0.zip *.c Makefile README.txt
Note I: this is a good thing to add to your Makefile.
Note II: do not include object files, executables or
temporary files in your zip file.
- Submit your zip file to Gradescope (access via Canvas).
Shortly after your submission, you will receive
automated feedback and a grade for the
correctness component of your grade.
- You may submit multiple times until the deadline.
- To be counted as on time, your solution must be submitted to the Gradescope server by 11:45:00 pm on Tuesday, Sept. 15th. Grade penalties will be imposed for late submissions (see the syllabus for the details).
Grading Criteria
- README.txt (10%): contains the required information
- Makefile (10%): satisfies the make file requirements
- Correctness (80%): passes all of the (hidden) unit tests
Testing
You are responsible for generating your own test cases.
We have provided a couple of samples to get you started, but keep in
mind that we have other tests that are hidden from you.
- Download the following file: project0_public_tests.tar
- Copy the file into your working project directory on your VM
- In a shell on your VM: cd to your project directory and
type:
tar -xvf project0_public_tests.tar
This will unpack this archive file into your local
directory. (do an ls to see what new things have appeared)
- Invoke a test:
./project0 < input1.txt > out.txt
This will start you program and pipe the contents of the
specified file into your program (as if you typed the contents). The
output from your program will be stored in the file output.out
- Compare your program against the reference file:
diff -b -B out.txt output1_default.txt
This compares the contents of these two files. Any differences
will be highlighted on a line-by-line basis. If diff
does not generate any output, then the two files are identical
(the state that you want to be in). Note that the parameters
that we give to diff ignore extra spaces and extra
newlines.
- Alternative method for comparison
diff -y -b -B out.txt output1_default.txt
This will print out the two files in question, side-by-side. This
facilitates a visual comparison of the two files.
Addenda
andrewhfagg at gmail.com
Last modified: Tue Sep 8 14:33:04 2020