2012-10-27 48 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; 
}