BU CAS CS 113
Introduction to Computer Science II with Intensive C
Fall 1996


Assignment 9: Tables Using Binary Search Trees

Deadline

December 11, 1996.

LATE WORK WILL ONLY BE ACCEPTED UNTIL DECEMBER 12 (one day late). TURN IN AS MUCH AS YOU HAVE ON DECEMBER 12!.

What to Submit

You should submit four files. Be sure the files you submit have exactly the following names: hw9-table.c hw9-types.h hw9-types.c hw9-main.c .

These programs are to be electronically submitted by using the submit program on csa. The code you submit should conform with the program assignment guidelines.

The ADT Table

Your task is to implement the following interface using Binary Search Trees:

/*  
 * File: table.h
 * -------------
 * This is the interface for a general table.
 *
 * Elements of the table have a key, by which they are stored and retrieved,
 * and some additional data.  Access to the table is only allowed via keys.
 * Duplicate keys are not permitted.
 */

#ifndef _table_h
#define _table_h

#include "genlib.h"			/* need bool typedef */

/*
 * Types: tableElementT, tableKeyT, tableDataT
 * -------------------------------------------
 * Items stored in the table have a key of type tableKeyT and some additional
 * data of type tableDataT.  The actual type of things stored in the table
 * is therefore tableElementT, a struct containing fields key and data.
 *
 * The types assigned to the keys and the data are defined (by the client)
 * in tabletypes.h
 */

#include "tabletypes.h"      		/* need tableKeyT and tableDataT*/ 

typedef struct tableElementT{
  tableKeyT key;
  tableDataT data;
}tableElementT;

/*
 * Function: KeyCompare
 * Usage if ( KeyCompare(key1, key2) == 0 );
 *       if ( KeyCompare(key1, key2) < 0 );
 *       if ( KeyCompare(key1, key2) > 0 );
 * ----------------------------------------
 * This compares two keys returning 0 if they are the same,
 * a negative integer if key1 is less than key2,
 * a positive integer if key1 is greater than key2.
 *
 * This function is provided by the client in accordance with tableKeyT.
 */

int KeyCompare(tableKeyT key1, tableKeyT key2);

/*
 * Type: tableADT
 * --------------
 * The actual implementation of a table is completely hidden.  Client will
 * work with tableADT which is a pointer to underlying tableCDT
 */

/* note:  need word struct below so that the compiler knows at least that
 * a tableCDT will be some sort of struct. 
 */

typedef struct tableCDT *tableADT;	



/*
 * Function: NewTable
 * Usage: table = NewTable();
 * -------------------------
 * A new empty table is allocated, created and returned.
 */

tableADT NewTable(void);

/* Function: FreeTable
 * Usage: FreeTable(table);
 * -----------------------
 * This function frees all memory associated with the table.  table
 * may not be used again unless NewTable(table) is called first.
 */

void FreeTable(tableADT table);


/*
 * Functions: TableInsert, TableRemove, TableUpdate, TableRetrieve
 * Usage: 	success = TableInsert(table, key, data);
 *   		success = TableRemove(table, key);
 *        	success = TableUpdate(table, key, newData);
 *   		success = TableRetrieve(table, key, &data);
 * ----------------------------------------------------
 * TableInsert and TableRemove are used to insert new elements and remove
 * old elements from the table.  
 *
 * TableUpdate replaces the data in the table associated with key with
 * newData.
 *
 * TableRetrieve stores in data the information in the table associated 
 * with key.
 *
 * All of these functions return a boolean value indicating whether the 
 * operation is successful.  TableInsert may be unsuccessful if the table is
 * full or if the key already existed in the table.  The other operations 
 * are unsuccessful if the key searched for is not in the table.
 */

bool TableInsert(tableADT table, tableKeyT key, tableDataT data);
bool TableRemove(tableADT table, tableKeyT key);
bool TableUpdate(tableADT table, tableKeyT key, tableDataT newData);
bool TableRetrieve(tableADT table, tableKeyT key, tableDataT *dataPtr);


/* 
 * Function: TableTraverse
 * Type: VisitFuncT
 * Usage: TableTraverse(table, &Visit);
 * ------------------------------
 * TableTraverse traverses the entire table in order and performs the function
 * Visit on each element.  
 *
 * Visit must be a function which takes two parameters of type tableElementT 
 * and returns another.  This works as follows:
 *
 *   The first parameter is intended to be the item in the table 
 *   currently being visited.  
 *
 *   The second paramter is used to receive information from the previous
 *   visit.  (Or from TableTraverse itself in the case of the first visit.)
 *
 *   The return value passes information to the next visit.  (Or is returned 
 *   from TableTraverse in the case of the last visit.)
 *
 * There are many situations in which the second parameter and the return
 * value are simply ignored.  Example:  simple printing of the table.
 *
 * The ability to pass information from one visit to the next allows one to
 * do things like, e.g., locate an item with the largest value in some 
 * field of the data.
 * 
 * IMPORTANT NOTE!!!
 * ================= 
 * Visit must not make any calls to TableInsert() or TableDelete(), as this
 * may change the table being traversed.  Using TableTraverse with such a Visit
 * is an error and may lead to unpredictable behavior of the program.
 */

typedef tableElementT (*VisitFuncT)(tableElementT, tableElementT);

tableElementT TableTraverse(tableADT table, 
                            VisitFuncT VisitPtr,
                            tableElementT initElem);

/*
 * Functions: TableIsFull
 * Usage: if (TableIsFull(table)) ...
 * -----------------------------------
 * These return TRUE if the table is full.
 */

bool TableIsFull(tableADT table);

/*
 * Function: TableSize
 * Usage: n = TableSize(table);
 * -----------------------------
 * This returns the number of elements currently in the table.
 */

int TableSize(tableADT table);

#endif

/*   ------------< end-of-file "table.h" >------------     */

You do not need to submit hw9-table.h. You are not allowed to modify it.

Some of this has already been done in class. I have provided you some of the code you will need in hw9-table.c. And we have discussed much of the rest of the code you need to write.

Files: hw9-table.c

Using the Table ADT: Counting Words in a File

Write a program (in hw9-main.c) which reads a file and prints a report about the words in the file and how often they occur. The reports will consist of lines which begin with a frequency and then the word with a tab separating them. The words whould occur in alphabetical order.
3	a
2	is
3	rose

All of the information should be passed to the program via program arguments as follows.

-m : short for "more", print only words which occur
          more than  times.  

-l : short for "less", print only words which occur
          fewer than  times.  

-c : short for "common", print only the  most frequent words.

-f : short for "file", reads words from .
Update: Simplified command-line arguments (10 Dec 96). There will be at most one argument of type -m, -l or -c (no combinations, no repetitions) and it will occur first. there may still be multiple files. You may treat any other kind of command line as an error (and respond with the appropriate message). Thus the following need not be implemented:
words -m 2 -l 3 -f somefile
words -c 2 -l 5 -f somefile
words -f somefile  -l 5 
(It will not hurt if they have been implemented, but I will not test any calls of those kinds.) All of the command arguments (-m, -l, -c) must occur before any file arguments (-f). If multiple files are given, then all files given should be read and treated like one large file, that is word counts will refer to how often a word occurs in all the files together. If the same type of command argument is given more than once, only the last occurance is used for determining the type of report. (You are not required to handle multiply occuring arguments of type other than -f.) Otherwise the effect is cummulative. If no file argument is given or if a command is given which is not one of those above, an appropriate message should be displayed which tells the syntax and explains the various commands. If a file is given, but no other commands, then a list of all words is displayed (along with their frequencies) in alphabetical order.

Words.A word is any string of characters which contains only letters. All punctuation, hyphens, digits, spaces, etc. serve to separate words, but are otherwise ignored. The maximum length of a word is 25 letters. (Any additional letters are discarded.) Case is ignored and all words are treated as if all letters were lower-case when displaying results.

Partial implementaion. If you are unable to implement any of these options, be sure that your program still does something and print out a message saying what it was supposed to do and what it has done instead. The most difficult option is -c. It is not too hard to do -c 1, but it gets more difficult for -c 2 and greater. You may resolve ties in any manner you wish, but it is probably easiest to do them in alphabetical order. (See the examples below.) Implementing the -c flag with values 2 or greater is extra credit.

Examples. Here are some examples. Suppose that our executable is called words and we have files rose, time, and huh. Which contain the following: "A rose is a rose is a rose", "Now is the time for all good men to come to the aid of their country.", and "I thought that that was that. That was not the case."

  1. words -f rose produces the output above.
  2. words -m 2 -f rose produces only:
    3	a
    3	rose
    
  3. words -c 1 -f rose -f time -f huh produces
    4 	that
    
  4. words -m 2 -l 4 -f rose -f time -f huh produces
    3	a
    3	is
    3	rose
    3	the
    
    or a usage message (as per update).
  5. words -c 2 -f rose -f time -f huh produces
    4	that
    3	a
    

Files.

Testing your table code

I have written a little program hw9-test.c which you can use to test your table code. For this to work, you must modify your hw9-types.h and hw9-types.c so the the keys are characters and the data integers. (Save your originals!) Here are example versions of hw9-types.H and hw9-types.C which aren't pretty, but do work. I've named them with capital C and H just to avoid name collisions, you will have to rename them. Or you can modify hw9-test.c to work with whatever your types are. The Makefile includes the instructions for compiling, type make hw9-test (after appropriate changes have been made).

Makefile

Use the makefile for this assignment to make sure that your file names are correct. This file is also located in ~cs113/F96/assignments on csa.

Academic Honesty and Collaboration

It is reasonable to discuss with others possible general approaches to problems. It is unreasonable to work together on a detailed solution, to copy a solution, or to give away a solution. If your common discussion can be detected by looking at the solutions, then there is too much collaboration. Such instances of academic dishonesty may result in a course grade of F or expulsion from Boston University.

Do not allow your work to be used by others:

Warning: If someone cheats by using your work, you will also be penalized.