This lab will show you how to use structures to organize data.
Files referred to here are available in this on-line directory:
http://www.tricity.wsu.edu/~bobl/cpts121/lab07_structures
One of those files, writeup.html, is this document in HTML. We'll download other files from this directory below.
Plug your thumbdrive into your workstation. Give it a few seconds to be recognized by Windows and then create a MinGW terminal emulator. In that emulator, create a new directory for this lab and cd to it:
$ cd /e/cpts121 $ mkdir lab07 $ cd lab07
As always, keep all your work for this lab in this directory.
As an example, we'll create a small database of movie monsters. Here is the data we'll start out with, together with the type of each datum:
attribute | type | definition |
---|---|---|
name | char [15] | the monster's name |
film | char [50] | the (first) film they appeared in |
year | int | what year the film came out |
weakness | char [25] | what defeated them |
defeatedBy | char [30] | who defeated them |
rating | double | the film's Internet Movie Database rating |
Deciding what your data is and how to represent it is an important part of software design. Taking extra time here and thinking about all the angles can save much grief later on.
We'll start by creating a C struct to hold our monster data:
Download the file monster_tplt.c to your lab directory.
Rename it:
$ mv monster_tplt.c monster.c
Here's what it looks like:
#include <stdio.h> #include <string.h> /* * First, we #define sizes of every string (char array) attribute in * the database. This is its maximum length plus one (and its minimum * width for table printing purposes). */ #define NAME_SIZE 15 /* add additional *_SIZE #define's according to the table above */ /* * This "struct" declares all information we want to maintain in the * "monster" database. All strings have the #define'd sizes given * above. */ typedef struct { char name[NAME_SIZE]; /* * Add additional elements according to the table above and using * the *_SIZE #define's (for the char arrays only). */ } Monster; /* * Initialize an array of structs to form the database. */ Monster monsters[] = { { /* We'll initialize the first structure by position. */ "Count Dracula", "Dracula", 1931, "wooden stake", "Van Helsing", 7.6, }, { /* * We'll initialize the second stucture by attribute name, * rearranging the order just to show we can do it. */ .rating=8.0, .film="Frankenstein", .weakness="fire", .name="The Monster", .year=1931, .defeatedBy="villagers", }, /* add some more favorites here, if you have time */ /* * A name of zero length terminates this list. */ { "", }, }; void monster_print(Monster monster) /* print a "monster" */ { int colonIndent = 15; /* set this empirically so the ':'s line up */ /* * The following shows a good way to print out attributes: one per * line with the attribute name appearing as "ragged left" * followed by a ':'. */ printf("%*s: %s\n", colonIndent, "Name", monster.name); /* * Add additional printf() calls similar to the one above. Be sure * to use the format that matches the attribute type. */ } int main(void) { /* * for each `monster[i]` in the `monsters` array (as long as * `monster[i].name[0] != 0`) * print it using monster_print() * print an extra newline to separate outputs */ return 0; }
Follow the instructions in the comments to complete the Monster struct definition and .
Compile your code as usual:
$ gcc -Wall monster.c -o monster.exe
When you run it, your result should look like this:
$ ./monster Name: Count Dracula Film: Dracula Year: 1931 Weakness: wooden stake Defeated By: Van Helsing Rating: 7.6 Name: The Monster Film: Frankenstein Year: 1931 Weakness: fire Defeated By: villagers Rating: 8.0
A convenient way to display struct data is in a table, and the HTML format used by browsers is a very flexible way to do this. We'll use a template plus parts of your monster.c to create a new source file monster_html.c that will output the same data in HTML format:
Download the file monster_html_tplt.c to your lab directory.
Rename it:
$ mv monster_html_tplt.c monster_html.c
Here's what it looks like:
#include <stdio.h> #include <string.h> /* * Copy the Monster structure definition here. */ /* * Initialize an array of structs to form the database. */ Monster monsters[] = { { /* We'll initialize the first structure by position. */ "Count Dracula", "Dracula", 1931, "wooden stake", "Van Helsing", 7.6, }, { /* * We'll initialize the second stucture by attribute name, * rearranging the order just to show we can do it. */ .rating=8.0, .film="Frankenstein", .weakness="fire", .name="The Monster", .year=1931, .defeatedBy="villagers", }, /* add some more favorites here, if you have time */ /* * A name of zero length terminates this list. */ { "", }, }; void monster_printHtmlTableHeader(void) /* print the header for an HTML table of monster */ { printf("<tr>\n"); /* HTML table rows begin with this tag */ /* * Here's how to print the first column, which is "Name": */ printf("<th>Name</th>\n"); /* * Insert additional printf()s for the other column names, in * order. */ printf("</tr>\n"); /* HTML table rows end with this tag */ } void monster_printHtmlTableRow(Monster monster) /* print the data in "monster" as an HTML row */ { printf("<tr>\n"); /* HTML table rows begin with this tag */ printf("<td>%s</td>\n", monster.name); /* * Insert additional printf()s for the other attribute values, in * order. Be sure to choose the right format for printf(). The * `rating` should be printed with one decimal place. */ printf("</tr>\n"); /* HTML table rows end with this tag */ } int main(void) { /* * print "<table>" to begin the HTML table * print the HTML table header using monster_printHtmlTableHeader() * for each monster in the `monsters` array (as long as name[0] != '\0') * print it as a row in the table using monster_printHtmlTableRow() * print "</table>" to end the HTML table */ return 0; }
Follow the instructions in the comments to insert the code from monster.c and add additional code to output HTML.
Compile your code as usual:
$ gcc -Wall monster_html.c -o monster_html.exe
When you run it, you should get this:
$ ./monster_html <table> <tr> <th>Name</th> <th>Film</th> <th>Year</th> <th>Weakness</th> <th>Defeated By</th> <th>Rating</th> </tr> <tr> <td>Count Dracula</td> <td>Dracula</td> <td>1931</td> <td>wooden stake</td> <td>Van Helsing</td> <td>7.6</td> </tr> <tr> <td>The Monster</td> <td>Frankenstein</td> <td>1931</td> <td>fire</td> <td>villagers</td> <td>8.0</td> </tr> </table>
which is pretty ugly, but do this:
$ ./monster_html >table.html
and then open table.html with your browser of choice. (Just clicking on it from the file browser should do this.)
Much better!