UMBC CMSC201, Computer Science I, Spring 1994
Sections 0101, 0102 and Honors
Project 5
Due: May 12, 1994
Click here for the latest news and hints.
Objective:
The objective of this assignment is to practice using pointers
and structures.
Assignment
Your assignment is to re-implement Project 4 using the following
strategy.
count = GetInteger() ;
i = 0 ;
while (TRUE) {
if ( EndOfInput(& input) ) break ;
spaces = GetSpaces(& input) ;
WriteOut(& output, spaces) ;
if ( EndOfInput(& input) ) break ;
word = GetWord(& input) ;
i = i + 1 ;
if (i % (count + 1) != 0 ) WriteOut(& output, word) ;
}
Flush(& output) ;
Here, word and spaces are strings and i and
count are integers. We want the function EndOfInput
to be true when there are no more words or spaces to be processed.
The function GetSpaces should return the possibly empty
run of non-alphabetical characters between the words; and the
function GetWord should return the next run of alphabetical
characters.
There are several difficulties with this approach. First, there is no
provision for actually reading the input; this has to be handled by
GetSpaces and GetWord. For example, if the end of
a line is reached and GetWord is called, then GetWord
should cause the next line of the user's input to be read. Also,
when GetSpaces is called after the last word of a line is reached,
it should return all the non-alphabetical characters up to the next word.
This could include all the spaces at the end of the line and all the
spaces at the beginning of the next line! A further problem with this
approach is with the output function WriteOut. If this function
merely used printf to print out the strings, then the entire
output would be on one line. If WriteOut printed out a carriage
return every time, then each run of spaces and each word would appear
on a line by itself. This is also undesirable.
Fortunately, now that we understand structures and pointers, we can
solve all of these problems using a technique called buffering.
An output buffer saves the strings to be printed out until there is
enough to fill one line of output. Then, all of the strings saved
so far are printed out as a single line with a carriage return.
An input buffer holds the current line of the user's input. When
all the characters in the input buffer has been scanned, then
additional input is read. To implement a buffer properly, a buffer
must be more than just a string. Consider the following structure:
typedef struct {
string line ;
int index ;
int length ;
} io_buffer ;
The variables input and output are of the type io_buffer.
For the input buffer, the field line will hold the current input line
from the user, the field index will indicate the next character to
be scanned, and the field length will contain the length of the
string in the line field. For the output buffer, the field
line will hold the string to be output so far, the field index
should store the number of characters in line so far, and the
field length determines the maximum number of characters allowed
in a single line. Note that in order to implement input and output
buffering correctly, the functions GetWord and GetSpaces
must be able to change the values of the fields. Hence, input
and output must be passed by reference.
Implementation Notes
Your program should adhere to the following guidelines.
- Your program should delete take two numbers from the user.
The first number is the number of words to be skipped (see Project 4
description). The second number is the maximum length of
an output line. Your program then takes the user's input line
by line until a line that begins with a period is reached. For
this program, you should use UNIX input/output redirection, so
you don't have to prompt the user for the input.
- Your main program should be very similar to the code given
above. You must implement the functions EndOfInput,
GetWord, GetSpaces, WriteOut and Flush.
- EndOfInput should return true if the end of the entire
input is reached, not just at the end of a line. You may need
to read another line of input to determine if there is more input.
- GetWord should return the next word in the input.
If the end of the current line has been reached, then the
next line should be read. The input buffer should be updated
accordingly.
- GetSpaces should return the next run of non-alphabetical
characters. This might include all the spaces at the end of
one line and all the spaces at the beginning of the next line.
If the end of the current line is reached, then the next line
should be read and the input buffer must be updated accordingly.
Lines that consist of all spaces must be handled carefully.
- WriteOut should save the given string in the output buffer.
If the output buffer is full or cannot hold the given string
without exceeding the maximum length, then the contents of the buffer
should be printed out first. Your function should return an
error if the length of the string exceeds the maximum length of
the output buffer.
- Flush simply empties the output buffer at the end to
print out the final line.
- You will surely need to implement other functions to support
these functions.
What to turn in:
Copy the file input5 from the directory ~chang/pub/cs201.
Run your program on this input file using UNIX input redirection:
% a.out < input5
To save your output, you can use UNIX output redirection:
% a.out < input5 > output5
When you are sure that your project works, you can turn in the output
and your program using the usual UNIX mail command:
% cat project5.c output5 | mail chang@gl.umbc.edu
Last Modified: June 10, 1994
Richard Chang, chang@gl.umbc.edu