向量find返回了错误的值



这个程序的目的是从.txt文件中读取字符串,并将所有不重复的单词放入一个集合中。我将所有单词放入一个向量中,然后尝试遍历它,只将唯一的单词添加到集合中,并从向量中删除重复的单词。这是我的完整代码,底部是我遇到问题的部分。

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

这是给我带来麻烦的代码。每当我接近向量中的最后3ish元素时,find函数和";它";不要给我正确的输出。例如,如果正在搜索的临时值是"0";ben";并且这些字中的最后一个字已被删除,则其值不复位并保持"0";ben";在经历了find之后,使其看起来好像仍然存在"0"的值;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 << " ";
}

输出:

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

最新更新