CSE 333 Exercise 6

Out:   Friday, January 16
Due:   Wednesday, January 21 by 11 AM
Rating:   2 (note)
CSE 333 Exercise Rating Scale

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 or hexdump -c foo.txt to look at the bytes in a file foo.txt in 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.
  • fclose to close the file.
  • fseek and ftell to figure out how large the file is.
    • We'd suggest you fseek(f, 0, SEEK_END); and then size = ftell(f); to get the file size in bytes.
  • fseek and fread to read the file's contents, in reverse order, byte-by-byte.
  • printf, with the %c format 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 (gcc and valgrind).
  • 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 .c file 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.