CS140 -- Lab 4
This lab will give you practice with a number of programming concepts, including:
- Dr. Plank's Fields library,
- string manipulation,
- pointers,
- memory allocation,
- structs,
- linked structures, and
- generating test cases for your code
Files that you will need
Blog
A blog is an on-line journal where you or a group of people can post
entries about their daily activities, hobbies, personal experiences, etc.
In many ways a blog is like an on-line diary. You are going to write
a program named blog that reads blog entries and outputs
them as formatted html.
The blog entries will be presented to you in
chronological order, with the least recent post (i.e, the oldest post)
presented first, and the most recent post (i.e., the latest post) presented last.
You will output
the blog entries in reverse chronological order, with the most recent post
appearing first, and the least recent post appearing last.
A blog entry will have a person's name, date of creation, and time of creation on
one line, and then one or more lines with the person's comments. Each
blog entry will be separated by a blank line. You can see a sample input
file here. As you can see, dates are presented
in mm-dd-yy format. The name, date, and time will each be a single
field.
Your program will format each blog entry into a row in an html table. Do
not worry if you do not know how to create an html table. I will explain how
to do so shortly. Each row will have four columns for the person's name,
posting date, posting time, and comment. You will not need to do any processing
with either names or times. However, you will need to convert dates
from their "mm-dd-yy" format to a format that looks like "month dd, 20yr"
where "month" is a three letter abbreviation for the month. For example,
"03-20-08" will get translated to "Mar 20, 2008" (I have the list of
abbreviations that you should use printed below). A formatted output html page for
the sample input can be found here. Note that the
blog entries have been reversed from the sample input file, so that they are
now ordered from newest to oldest. If you find
the "page source" option in your browser, then you can see what the actual
html looks like. This is the html that your program will produce.
Data Structures
You will need to use the following data structures for your program:
- You will use an inputstruct to read lines from the blog file.
- You will use a FILE * pointer to reference the output html
file and will use fprintf to write lines to your html file.
- You should use a singly linked list to store the blog entries. Since I
am asking you to reverse the order of the blog entries, so that they
appear from most recent to least recent, you should add each new blog
entry to the front of the linked list. For this lab do not use my
sllist library. Instead add a link field to your blog entry struct, as
described in the next list item.
- You will need to use a typedef and a struct for storing each blog entry.
You should create a struct using the typedef and assign
an appropriate name to the type you have created. The struct should
store the following information:
- the name of the person who wrote the entry,
- the date they posted it,
- the time they posted it,
- the comment they wrote, and
- a pointer to the next blog entry in the list. Since the pointer points
to the next blog entry, it will point to a blog entry struct. Therefore,
as discussed in class, you will need to name the struct (i.e., you cannot
use an anonymous struct).
It is mandatory that you place the declaration for this struct in
a header file named blog.h
and that you include this header file in your program.
- You will use a dynamic array to store the comment field.
Program Design
Roughly speaking, your program will be designed as follows:
- You will need to read from the command line
the names of the input file containing the
blog entries and the output file to which you will write your html
code from the command line.
- You will need to write a while loop that reads each line from the
blog file using the fields library:
- When you encounter a blank line you will start a new blog entry.
- When you read the first line of a blog entry, you should check to
ensure that it contains exactly three fields. If it does not contain
exactly three fields, you should print an error message that lists the
line number and that tells the user what the problem is. You can mimic
the error message I use in my executable. Your program should then exit
without creating an output file.
If the line contains exactly three fields, then you will malloc a
blog entry struct and save the person's name and the time at which the
entry was posted. You will need to convert the date string to an
appropriately formatted string using sprintf. sprintf
is just like fprintf and printf, except that it
writes into a string, rather than a file or to stdout. You need to
provide a string that is big enough to contain the formatted string that
you wish to create. Remember to include an extra space for the null (\0)
character. For example, if I have two string variables named lastname and
firstname, and I want to create a string with the format
"lastname, firstname", I can use the following sprintf statement to
create the desired string:
char *formatted_name;
// calculate the length of the formatted name. The extra 3 characters
// are for the comma, the space between lastname and firstname, and
// the null character, \0, at the end of the formatted name
int name_length = strlen(lastname) + strlen(firstname) + 3;
sprintf(formatted_name, "%s, %s", lastname, firstname);
You should use the following abbreviations for the months:
1 | 2 | 3 | 4 | 5 | 6 |
7 | 8 | 9 | 10 | 11 | 12 |
Jan | Feb | Mar | Apr | May | Jun |
Jul | Aug | Sep | Oct | Nov | Dec |
Hint: You can use the strchr function to help you convert the
'-'s in the date string to '\0's, thus giving you a string of the form "mm\0dd\0yy".
You can now treat the original string as three separate strings and extract
the month, day, and year using sscanf.
- When you read the remaining lines of a blog entry, you should simply
concatenate them together into one long string. You do not know in
advance how long your eventual string will be or how many lines
you will have to read. Therefore I suggest that you use a dynamic
array to hold the comment as you construct it, and that you resize
the array as you add each new fragment of the comment. Hence, as you
read each comment line (i.e., each comment fragment),
your program 1) figure out how long your comment will be
once you concatenate the new fragment to the end of the existing comment
2) realloc your comment string so that it has this newly compute length,
and 3) concatenate the new fragment to the end of
the realloced comment string.
- Once you have finished reading your blog entries, you should write them
to your output file. To start your table, output the following two lines,
exactly as I have written them, replacing output_file with the
name of your output file pointer:
fprintf(output_file, "
\n");
fprintf(output_file, "Name | Date | Time | Comment |
\n");
The first line creates a table that has a 1 pixel wide border, no frame, lines
between all the table cell entries, and 5 pixels of padding around each table
cell. The second line creates a set of column headings and indicates that
the comment column should take up 50% of the browser window. Note that I used
\" so that fprintf would know that I want to print the
\" rather than have it terminate the format string, and
I used %% to tell fprintf that I want it to output a % sign, rather
than interpret the % sign as the start of a conversion specifier.
You will then output each row of the table. Each row should start with the
tag <tr> and should end with the tag </tr>.
Each column should start with the tag <td> and should end with
the tag </td>. For example, to get the following column:
Brad | Aug 8, 2009 | 12:20pm | Climbing Mt. Whitney |
you would need to output the following lines of html:
Brad |
Aug 8, 2009 |
12:20pm |
Climbing Mt. Whitney |
Testing Your Code
You need to start to get in the habit of thinking about the various types
of errors and boundary conditions that can arise and then testing for them.
Several errors and boundary conditions that I expect you to test for in this
lab include:
- error conditions
- wrong number of command line arguments
- invalid blog file name
- inability to open the output file. One way you can test whether or not
your code works is to deny yourself write permission for the output
file. You can do so by first creating a file and then using chmod to
deny yourself write privileges. For example:
chmod u-w brad.html
The string "u-w" says to subtract write permission from the user, which
in this case is yourself. You can re-establish write privileges to the
file by using "chmod u+w brad.html".
- improper number of fields on the first line of a blog entry
- boundary conditions
- empty blog file: just output the headers for the table (see my
executable)
- one or more empty lines at the end of the blog file
- a very large blog file with a large number of entries
- a very large blog entry (i.e., a blog entry whose comment runs
over a great many lines)
- normal conditions that your program should handle
- more than one line between blog entries
- dates whose month or day is a single digit
In this lab you do not have to worry about the date being misformatted or
the month or date being too large. You
may assume that a date always correctly appears as "mm-dd-yy", although the
month and day may be single digits. The year will always be two digits.
Note that blog_data.txt and empty_blog.txt test some of
these boundary conditions, but not all of them.
What to Submit
Submit a source file named blog.c and
a header file named blog.h.