Programming Project: File Listing
Okay, it's finally time for your first C++ programming project! And, instead of doing something somewhat meaningless, you'll get to write a program that's actually useful!
You're to write a program that generates a file listing. A file listing is a copy of C++ source code that has a line number preceding each and every line of code. For example, take a look at SampleListing.txt to see what kind of output your program will generate. Notice that each line has a four-digit number indicating the line number; this is quite helpful when looking at and discussing source code, you can use the line numbers to direct everyone's attention to a particular line of code.
When you run the program, the user at the keyboard should be prompted for the name of the C++ source code file to use. If the input filename isn't valid, an error message is displayed and the program will end. Otherwise, the program proceeds to create an output file of the same name, but with a .lst filename extension instead of .cpp. Then the input file is copied to the output file, one character at a time, but each line is prefixed with the current line number.
To help you get started, you'll find a Project1 subdirectory in your ssh account, and in there you'll find a starter kit called FileListingStarterKit_Spring2013.tar.gz. To extract the files out of the starter kit, just type this at the command line prompt:
tar xvzf FileListingStarterKit_Spring2013.tar.gz
Once you do that, you'll find in your Project1 directory a sample executable named flist. This is an executable file just like all the a.out files you've created, so to run it all you need to do is to type the file name prefixed with a leading dot-slash, like ./flist. Once you do that, you'll be prompted for the name of a C++ file so you can create a listing. (It would probably be helpful to copy a few C++ files into that directory before you run the program so you can try it out.) You'll also find a skeletal source code file flist.cpp to give you a boost! In it you'll find that you need to implement a few functions:
FnameIsValid – This function receives a cstring from the caller that contains a potential input filename. The task to accomplish here is to determine if the filename is valid or not. Just what constitutes a legitimate input file name? Well, it must have a .cpp extension, but in addition to that the file name must consist of only letters, digits and underscores (just like an identifier in C++). If the filename is valid, this function should return a value of true, otherwise it should return false.
CreateListingFname – This function is responsible for generating the name of the listing file. It takes as input the base addresses of two character arrays: the first contains the candidate filename (which may or may not be valid), and the second is just a buffer where the listing filename is to be stored. If it's determined that the input filename is valid, the function should derive the listing filename, copy it to the second character array and return a value of true; otherwise, a value of false should be returned.
ListFile – This function will create the actual listing file. It receives as input references to the input file stream and the output file stream, both of which are freshly opened and ready to go. It also has parameters that allows the caller to specify the field width to use for the line numbers, as well as the character to use to fill unused space within the field widths. This function returns the total number of lines written to the output file.
WriteLine – This function is called by ListFile and will write a single line of text from the input file to the output file. It receives references to both file streams from the caller. If end-of-file is encountered, the function will return true to the caller, else return a value of false. NOTE: you must use character I/O in this function.
There are some other functions from the standard libraries that you might find useful:
.fill – This function is an output stream member function, and it's used to specify the character to use for filling unused space in a field width. It takes a single argument, which is the fill character. I happen to have a few notes I wrote on the subject, you can read them in NotesOnFill.txt.
.peek – This function is an input stream member function. It takes no arguments, and returns the next character that's on the input stream, but it doesn't remove it from the input stream, it just lets you take a peek! This function can be useful if you want to see if there's actually another character that can be read from the input stream or not.
.putback – This function is an input stream member function. It only takes one argument, which is a single character. This might be helpful if you find you've removed a character from an input stream, but want to put it back so it will be there for the next .get function call.
You don't have to use any of these functions if you don't want to, I'm only putting them up here just in case you find them helpful.
Before you begin writing any code, you might find yourself able to save a lot of time and frustration simply by thinking a lot! Don't commit to the first solution that seems like it will work, you really want to consider all of your options before making that kind of investment. Once you convert your ideas into code, it becomes much more difficult (and time-consuming) to fix your mistakes at that point than it would be to simply reject ideas that haven't been committed to a file yet.
So when is this thing due? Your implementation is due on Wednesday, April 17th, giving you an entire week to finish it off. Just leave your file flist.cpp in the Project1 directory so I can fetch it by the time our class starts. Just in case any issues arise that you may need to know about, you should probably check the Announcements page from time to time to see if any problems you may be experiencing have already been handled. Best of luck!
S. Edwards, 04/09/13, 11:44pm