在C++中使用find函数时出现问题

Trouble using find function in C++

本文关键字:问题 函数 find C++      更新时间:2023-10-16

当我使用std::find时,我正试图找出代码中的差异。

对于我的测试代码。我制作了一个名为Test 的矢量

std::vector<const char*> Test;

为了测试find函数,我使用push_back函数在test矢量中填充了伪数据

Test.push_back("F_S");
Test.push_back("FC");
Test.push_back("ID");
Test.push_back("CD");
Test.push_back("CT");
Test.push_back("DS");
Test.push_back("CR");
Test.push_back("5K_2");
Test.push_back("10K_5");
Test.push_back("10K_1");
Test.push_back("10K_2");
Test.push_back("10K_3");
Test.push_back("10K_4");
Test.push_back("10K_5");

我想用find函数做的是通过测试,看看是否有任何重复的数据。第一次遇到数据时,我会将其保存到一个名为Unique_data的向量中。

std::vector<const char*> Unique_Data;

因此,对于上面的14个数据点,由于10K_5重复,将只保存13个。

我使用的代码看起来像这个

for(int i = 0; i < Test.size(); i++) 
    {
        if( Unique_Data.empty())
        {
            Unique_Data.push_back(Test[i]);
        }
        else if (std::find(Unique_Data.begin(), Unique_Data.end(), Test[i]) != Unique_Data.end())
        {
            // Move on to next index
        }
        else
        {
            Unique_Data.push_back(Test[i]);
        }
    }

我遇到的问题是当我使用伪数据时。我得到了Unique_Data的正确答案。

但是,如果我将实际数据保存到保存在链表中的测试向量中。我知道它们都是独一无二的。

代码看起来像这个

p_curr = List.p_root;
    while(p_curr != NULL)
    {
            // id starts from 0
        if(atoi(p_curr->id) == 14) break;
        Test.push_back(p_curr->Descriptor);
        p_curr = p_curr->p_next;
    }

我用同样的14个数据进行了测试。它们都是const-char*类型。但是,当我使用链表数据时。find函数认为所有数据都是唯一的。

有人能告诉我这是怎么回事吗?

使用C风格的字符串有点棘手,它们只是一个指针,指针是通过标识进行比较的。两个C字符串具有相同的字符序列,但不同的地址会比较不同。

const char first[] = "Hi";
const char second[] = "Hi";
assert(first == second);     // will fail!

这个问题有两种解决办法。简单的方法是在容器中使用std::string,因为std::string将提供值比较。另一种选择是将比较函子作为最后一个参数传递给std::find。但这仍然会留下管理存储在向量中的const char*-s的寿命的问题。

这是一个指针问题。您不是在数组中存储字符串,而是在字符串中存储数据的内存地址。

这种奇怪的行为可能是因为在您的示例中,您有无法更改的文本字符串,因此编译器正在优化存储,当两个字符串相同时,它会为所有具有相同文本的字符串存储相同的地址。

在实际数据示例中,有一组字符串保存相同的数据,但这些字符串中的每一个都位于不同的内存地址,因此find函数表示所有字符串都有不同的地址。

总之,find函数查看的是字符串的内存地址,而不是字符串中的数据(文本)。如果使用std::string,那么这个问题就会消失。

我强烈建议使用字符串,因为性能会非常好,而且它们可以消除大量问题。

正如David Rodriguez在回答中提到的,您只比较指针,而不是字符串本身的内容。如果存储std::string而不是char const *,您的解决方案将按原样工作。对于后者,您需要使用std::find_if和调用strcmp的谓词来确定字符串是否相同。

#include <iostream>
#include <vector>
#include <algorithm>
#include <cstring>
int main()
{
    std::vector<const char*> Test;
    Test.push_back("F_S");
    Test.push_back("FC");
    Test.push_back("ID");
    Test.push_back("CD");
    Test.push_back("CT");
    Test.push_back("DS");
    Test.push_back("CR");
    Test.push_back("5K_2");
    Test.push_back("10K_5");
    Test.push_back("10K_1");
    Test.push_back("10K_2");
    Test.push_back("10K_3");
    Test.push_back("10K_4");
    Test.push_back("10K_5");
    std::vector<const char*> Unique_Data;
    for(auto const& s1 : Test) {
        if(std::find_i(Unique_Data.cbegin(), Unique_Data.cend(), 
            [&](const char *s2) { return std::strcmp(s1, s2) == 0; })
            == Unique_Data.cend()) {
            Unique_Data.push_back(s1);
        }
    }
    for(auto const& s : Unique_Data) {
        std::cout << s << 'n';
    }
}

下面是的一个实例