CSE 333 Exercise 6
Due: Wednesday, January 21 by 11 AM
Rating: 2 (note)
Each exercise this quarter is rated on a integer scale of 1 – 5, inclusive, with 1 being the "least time-consuming" and 5 being the "most time-consuming".
This difficulty scale is meant as a rough guide for you in predicting the amount of time to set aside for each exercise as you balance the work required for 333 with your other obligations. However, it is necessarily imperfect as everyone's set of circumstances and experiences with the exercises differ. If your experience with an exercise does not align with its rating, that is not a reflection of you or your abilities.
Goals
- Learn how to use various parts of the standard C file I/O library.
- Practice reading reference material such as Linux manual pages.
Problem Description
Write a C program that accepts a filename as a single command-line
argument.
The program should read the file, copying the contents of the file
to stdout in reverse order, character by character
(or, more precisely, byte by byte).
Your code should read the bytes one-at-a-time and print them
immediately.
Do not read the entire file into memory and print it backwards or
create a reversed copy of the data and print that.
For example, consider a file name foo.txt in the
current directory that contains the following 7 bytes (the 7th byte
is the newline character at the end):
hello!
- You can use linux commands like
hexdump -C foo.txtr orhexdump -c foo.txtto look at the bytes in a filefoo.txtin hex and in other formats to see exactly what's there, including invisible characters. Many text editors also have modes to do this.
Running the program should result in the following:
$ ./ex6 foo.txt !olleh$
- Pay careful attention to where the newline and other characters are in this output, including the new command line prompt immediately following the 'h'.
Implementation Notes
Standard Library Functions
You will need to use several C standard library functions. In particular, you should use:
fopen, with mode"rb", to open the file.fcloseto close the file.fseekandftellto figure out how large the file is.- We'd suggest you
fseek(f, 0, SEEK_END);and thensize = ftell(f);to get the file size in bytes.
- We'd suggest you
fseekandfreadto read the file's contents, in reverse order, byte-by-byte.printf, with the%cformat code, to print out the characters (bytes) of the file one at a time.
Remember to consult the
C/C++ Reference Material
and
Linux manual pages
to learn how to use each of these functions (in the
stdio.h header).
Function Parameter Type
Some of these library functions are quite old and have parameters
or results whose type is long.
Style guides and programs like cpplint generally
discourage using long and recommend using types like
int64_t instead.
But for these library functions, it's appropriate to use variables
of type long to match function parameter and result
types, since that guarantees an exact match regardless of the exact
size of long on the underlying machine.
Feel free to ignore any cpplint warnings about using
long in these situations.
Style Focus
File Descriptors
A file descriptor gives us the ability to work with a file at a high level. Under the hood, file descriptors maintain a lot of states which takes up memory. Since there is memory associated with file descriptors, it is good style and practice to close file descriptors on all exit paths when they are no longer needed. This will prevent memory leaks!
Submission
Submit the following file(s) by creating an ex6-submit tag in your exercise repo before the assignment deadline. The file(s) should be located in the exact directory listed below, including capitalization:
ex6/ex6.c
Your code must:
- Compile without errors or warnings on CSE Linux machines
(lab workstations,
attu, or CSE home VM). - Have no runtime errors, memory leaks, or memory errors
(
gccandvalgrind). - Be contained in the file listed above that compiles with the command:
$ gcc -Wall -g -std=c17 -o ex6 ex6.c
- Have a comment at the top of your
.cfile with your name(s) and CSE or UW email address(es). - Be pretty: the formatting, variable and function names,
commenting, and so on should be consistent with class style
guidelines. Additionally, the linter shouldn't have any complaints about your
code (
cpplint.py --clint). - Be robust: your code should deal with hard-to-handle/edge cases and bogus user input (if there are any) gracefully.