2012-10-27 46 views
0

代码从C++引擎(3第三个)。 错误是:在Ubuntu Linux上使用g ++编译引擎示例代码时出错

* filterString.cpp:在函数 '诠释主()': filterString.cpp:32:68:错误:不能转换 '__gnu_cxx :: __ normal_iterator *,性病::矢量>>'到'std :: string * {aka std :: basic_string }'在初始化中

请帮我分析一下错误, 谢谢。

代码:

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

如果您正在从一本书或其他旧的(互联网时间)来源开始工作,您可能正在处理对事物如何运作的理解的变化,因为语言已经得到了更好的指定。设置一个'-std ='可以让你在编译器中使用一个更早的理解。 – dmckee

+0

对不起,我完全无法理解。尤其是这样的话:“设置-std =可能让你在编译器中使用更早的理解”。你能否从一点到另一点解释它!非常感谢! –

+0

G ++采用'std = C++ 98'或'std = C++ = 0x'形式的参数。选择正确的*可能会得到g ++来处理代码。 – dmckee

回答

0

这很有趣。迭代器的行为非常像指针,但不完全如此。特别是,你不能将一个迭代器转换为一个指针。

但是,您可以更改此代码以使用一个迭代器作为一种字符串*指针:

vector<string>::iterator max = max_element(text.begin(), text.end(), length_less); 

声明最大值是不是指向字符串的指针,而是一个迭代器串的矢量,这是max_element算法适用于字符串向量时返回的值。

你也可以使用指针,但这是一个坏习惯。只是用于测试的想法,您可以:

string *max = &*max_element(text.begin(), text.end(), length_less); 

的* max_element(...)返回字符串的引用返回的迭代器指向(就像废弃一个真正的指针)和&创建(字符串* )指向该字符串的指针。

这会引起麻烦,因为矢量的结构修改可能悄悄地使该指针无效。随后使用指针会将“随机”内存视为字符串对象。更糟糕的是,它可能在你的测试过程中起作用,并且在软件发货之前不会失败!

迭代器的体面实现应该检测失效并抛出异常。可预测的失败比随机崩溃更好。

+0

我会将其改写为“迭代器的体面实现应该在编译时检测到无效赋值并生成错误。”这就是gcc正在做的事情。 Visual C++正在生成类似的错误。 – user515430

+0

使用现代编译器可以写出“auto max = max_element(text.begin(),text.end(),length_less);”。 – user515430

+0

关于无效分配的编译时检测:我认为这并不可行。这需要编译器跟踪迭代器,而且这种语言并没有真正提供这一点。集合的结构修改没有问题,而以前使用的迭代器仍在范围内。这是该迭代器之后的使用,这是一个错误...然后只有当集合决定实际的特定修改应该使迭代器失效时。 –

1

在第32行,

std::max_element(text.begin(), text.end(), length_less); 

此函数返回的正向迭代解决该范围中的最大元件第一次出现的位置搜索而不是字符串。

你可以做的,而不是这一行什么:

string *max = max_element(text.begin(), text.end(), length_less); 

你必须要做到这一点,

//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); 
+0

我已经导入std命名空间。所以它也不起作用! –

+0

这不是关于std命名空间,它是从函数中得到的。你得到一个前向迭代器,你将它作为一个字符串来投射。 – rajat

+0

我明白了。非常感谢。向量 :: iterator max = max_element(text.begin(),text.end(),length_less); –

0

好吧,所以我就过了。这是我认为是使用lambdas和auto的更现代的解决方案。我把它留给其他人来决定是否更容易理解。

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