// Problem: words_to_line // Author: Chuck Stweart // Purpose: Given a text file, give an alphabetical listing of the // words in the file and the file line numbers on which each word // appears. If a word appears on a line more than once, the line // numbers are not repeated. A map of strings and vectors is used // to store the information. #include #include #include #include #include #include #include // Forward reference to a function that will be discussed in Lecture 13. std::vector breakup_v2( const std::string& line ); int main( int argc, char* argv[] ) { if ( argc != 2 ) { std::cerr << "Usage: " << argv[1] << " text-file\n"; return 0; } std::ifstream in_str( argv[1] ); if ( !in_str ) { std::cerr << "Failed to open " << argv[1] << '\n'; return 0; } std::map< std::string, std::vector > words_to_lines; std::string line; int line_number = 0; while ( std::getline( in_str, line ) ) { ++ line_number; // Break the string up into words std::vector words = breakup_v2( line ); // Enter each word in the map for ( std::vector::iterator p = words.begin(); p!= words.end(); ++p ) { // Find if the word is already in the map. If it is not, // create a new entry with an empty std::vector (by // default) and add to the end of the std::vector std::map< std::string, std::vector >::iterator map_itr = words_to_lines.find( *p ); if ( map_itr == words_to_lines.end() ) { words_to_lines[ *p ].push_back( line_number ); // could use insert here } // If the word is in map, check the last entry to see if // the line number is already there. If it isn't, add it // to the back of the std::vector. else if ( map_itr -> second . back() != line_number ) { map_itr -> second . push_back( line_number ); } } } // Output each word on a single line, followed by the line numbers. for ( std::map< std::string, std::vector >::iterator map_itr = words_to_lines.begin(); map_itr != words_to_lines.end(); ++ map_itr ) { std::cout << map_itr -> first << ":\t"; for ( unsigned int i = 0; i < map_itr -> second . size(); ++i ) std::cout << ( map_itr -> second )[ i ] << " "; std::cout << "\n"; } return 0; } std::vector breakup_v2( const std::string& line ) { std::vector strings; std::string::const_iterator p = line.begin(); std::string one_word; while ( p != line.end() ) { // Find the beginning of the next alphabetic string while ( p != line.end() && !isalpha( *p ) ) p ++; // If haven't reached the end of the line if ( p != line.end() ) { // Restart the word with *p one_word.clear(); one_word += tolower(*p); // Add remaining letters for ( ++p; p != line.end() && isalpha(*p); ++p ) one_word += tolower(*p); // Add word to the vector of strings strings.push_back( one_word ); } } return strings; }