簡體   English   中英

如何在 C++ 中實現迭代器?

[英]How to implement the iterator in C++?

我在以下代碼上使用迭代器時遇到問題? 有誰知道如何修理它?

using StringVec = std::vector<std::string>;
using StringIntMap = std::unordered_map<std::string, int>;
  
StringIntMap makeWordCounts(const StringVec& words) {
   StringIntMap wordcount_map;
    
    std::vector<std::string>::const_iterator iter = words.begin();
    while(iter != words.end()) { //error message appears here
        if(wordcount_map.count(iter)) {
            wordcount_map[iter] = 1;
        }else{
            int value = wordcount_map.at(iter);
            wordcount_map[iter] = value+1;
        }
    }
  return wordcount_map;
}

錯誤消息:沒有可行的轉換來自

 'std::vector<std::string>::const_iterator' (aka '__wrap_iter<const
  std::__1::basic_string<char> *>') to 'const
  std::__1::unordered_map<std::__1::basic_string<char>, int,
  std::__1::hash<std::__1::basic_string<char> >,
  std::__1::equal_to<std::__1::basic_string<char> >,
  std::__1::allocator<std::__1::pair<const std::__1::basic_string<char>,
  int> > >::key_type' (aka 'const std::__1::basic_string<char>')
    if(wordcount_map.count(iter)) {

感謝您的幫助。

看看你調用的是什么函數:

 wordcount_map.count(iter) ^^^^^

現在,看一下參數的類型:

size_type count( const Key& key ) const;
                 ^^^^^^^^^^

請注意,該參數應該是地圖的鍵。 現在,看看你映射的鍵類型:

 using StringIntMap = std::unordered_map<std::string, int>; ^^^^^^^^^^^

它是一個字符串。 最后,看看你試圖傳遞給函數的參數的類型:

 std::vector<std::string>::const_iterator iter = words.begin(); ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

你能看出問題嗎? 您正在將迭代器傳遞給需要字符串的函數。 這是一種完全錯誤的對象類型,甚至不能轉換為預期的類型。 這就是您收到錯誤的原因:

錯誤消息:沒有從 [iterator] 到 [string] 的可行轉換


您還沒有描述您要做什么,但鑒於迭代器指向一個字符串,而您調用的函數需要一個字符串,我猜您想將迭代器指向的字符串傳遞給函數. 要訪問指向的字符串,您需要通過迭代器間接訪問。 這可以使用間接運算符來實現:

*iter

PS 如果進入循環,它將永遠不會結束(除非有東西被拋出或進程終止),因為iter永遠不會被修改,因此不會改變結束條件。

此外, else分支似乎總是拋出(這將結束循環)。

假設您想使用iter當前引用words向量的std::string元素作為wordcount_map索引/鍵,那么您只需要使用*運算符取消引用iter 此外,就目前而言,您的while循環不會對iter變量進行任何修改; 在循環結束時,您可能需要一個增量 ( ++ ) 運算符:

using StringVec = std::vector<std::string>;
using StringIntMap = std::unordered_map<std::string, int>;

StringIntMap makeWordCounts(const StringVec& words)
{
    StringIntMap wordcount_map;

    std::vector<std::string>::const_iterator iter = words.begin();
    while (iter != words.end()) {
        if (wordcount_map.count(*iter)) { // Use * to dereference iter
            wordcount_map[*iter] = 1;     // ... and here
        }
        else {
            int value = wordcount_map.at(*iter); // ...
            wordcount_map[*iter] = value + 1;    // ...
        }
        ++iter; // Increment the iterator to move on to the next vector element
    }
    return wordcount_map;
}

但是,與其在while循環中將++iter添加為單獨的行,不如使用for循環:

    for (std::vector<std::string>::const_iterator iter = words.begin(); iter != words.end(); ++iter) {
        //...

或者,更簡單的是,根本不使用顯式迭代器; 只需使用“基於范圍”的for循環:

    for (auto str : words) {
        if (wordcount_map.count(str)) {
            wordcount_map[str] = 1;
        }
        else {
            int value = wordcount_map.at(str);
            wordcount_map[str] = value + 1;
        }
    }

正如其他答案所解釋的那樣,您收到編譯器錯誤是因為您沒有取消引用迭代器來訪問它所引用的std::string

我只想補充一點,即使修復了該錯誤,您的代碼中仍然存在邏輯錯誤:

  • 您的循環根本不會增加迭代器,因此如果words向量不為空,它將無休止地運行。

  • 你的循環體是向后實現的。 std::unordered_map::count()返回與請求的鍵匹配的元素 if語句將數值 0 視為false ,將任何其他數值視為true 因此,如果count()返回> 0表示給定的鍵確實存在,則您正在使用值 1更新該元素,並刪除其先前的值。 如果count()返回0表示給定的鍵存在,則您正在使用相同的鍵調用std::unordered_map::at() ,該鍵失敗並拋出std::out_of_range異常。

更正后的版本如下所示:

using StringVec = std::vector<std::string>;
using StringIntMap = std::unordered_map<std::string, int>;
  
StringIntMap makeWordCounts(const StringVec& words) {
   StringIntMap wordcount_map;
    
    StringVec::const_iterator iter = words.begin();
    while (iter != words.end()) {
        if (wordcount_map.count(*iter)) {
            int value = wordcount_map.at(*iter);
            wordcount_map[*iter] = value + 1;
        }else{
            wordcount_map[*iter] = 1;
        }
        ++iter;
    }

    return wordcount_map;
}

然而,這段代碼不必要地復雜和低效。 它可以大大簡化為:

using StringVec = std::vector<std::string>;
using StringIntMap = std::unordered_map<std::string, int>;
  
StringIntMap makeWordCounts(const StringVec& words) {
    StringIntMap wordcount_map;
    
    for(const auto &word : words) {
        wordcount_map[word]++;
    }

    return wordcount_map;
}

基於范圍的for循環將為您處理迭代器。 並且std::unordered_map::operator[]返回對元素值的引用,如果請求的鍵尚不存在,則為您插入和初始化一個新元素。

錯誤不在你認為的那一行。 在后面和其余代碼的行中,您忘記取消對iter引用,並且在需要std::string地方傳遞了一個迭代器。 使固定:

    if(wordcount_map.count(*iter)) {
        wordcount_map[*iter] = 1;
    }else{
        int value = wordcount_map.at(*iter);
        wordcount_map[*iter] = value+1;
    }

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM