// Program slice.cpp CS 31 Extended Example shinnerl@ucla.edu // For a detailed description, see the accompanying specification. // Note: "word" means any contiguous sequence of nonspace characters. #include #include #include #include #include using std::string; using std::cout; using std::cin; using std::endl; using std::isspace; void showMenu(){ cout << "\n String Slicer Menu\n" << " ------------------\n" << " P PRINT the phrase to the screen \n" << " S SLICE one letter from each word \n" << " T TABULATE all slices in adjacent columns \n" << " Q QUIT the program" << endl; } void showPrompt(){ cout << "\nPSTQ> "; } unsigned skipSpace( const string& s, unsigned i, unsigned length ){ // Returns "length" when end of string is reached. // Else, returns index of next nonspace. while ( i < length && isspace( s[i] ) ) ++i; return i; } unsigned nextWord( const string& s, unsigned i ){ // Return the index of the first character of the next word. // Return index equal to s.size() if the end of s is reached. unsigned l = s.size(); while ( i < l && !isspace( s[i] ) ) // Skip remaining nonspace. ++i; i = skipSpace( s, i, l); // Skip remaining space. return i; } unsigned wordLength( const string& s, unsigned i ){ // Given a word starting at index i, // find the number of characters in the word. unsigned l = s.size(); assert (!isspace(s[i]) && i < l ); unsigned j = 0; while ( i < l && !isspace( s[i] ) ) { ++i; ++j; } return j; } void printSlice( const string& s, unsigned mwl ){ // mwl = maximum word length unsigned iSlice; do{ cout << "Which letter? Enter the slice index (1-" << mwl << "): "; cin >> iSlice; } while ( iSlice <= 0 || iSlice > mwl ); cout << "Requested slice: "; unsigned l = s.size(); unsigned i = skipSpace( s, 0, l); // Start at first nonspace. while ( i < l ){ // Invariant: i indexes the beginning of the next word. unsigned wl = wordLength(s, i); cout << s[ i+(iSlice-1)%wl ]; i = nextWord(s, i); } } unsigned maxWordLength( const string& s ){ // Find the length of the longest word in the string. unsigned l = s.size(), cwl = 0, // cwl == "current word length." i = 0, answer = 0; i = skipSpace( s, i, l ); while (i < l){ cwl = wordLength( s, i ); if ( cwl > answer ) answer = cwl; i = nextWord( s, i ); } return answer; } void printTable( const string& s, unsigned mwl ){ // Print the words of s in a rectangular table, // padding out words shorter than mwl==maxWordLength(s) // by periodic repetition to form a rectangle. unsigned i = 0, j; const char space = ' '; unsigned l = s.size(); i = skipSpace( s, i, l); // Go to start of the first word. while ( i < l){ unsigned cwl = wordLength( s, i ); // cwl == current word length unsigned i0 = i; while ( i < l && !isspace(s[i]) ){ // Print each word at least once, cout << space << s[i++]; // but watch out for the end of s! } j = i-i0; while ( j < mwl ){ // Repeat until the row is filled. cout << space << s[i0 + j++%cwl] ; } cout << endl; i = skipSpace( s, i, l); // Go to start of the next word. } } int main(){ string input; char selection; cout << "Enter a one-line phrase: " << endl; getline(cin, input); if (input.empty()) { cout << "Error: empty input phrase\n"; std::exit(-1); } unsigned mwl = maxWordLength( input ), iSlice=0; showMenu(); do{ showPrompt(); cin >> selection; switch (selection){ case 'P': case 'p': cout << input << endl; break; case 'S': case 's': printSlice(input, mwl); cout << endl; break; case 't': case 'T': printTable(input, mwl); break; case 'q': case 'Q': break; default: showMenu(); } } while ( selection != 'Q' && selection != 'q' ); return EXIT_SUCCESS; }