[英]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.