繁体   English   中英

矢量查找返回错误的值

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

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM