输出所有给定单词所在的行号和该行的内容。
用一个类来完成此功能TextQuery
#ifndef TEXTQUERY_H
#define TEXTQUERY_H
#include < iostream >
#include < fstream >
#include < sstream >
#include < string >
#include < vector >
#include < map >
#include < set >
using namespace std;
class TextQuery{
public :
// typedef to make declarations easier
typedef std::vector < std:: string > ::size_type line_no;
/* interface:
*read_file builds internal data structures for the given file
*run_query finds the given word and returns set of ines on which it appears
*test_line returns a requested line from the input file
*/
void read_file(std::ifstream & is )
{
store_file( is );
build_map();
}
std:: set < line_no > run_query( const std:: string & ) const ;
std:: string text_line(line_no) const ;
private :
// utility functions used by read_file
void store_file(std::ifstream & ); // store input file
void build_map(); // associated each word with a set of line numbers
// remember the whole input file
std::vector < std:: string > lines_of_text;
// map word to set of the lines on which it occurs
std::map < std:: string ,std:: set < line_no > > word_map;
};
// read input file:store each line as element in lines_of_text
void TextQuery::store_file(std::ifstream & is )
{
string textline;
while (getline( is ,textline))
lines_of_text.push_back(textline);
}
// finds whitespace-seperated words in the input vector
// and puts the word in word_map along with the line number
void TextQuery::build_map()
{
// process each line from the input vector
for (line_no line_num = 0 ;line_num != lines_of_text.size(); ++ line_num)
{
// we'll use line to read the text a word at a time
istringstream line(lines_of_text[line_num]);
std:: string word;
while (line >> word)
// add this line number to the set
// subscript will add to to map if it's not already there
word_map[word].insert(line_num);
}
}
set < TextQuery::line_no > TextQuery::run_query( const string & query_word) const
{
// Note:must use find and not subscript the map directly
// to avoid adding words to word_map!
map < string , set < line_no > > ::const_iterator loc = word_map.find(query_word);
if (loc == word_map.end())
return set < line_no > (); // not found,return empty set
else
// fetch and return set of line numbers for this word
return loc -> second;
}
string TextQuery::text_line(line_no line) const
{
if (line < lines_of_text.size())
return lines_of_text[line];
throw ;
}
#endif
#define TEXTQUERY_H
#include < iostream >
#include < fstream >
#include < sstream >
#include < string >
#include < vector >
#include < map >
#include < set >
using namespace std;
class TextQuery{
public :
// typedef to make declarations easier
typedef std::vector < std:: string > ::size_type line_no;
/* interface:
*read_file builds internal data structures for the given file
*run_query finds the given word and returns set of ines on which it appears
*test_line returns a requested line from the input file
*/
void read_file(std::ifstream & is )
{
store_file( is );
build_map();
}
std:: set < line_no > run_query( const std:: string & ) const ;
std:: string text_line(line_no) const ;
private :
// utility functions used by read_file
void store_file(std::ifstream & ); // store input file
void build_map(); // associated each word with a set of line numbers
// remember the whole input file
std::vector < std:: string > lines_of_text;
// map word to set of the lines on which it occurs
std::map < std:: string ,std:: set < line_no > > word_map;
};
// read input file:store each line as element in lines_of_text
void TextQuery::store_file(std::ifstream & is )
{
string textline;
while (getline( is ,textline))
lines_of_text.push_back(textline);
}
// finds whitespace-seperated words in the input vector
// and puts the word in word_map along with the line number
void TextQuery::build_map()
{
// process each line from the input vector
for (line_no line_num = 0 ;line_num != lines_of_text.size(); ++ line_num)
{
// we'll use line to read the text a word at a time
istringstream line(lines_of_text[line_num]);
std:: string word;
while (line >> word)
// add this line number to the set
// subscript will add to to map if it's not already there
word_map[word].insert(line_num);
}
}
set < TextQuery::line_no > TextQuery::run_query( const string & query_word) const
{
// Note:must use find and not subscript the map directly
// to avoid adding words to word_map!
map < string , set < line_no > > ::const_iterator loc = word_map.find(query_word);
if (loc == word_map.end())
return set < line_no > (); // not found,return empty set
else
// fetch and return set of line numbers for this word
return loc -> second;
}
string TextQuery::text_line(line_no line) const
{
if (line < lines_of_text.size())
return lines_of_text[line];
throw ;
}
#endif
#include
"
TextQuery.h
"
void print_results( const set < TextQuery::line_no >& , const string & , const TextQuery & );
ifstream & open_file(ifstream & in , const string & file);
// program takes single argument spesifying the file to query
int main( int argc, char ** argv)
{
// open the file from which user will query words
ifstream infile;
if (argc < 2 ||! open_file(infile,argv[ 1 ]))
{
cerr << " No input file! " << endl;
return - 1 ;
}
TextQuery tq;
tq.read_file(infile); // builds query map;
// iterate with the user:prompt for a word to find and print result
// loop indefinitely;the loop exits is inside the while
while ( true )
{
cout << " enter word to look for,or q to quit: " ;
string s;
cin >> s;
// stop if hit eof on input or a 'q' is enterd
if ( ! cin || s == " q " )
break ;
// get the set of line numbers on which this word appears
set < TextQuery::line_no > loc = tq.run_query(s);
// print count and all occurrences,if any
print_results(loc,s,tq);
}
return 0 ;
}
// return plural version of word if ctr isn't 1
string make_plural(size_t ctr, const string & word, const string & ending)
{
return (ctr == 1 ) ? word:word + ending;
}
ifstream & open_file(ifstream & in , const string & file)
{
in .close(); // close in case it was already open
in .clear(); // clear any existing errors
// if the open fails,the stream will be in an invalid state
in .open(file.c_str()); // open the file we were given
return in ;
}
void print_results( const set < TextQuery::line_no >& loc, const string & sought, const TextQuery & file)
{
// if the word was found,then print count and all occurrences
typedef set < TextQuery::line_no > line_nums;
line_nums::size_type size = loc.size();
cout << " \n " << sought << " occurs " << size << " " << make_plural(size, " time " , " s " ) << endl; // if size=1 then print "time",or not print "times"
// print each line in which the word appeard
line_nums::const_iterator it = loc.begin();
for (;it != loc.end(); ++ it)
{
cout << " \t(line "
// don't confound user with text lines starting at 0
<< ( * it) + 1 << " ) " << file.text_line( * it) << endl;
}
}
void print_results( const set < TextQuery::line_no >& , const string & , const TextQuery & );
ifstream & open_file(ifstream & in , const string & file);
// program takes single argument spesifying the file to query
int main( int argc, char ** argv)
{
// open the file from which user will query words
ifstream infile;
if (argc < 2 ||! open_file(infile,argv[ 1 ]))
{
cerr << " No input file! " << endl;
return - 1 ;
}
TextQuery tq;
tq.read_file(infile); // builds query map;
// iterate with the user:prompt for a word to find and print result
// loop indefinitely;the loop exits is inside the while
while ( true )
{
cout << " enter word to look for,or q to quit: " ;
string s;
cin >> s;
// stop if hit eof on input or a 'q' is enterd
if ( ! cin || s == " q " )
break ;
// get the set of line numbers on which this word appears
set < TextQuery::line_no > loc = tq.run_query(s);
// print count and all occurrences,if any
print_results(loc,s,tq);
}
return 0 ;
}
// return plural version of word if ctr isn't 1
string make_plural(size_t ctr, const string & word, const string & ending)
{
return (ctr == 1 ) ? word:word + ending;
}
ifstream & open_file(ifstream & in , const string & file)
{
in .close(); // close in case it was already open
in .clear(); // clear any existing errors
// if the open fails,the stream will be in an invalid state
in .open(file.c_str()); // open the file we were given
return in ;
}
void print_results( const set < TextQuery::line_no >& loc, const string & sought, const TextQuery & file)
{
// if the word was found,then print count and all occurrences
typedef set < TextQuery::line_no > line_nums;
line_nums::size_type size = loc.size();
cout << " \n " << sought << " occurs " << size << " " << make_plural(size, " time " , " s " ) << endl; // if size=1 then print "time",or not print "times"
// print each line in which the word appeard
line_nums::const_iterator it = loc.begin();
for (;it != loc.end(); ++ it)
{
cout << " \t(line "
// don't confound user with text lines starting at 0
<< ( * it) + 1 << " ) " << file.text_line( * it) << endl;
}
}