COMP 142: Project 3 --- Mesostics
A mesostic is a poem arranged in such a way that a word appears vertically consisting
of single letters from the horizontal lines of the poem.
Here's an example, albeit with a misspelling.
For this project, you will create a program that arranges the words of a poem into a mesostic by adjusting the spacing of the lines of the poem.
Your program will work by opening and reading the lines of a text file.
The first line
of the file will contain a single word without spaces. The subsequent lines will contain the lines of a poem; these
lines may include spaces. Your program will print out the lines of the poem spaced so that the single word from the beginning
of the file can be read vertically in the output.
It is guaranteed that all the files I use to test your program will consist of poems for
which mesostics can be found. You should also note that this concept only works in computational form
because typical computer programs produce their output in a monospace (a font where each letter, number, or punctuation symbol takes
up the same amount of horizontal space), as opposed to a proportional font (a font where the amount of horizontal
space used for a character is proportional to the normal amount of horizonal space the character actually would take up).
Examples: This is a monospace font. This is a proportional font.
Program details and algorithms
You should use a struct in your program to hold the mesostic. The declaration of the struct should be the following:
struct mesostic
{
string vert_word;
vector<string> poem_lines;
vector<int> match_positions;
};
The struct contains the following information about a mesostic:
- vert_word: a string containing the vertical word that will be found in the poem.
- poem_lines: a vector of strings; each string is a lines of the poem.
- match_positions: a vector of integers; each integer specifies where each letter in the vertical word
can be found in the appropriate line of the poem. Note that the size of the match_positions and
and poem_lines vectors will always be identical.
Let us illustrate these pieces with a short example. Say your input file contains the four lines:
cat
this cuddly
animal
bites me
When your program reads this file, it would create a mesostic struct with vert_word as "cat" and
poem_lines consisting of the strings "this cuddly", "animal", and "bites me" in a vector.
match_positions would contain a vector of 5, 0, and 2, because the 5th position (counting from zero)
in the string "this cuddly" is 'c', the 0th position in "animal" is 'a', and the 2nd position in
"bites me" is 't'.
Naturally, you will need to write code to calculate the integer values in the match_positions vector.
It is also worth pointing out that poem_lines contains three strings and match_positions contains
three integers.
After your program calculates this information, it should be able to print the poem (using cout and some blank spaces) as:
this cuddly
animal
bites me
Notice how the word "cat" is found vertically in the output.
How the program should work
The user should be asked to type in the name of a text file that contains a mesostic. The user will not
type in the vertical word and the lines of the poem manually; that information will be read from the text file.
Your program should then (1) create a struct to hold the mesostic, (2) read in the lines of the text file
into the vert_word and poem_lines vector, (3) calculate and set the appropriate values of the
match_lines vector, and (4) display the mesostic arranged
so the vertical word can be seen in the lines of the poem. Obviously, some of the lines of the poem will need to
be moved to the right on the screen; this can be done by printing a specific number of blank spaces before each line of the poem.
The mesostic
should always be left-justified; that is, there should be at least one line of the poem that is printed without
any leading spaces. This line is not necessarily the first line of the poem.
Parts of the program
You should use functions to break up parts of your program. At a minimum, you should have
a function that reads in the file, a function that calculates the match_positions vector, and
a function that prints the mesostic. You may use other functions as you see fit.
Here are some suggested prototypes:
mesostic read_file(string filename)
--- This function will read the file specified by the filename, read the vertical word,
the lines of the poem, calculate the match positions, and return the mesostic struct.
void find_match_positions(mesostic & m)
--- This function handles calculating the match positions and updates the mesostic struct; I called this from read_file.
void print_mesostic(const mesostic & m)
--- This function prints the mesostic with spaces in the right places on each line to make the vertical word appear.
Reading the file
Reading the file is a bit tricky because we need to use getline (because each line of the poem may
have spaces). What I suggest doing is using one initial call to getline to read in the vertical word
of the mesostic (save this into vert_word), and then use a loop to read in the lines of the poem. Using a loop
with getline is a little different than what we're used to; we don't use the eof() function. Instead, use this idea:
mesostic meso;
string s;
getline(infile, meso.vert_word); // read the vertical word directly
while (getline(infile, s))
{
meso.poem_lines.push_back(s);
}
Things will get wonky if you try to use while (!infile.eof()) here.
Calculating match_positions
You must devise an algorithm for this. Use the example above to figure out how
the algorithm should work and what numbers should go into the match_positions vector.
You will need a loop. You can loop over either the letters (chars)
of the vertical word, or the entire lines (strings) of the poem.
It doesn't matter either way, since it's guaranteed there are the
same number of chars in the vertical word as there are lines in the
poem.
Printing the mesostic with the correct spacing
Again, you will need to devise an algorithm for this, and this one will take a
little bit of thought. Here's a hint:
the number of spaces to add to each line of the poem is dependent upon
more than just that individual line --- the number depends on a factor
that can only be deduced by examining the entire poem.
Work out some examples (e.g., from the text files) on graph paper
to figure out this algorithm. The graph paper is useful because you can put
one character in each square on the paper and easily see how things are supposed to
line up. See if you can figure out what the
connection is between match_positions and how many leading spaces
are added to each line of the poem.
Coding style
All the normal guidelines for coding from previous projects apply.
Do not use any global variables.
Testing your program
You should test your program thoroughly to make sure it works correctly. Here are some sample mesostic files to try:
meso0.txt
meso1.txt
meso2.txt
meso3.txt
meso4.txt
Sample input and output
The program's output is in normal text; what the user types is in bold. Each test
of the program is shown separately; the SAMPLE RUN parts are not part of the output.
-----------------------------------------------------
SAMPLE RUN 1
-----------------------------------------------------
Mesostic input file: meso0.txt
this cuddly
animal
bites me
-----------------------------------------------------
SAMPLE RUN 2
-----------------------------------------------------
Mesostic input file: meso1.txt
let us make
of this
modest
place
a room holding
tons of love
(&, naturally, much good food, too)
-----------------------------------------------------
SAMPLE RUN 3
-----------------------------------------------------
Mesostic input file: meso2.txt
life is a
companion
treat it with
generosity
sincerity
patience and
love
-----------------------------------------------------
SAMPLE RUN 4
-----------------------------------------------------
Mesostic input file: meso3.txt
music
indeterminacy
words
collaboration
speech
invention
silence
cage
-----------------------------------------------------
SAMPLE RUN 5
-----------------------------------------------------
Mesostic input file: meso4.txt
it's just
great theater. there's
an ordinary guy, balding,
unknown,
leaves sunny stratford
penniless, a few plays
and poems in a bag, ends up on
the globe stage a master,
unrivalled
bard, 100%
literary genius.
Hints
- Even though the first line of the file is a single word, just use getline for reading in every line of the file.
It will be easier than using "infile >>" for the first line
and getline for the next lines.
- Make sure each step of your program works before moving on to the next step. For instance, before you even worry
about putting the words into a struct, make
sure you are opening the file and reading each line correctly. I recommend adding lots of cout statements
throughout your code to print out diagnostic messages (e.g., the lines
of the file as you read them). Such messages can then be removed or commented out before you turn in your program.
- If you use the string function find, note that it returns a size_t type, which is really just an unsigned int in
disguise. You can cast this to an int.
What to turn in
Through Moodle, turn in your code as a file called main.cpp or mesostic.cpp
.
Please do not upload anything other than the .cpp file.
Challenge Problem
Print the mesostic using uppercase letters for the vertical word to make it easier
to find quickly. For example, the output
for meso4.txt would change to
it'S just
great tHeater. there's
An ordinary guy, balding,
unKnown,
lEaves sunny stratford
pennileSs, a few plays
and Poems in a bag, ends up on
thE globe stage a master,
unrivAlled
baRd, 100%
litErary genius.
For historical reasons, the toupper function returns an int, not a char. If you use
toupper to convert from lowercase to uppercase, you will need to cast the return
value of toupper to a char to get it to print correctly.