[英]Error when compile the primer example code using g++ on Ubuntu Linux
The code is from C++ primer(3 third) . 代码来自C ++入门(第3部分) 。 The error is :
错误是:
*filterString.cpp: In function 'int main()': filterString.cpp:32:68: error: cannot convert '__gnu_cxx::__normal_iterator*, std::vector > >' to 'std::string* {aka std::basic_string }' in initialization * filterString.cpp:在函数'int main()'中:filterString.cpp:32:68:错误:无法将'__gnu_cxx :: __ normal_iterator *,std :: vector>>'转换为'std :: string * {aka std :: basic_string }'初始化中
pls help me analyse the error, thanks. 请帮助我分析错误,谢谢。
code: 码:
#include <string>
#include <algorithm>
#include <iterator>
#include <vector>
#include <iostream>
using namespace std;
template <class InputIterator>
void filter_string(InputIterator first, InputIterator last, string filt_elems = string("\",?.")) {
for (; first != last; first++){
string:: size_type pos = 0;
while ((pos = (*first).find_first_of(filt_elems, pos)) != string::npos)
(*first).erase(pos, 1);
}
}
bool length_less (string s1, string s2) {
return s1.size() < s2.size();
}
int main() {
istream_iterator<string> input(cin), eos;
vector<string> text;
copy(input, eos, back_inserter(text));
string filt_elems("\",.?;:");
filter_string(text.begin(), text.end(), filt_elems);
int cnt = text.size();
string *max = max_element(text.begin(), text.end(), length_less);
int len = max->size();
cout << "The number of words read is " << cnt << endl;
cout << "The longest word has a length of " << len << endl;
cout << "The longest word is " << *max << endl;
return 0;
}
In line 32 , 在第32行,
std::max_element(text.begin(), text.end(), length_less);
this function returns a forward iterator addressing the position of the first occurrence of the largest element in the range searched and not a string . 此函数返回一个正向迭代器,寻址所搜索范围而不是字符串中最大元素的首次出现的位置。
What you can do instead of this line: 您可以代替此行做什么:
string *max = max_element(text.begin(), text.end(), length_less);
you have to do this , 你必须这样做
//First find the index of the max_element , by subtracting the forward iterator you get from calling max_element from the iterator for first element .
int index=max_element(text.begin(), text.end(), length_less) - text.begin();
//And then find string stored on that index.
string *max = text.at(index);
This is interesting. 这是有趣的。 Iterators behave much like pointers, but not exactly.
迭代器的行为很像指针,但不完全相同。 In particular, you can't convert an iterator to a pointer.
特别是,您不能将迭代器转换为指针。
However, you can change this code to use an iterator as a sort of string* pointer: 但是,您可以更改此代码以将迭代器用作某种字符串*指针:
vector<string>::iterator max = max_element(text.begin(), text.end(), length_less);
That declares max to be not a pointer to a string, but an iterator into a vector of strings, which is what the max_element algorithm returns when applies to a vector of strings. 这声明max不是指向字符串的指针,而是指向字符串向量的迭代器,这是将max_element算法应用于字符串向量时返回的内容。
You can also use a pointer, but it's a bad habit. 您也可以使用指针,但这是一个坏习惯。 Just for testing the idea, you can:
只是为了测试这个想法,您可以:
string *max = &*max_element(text.begin(), text.end(), length_less);
The *max_element(...) returns a reference to the string the returned iterator points to (just like dereferencing a real pointer) and & creates a (string*) pointer to that string. * max_element(...)返回对返回的迭代器指向的字符串的引用(就像取消引用真实指针一样),并创建指向该字符串的(字符串*)指针。
This invites trouble, since a structural modification of the vector could quietly invalidate that pointer. 这会带来麻烦,因为向量的结构修改可能会静默使该指针无效。 Subsequent use of the pointer would be treating "random" memory as a string object.
指针的后续使用将把“随机”内存视为字符串对象。 Even worse, it might work during your testing and not fail until the software was shipped!
更糟糕的是,它可能会在您的测试过程中起作用,并且在软件出厂之前不会失败!
A decent implementation of iterators should detect the invalidation and throw an exception. 良好的迭代器实现应检测到无效并引发异常。 A predictable fail is better than a random meltdown.
可预见的失败比随机崩溃要好。
OK, so I went overboard. 好的,所以我太过分了。 Here is what I think is a more modern solution using lambdas and auto.
我认为这是使用lambda和auto的更现代的解决方案。 I leave it to others to decide if it is easier to understand.
我将它留给其他人来决定是否更容易理解。
#include <algorithm>
#include <iostream>
#include <iterator>
#include <ostream>
#include <string>
#include <vector>
using namespace std;
template <class InputIterator>
void filter_string(InputIterator first, InputIterator last,
const string filt_elems = const string("\",?."))
{
for_each(first, last,
[filt_elems](string& s)
{
s.erase(
// Shift valid characters up before erasing the undesirable
remove_if(s.begin(), s.end(),
[filt_elems](string::value_type c)
{ return filt_elems.find_first_of(c) != string::npos; }),
s.end());
});
}
int main()
{
istream_iterator<string> input(cin);
istream_iterator<string> eos;
vector<const string> words;
copy(input, eos, back_inserter(words));
const string filt_elems("\",.?;:");
filter_string(words.begin(), words.end(), filt_elems);
const int count = words.size();
// Get a reference to the longest word
const auto& max_word = *max_element(words.cbegin(), words.cend(),
[](const string& lhs, const string& rhs)
{ return lhs.size() < rhs.size(); });
const int length = max_word.size();
cout << "The number of words read is " << count << endl;
cout << "The longest word has a length of " << length << endl;
cout << "The longest word is " << max_word << endl;
return 0;
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.