gpt4 book ai didi

c++ - Accelerated C++ exercise 8-5 解不清楚

转载 作者:塔克拉玛干 更新时间:2023-11-02 23:38:47 27 4
gpt4 key购买 nike

我一直在解决 Accelerated C++ 练习 8-5,我不想错过本书中的任何一个练习。

Accelerated C++练习8-5如下:

Reimplement the gen_sentence and xref functions from Chapter 7 to use output iterators rather than putting their entire output in one data structure. Test these new versions by writing programs that attach the output iterator directly to the standard output, and by storing the results in list <string> and map<string, vector<int> >, respectively.

为了理解这个问题的范围和本书这一部分的当前知识——这个练习是关于通用函数模板和迭代器在模板中的使用的章节的一部分。之前的练习是实现 <algorithm> 的简单版本库函数,例如 equal, find, copy, remove_copy_if

如果我没理解错,我需要修改xref函数所以它:

  • 使用输出迭代器
  • 将结果存储在 map<string, vector<int> >

我试图将 map 迭代器作为 back_inserter() 传递, .begin() , .end()到这个函数,但无法编译它。回答here解释原因。

第 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;
}

拆分实现:

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;
}

请帮助理解我错过了什么。

最佳答案

我在此处找到了有关该练习的更多详细信息: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 )

USAGE:

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 )

USAGE:

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

坦率地说,我不得不得出这个问题不恰当的结论,特别是在他们为 xref 指定新接口(interface)的地方:xref 应该产生 map 。但是,在这种情况下,使用输出迭代器意味着使用 std::inserter(map, map.end())。虽然您可以编写代码的编译版本,但这不会达到您的预期,因为 map::insert 将简单地忽略任何具有重复键的插入。

如果外部参照的目标只是将单词链接到它们第一次出现的行号,这仍然可以,但我有一种感觉,练习的作者只是错过了这个微妙的地方点:)

无论如何,这里是代码(请注意,我为 split 发明了一个愚蠢的实现,因为它既缺少又需要):

#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;
}

关于c++ - Accelerated C++ exercise 8-5 解不清楚,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8551922/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com