Winter 2004 UCLA CS 31 Section 1 (Shinnerl)

Extended Practice Problem: String Slicer

I. Overview

Implement a C++ program to assist users in the creation of good passwords. When invoked, the program prompts the user to enter a data phrase on one line of input. The phrase may include any printable ASCII characters, including spaces and tabs, but excluding the newline character, '\n', which is used to delimit the end of the phrase. After reading the phrase and checking that it is nonempty, the program displays the following menu.

 String Slicer Menu
 ------------------
 P    PRINT    the phrase to the screen
 S    SLICE    one letter from each word
 T    TABULATE all slices in adjacent columns
 Q    QUIT     the program
Next, and, after every successful completion of a user request, the program displays the following short prompt:
PSTQ>
The sequence of prompts and responses for each of the above options is listed in detail below.

  1. P or p -- Simply echo the user's original input to the screen without changing a single character.

  2. S or s -- Request and read in one positive integer from the user, say k, called the slice index. The value of the slice index must be no more than the length of the longest word in the user's phrase; repeat its input process until the user supplies a legal value. Traverse the phrase, printing the kth character in each word. Do not exclude any printable nonspace characters; punctuation, digits, etc. are all fine. If k is greater than the length of any word, use wrap-around to select an alternate character from that same word. See the sample transcript for an example.

  3. T or t -- Display the words in the string in order vertically, each word on its own horizontal line of the screen output, with one extra space inserted between each pair of nonspace characters. For every word whose length is less than the maximum word length in the given string, repeat printing of the word's characters until that maximum word length is reached. In this way, a rectangular table of characters is displayed, with the columns of the table being all the string slices that can be constructed by the program for the given input phrase.

  4. Q or q -- Terminate execution.

  5. Anything else -- Display the string slicer menu as above, followed by the usual short prompt.

II. Advice

Whitespace refers to any sequence of any of the following characters: ' ' '\t' '\n' '\r' '\f' . To test whether a character is whitespace, you may compare to the above charaters directly, or you may use the bool std::isspace(char) function from the cctype library.

In text processing, a word is any contiguous sequence of nonwhitespace characters. Hence, words in a string are separated from each other by whitespace. But the last word in a string might not have whitespace after it.

The driver (main() function) should be kept short. Menu options S and T should each be handled by at least one separate function. To support these functions, you will find it useful to implement additional functions for performing the following tasks, among others.

  1. Given an initial position somewhere in the string, find the unsigned integer index of the beginning of the next word in the string.
  2. Given the index of the first character in any word in the string, find the length of the word.
  3. Find the maximum length of any word in the string.

Recall that the stream extraction operator >> leaves any '\n' character trailing its input in the input stream for the next input operation to handle. Hence, the following code fragment will fail to correctly input a line of text into the string s:

   string s;
   int i;
   cout << "Enter an integer, then enter a string: "
   cin >> i;           // This operation leaves the '\n' behind!
   getline(cin, s);    // Error: s does not receive any data!
To remove a known and unwanted newline character left behind by the >> operator, use the istream::ignore(int, char) function:
   cin >> i;                // This operation leaves the '\n' behind!
   cin.ignore(1000, '\n');  // Discards the unwanted '\n'
   getline(cin, s);         // Works as intended.
The number 1000 preceding the '\n' specifies an upper limit on how many characters preceding the '\n' to ignore.

Remember to ensure that, whenever you traverse any part of a string, you never attempt to access memory past the last stored character or before the first stored character in the string. Use the string::length() or string::size() function to prevent this very common error.

III. Sample Trace

$ slice
 Enter a one-line phrase:
 individuals in a hierarchy rise to their levels of incompetence

 String Slicer Menu
 ------------------
 P    PRINT    the phrase to the screen
 S    SLICE    one letter from each word
 T    TABULATE all slices in adjacent columns
 Q    QUIT     the program

 PSTQ> p
 individuals in a hierarchy rise to their levels of incompetence

 PSTQ> s
 Which letter?  Enter the slice index (1-12): 1
 Requested slice: iiahrttloi

 PSTQ> s
 Which letter?  Enter the slice index (1-12): 2
 Requested slice: nnaiiohefn

 PSTQ> s
 Which letter?  Enter the slice index (1-12): 0
 Which letter?  Enter the slice index (1-12): 14
 Which letter?  Enter the slice index (1-12): -54
 Which letter?  Enter the slice index (1-12): 7
 Requested slice: diacsthloe

 PSTQ> p
 individuals in a hierarchy rise to their levels of incompetence

 PSTQ> t
  i n d i v i d u a l s i
  i n i n i n i n i n i n
  a a a a a a a a a a a a
  h i e r a r c h y h i e
  r i s e r i s e r i s e
  t o t o t o t o t o t o
  t h e i r t h e i r t h
  l e v e l s l e v e l s
  o f o f o f o f o f o f
  i n c o m p e t e n c e

 PSTQ> ?

 String Slicer Menu
 ------------------
 P    PRINT    the phrase to the screen
 S    SLICE    one letter from each word
 T    TABULATE all slices in adjacent columns
 Q    QUIT     the program

 PSTQ> q

$