Accelerated C ++ exercise 8-5 solution is not clear

I am stuck in solving C ++ 8-5 Accelerated Exercises, and I don't want to miss one exercise in this book.

Accelerated Exercise 8-5 C ++ is as follows:

Repeat the gen_sentence and xref functions from chapter 7 to use output iterators instead of putting all their result in the same data composition. Check out these new versions by writing programs that attach the output of the iterator directly to standard output, and also save leads to list <string> and map<string, vector<int> > respectively.

To understand the scope of this question and current knowledge in this part of the book, this exercise is part of a chapter on common function templates and the use of an iterator in templates. The previous exercise was to implement simple versions of <algorithm> library functions such as equal, find, copy, remove_copy_if , etc.

If I understand correctly, I need to change the xref function so that it:

  • Use output iterator
  • Save results map<string, vector<int> >

I tried passing the map iterator as back_inserter() , .begin() , .end() this function, but I could not compile it. The answer here explains why.

xref, as in chapter 7:

 // find all the lines that refer to each word in the input map<string, vector<int> > xref(istream& in, vector<string> find_words(const string&) = split) { string line; int line_number = 0; map<string, vector<int> > ret; // read the next line while (getline(in, line)) { ++line_number; // break the input line into words vector<string> words = find_words(line); // remember that each word occurs on the current line for (vector<string>::const_iterator it = words.begin(); it != words.end(); ++it) ret[*it].push_back(line_number); } return ret; } 

Split implementation:

 vector<string> split(const string& s) { vector<string> ret; typedef string::size_type string_size; string_size i = 0; // invariant: we have processed characters `['original value of `i', `i)' while (i != s.size()) { // ignore leading blanks // invariant: characters in range `['original `i', current `i)' are all spaces while (i != s.size() && isspace(s[i])) ++i; // find end of next word string_size j = i; // invariant: none of the characters in range `['original `j', current `j)' is a space while (j != s.size() && !isspace(s[j])) ++j; // if we found some nonwhitespace characters if (i != j) { // copy from `s' starting at `i' and taking `j' `\-' `i' chars ret.push_back(s.substr(i, j - i)); i = j; } } return ret; } 

Please help me understand what I am missing.

+6
source share
1 answer

I found more information about the exercise, here: https://stackoverflow.com/questions/5608092/accelerated-c-exercise-8-5-wording-help :

 template <class Out> void gen_sentence( const Grammar& g, string s, Out& out ) 

APPLICATION:

 std::ostream_iterator<string> out_str (std::cout, " "); gen_sentence( g, "<sentence>", out_str ); 

 template <class Out, class In> void xref( In& in, Out& out, vector<string> find_words( const string& ) = split ) 

APPLICATION:

 std::ostream_iterator<string> out_str (std::cout, " "); xref( cin, out_str, find_url ) ; 

Frankly, I have to conclude that this question is incorrect, especially where they indicated a new interface for xref : xref should lead to a map. However, using output iterators implies using std::inserter(map, map.end()) in this case. Although you can write a compiling version of the code, this will not do what you expect, since map::insert will simply ignore any inserts with duplicate keys.

If the goal of xref is only to associate the words with the line number of their first appearance, it will still be okay, but I feel that the author of the exercise just skipped this thinner point :)

Here is the code anyway (note that I came up with a stupid implementation for split because it was missing and required):

 #include <map> #include <vector> #include <iostream> #include <sstream> #include <fstream> #include <algorithm> #include <iterator> std::vector<std::string> split(const std::string& str) { std::istringstream iss(str); std::vector<std::string> result; std::copy(std::istream_iterator<std::string>(iss), std::istream_iterator<std::string>(), std::back_inserter(result)); return result; } // find all the lines that refer to each word in the input template <typename OutIt> OutIt xref(std::istream& in, OutIt out, std::vector<std::string> find_words(const std::string&) = split) { std::string line; int line_number = 0; // read the next line while (getline(in, line)) { ++line_number; // break the input line into words std::vector<std::string> words = find_words(line); // remember that each word occurs on the current line for (std::vector<std::string>::const_iterator it = words.begin(); it != words.end(); ++it) *out++ = std::make_pair(*it, line_number); } return out; } int main(int argc, const char *argv[]) { std::map<std::string, int> index; std::ifstream file("/tmp/test.cpp"); xref(file, std::inserter(index, index.end())); #if __GXX_EXPERIMENTAL_CXX0X__ for(auto& entry: index) std::cout << entry.first << " first found on line " << entry.second << std::endl; #else for(std::map<std::string, int>::const_iterator it = index.begin(); it != index.end(); ++it) { std::cout << it->first << " first found on line " << it->second << std::endl; } #endif return 0; } 
+4
source

Source: https://habr.com/ru/post/904024/


All Articles