[英]vector find is returning the wrong value
该程序的目的是从 .txt 文件中读取字符串,并将所有不重复的单词放入一个集合中。 我通过将所有单词放入一个向量中来做到这一点,然后尝试通过它 go 并仅将唯一单词添加到集合中并从向量中删除重复单词。 这是我在底部遇到问题的部分的完整代码。
#include <iostream>
#include <fstream>
#include <set>
#include <vector>
#include <iterator>
#include <algorithm>
using namespace std;
int main ()
{
//create data types
set<string> non_duplicate;
vector<string> vectorstring;
vector<string>::iterator it;
ifstream file;
//open file return 1 if can't be opened
file.open ("txt.txt");
if (!file.is_open()) return 1;
//make variable for word
string word;
//take words one at a time from file and add to vector/
while (file >> word)
{
vectorstring.push_back(word);
}
//check vector from repeats and add to set if not
do
{
string temp = vectorstring[0];
vectorstring.erase(vectorstring.begin());
bool duplicate = 0;
check:
if (vectorstring.size() == 0)
{
non_duplicate.insert (temp);
break;
}
it = find(vectorstring.begin(), vectorstring.end(), temp);
if (*it != temp && duplicate != 1)
{
non_duplicate.insert (temp);
}
else if (*it == temp)
{
vectorstring.erase(it);
duplicate = 1;
goto check;
}
} while (!vectorstring.empty());
//output results
cout << "List of non-repeating words: ";
for (auto x = non_duplicate.begin(); x !=non_duplicate.end(); x++)
{
cout << *x << " ";
}
cout << endl;
这是导致我出现问题的代码位。 每次我接近向量中的最后 3 个元素时,找到 function 和“它”都没有给我正确的 output。 例如,如果正在搜索的临时值是“ben”并且这些单词中的最后一个已被删除,则它的值不会重置并在通过 find 后保持“ben”,看起来好像还有一个值“本”当没有的时候。 我不确定为什么会发生这种情况,因为它适用于除了接近结尾的值之外的每个值?
do
{
string temp = vectorstring[0];
vectorstring.erase(vectorstring.begin());
bool duplicate = 0;
if (vectorstring.size() == 0)
{
non_duplicate.insert (temp);
break;
}
check:
it = find(vectorstring.begin(), vectorstring.end(), temp);
if (*it != temp && duplicate != 1)
{
non_duplicate.insert (temp);
}
else if (*it == temp)
{
vectorstring.erase(it);
duplicate = 1;
goto check;
}
} while (!vectorstring.empty());
要从std::vector
中获取具有唯一条目的std::set
,您只需构造该集合。 根据定义,集合仅包含唯一条目:
#include <set>
#include <vector>
#include <iostream>
int main() {
std::vector<int> x{1,1,2,2,3,3};
std::set<int> non_duplicate{x.begin(),x.end()};
for (const auto n : non_duplicate) std::cout << n << " ";
}
Output:
1 2 3
你的代码太复杂了。 我发现了至少一个主要问题:
string temp = vectorstring[0];
vectorstring.erase(vectorstring.begin());
//....
it = find(vectorstring.begin(), vectorstring.end(), temp);
if (*it != temp && duplicate != 1)
当第一个元素vectorstring[0]
在向量中只出现一次时, find
将返回vectorstring.end()
(因为你删除了一个外观)。 在*it != temp
中取消引用结束迭代器会调用未定义的行为。
std::set
将只存储一次元素。 您可以简单地将所有内容直接存储在集合中,而无需涉及向量。
std::string word;
while (file >> word)
{
non_duplicate.insert(word);
}
此外,取消引用结束迭代器是未定义的行为。 如果未找到匹配项, std::find
返回第二个迭代器,您将在 if 条件中取消引用向量的结束迭代器。
此外,应该避免使用goto
,因为它很容易导致代码难以维护。 在您的情况下,改写代码以使用第二个嵌套循环并不难。
此外,循环确实假设向量最初不是空的。
这是你的循环的重写,虽然这会起作用:
while(!vectorstring.empty())
{
std::string temp = std::move(vectorstring[0]); // don't make a copy; we'll erase the object anyways
vectorstring.erase(vectorstring.begin());
// clear the duplicates from the vector
/* Note: We could just use the following more efficient one-liner for this
vectorstring.erase(std::remove(vectorstring.begin(), vectorstring.end(), temp), vectorstring.end());
*/
for (auto it = std::find(vectorstring.begin(), vectorstring.end(), temp); it != vectorstring.end(); it = std::find(vectorstring.begin(), vectorstring.end(), temp))
{
vectorstring.erase(it);
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.