-1

** 请不要批评代码本身的目的。它来自 Pat Morin 的 Open Data Structures 书。不是我的第一选择,它指定的阅读/练习。我只是想知道是否有区分的方法,或者更好的方法来解决这个问题。教科书--> http://opendatastructures.org/ods-cpp/ **

** 另一个注意事项:我来自 Java,这是允许的。我的代码仍然可以编译,它只是“修复”它**

我很惊讶以前没有出现过这样的问题,因为这似乎是一个简单的问题。也许它被埋没了,或者我没有使用正确的术语。

我有一个遍历向量中数据的 for 循环。如果找到,我需要返回正在搜索的值。如果找不到怎么办?这是我的代码。

int find(int x) {
    for(int i=0;i<bag.size();i++){
        // if x is equal to data, return data
        if (bag[i]==x){
            return bag[i]; // ends loop as soon as one instance is found
        }
    }
    // if we made it this far, no match was found.
    return NULL;

}

很简单。假设 0 是我可能需要记录和搜索的有效值之一。事实上,它实际上返回 0,而不是“NULL”。研究表明它是一回事。如何指定或区分?除了返回一个不会出现在程序中的晦涩数字之外,因为我们可能并不总是拥有那种奢侈(如 -1 或 -9999999)。例如,搜索您的帐户余额。没有数字是不可能的。

4

5 回答 5

8

为什么要从 find 函数返回要搜索的值?您已经知道值,它是您传递给函数的值。而是返回找到的元素的位置,因为此信息更有用。当未找到该值时,您可以返回一个特殊位置,例如 -1。或者您可以遵循标准库的模型并返回结束迭代器,这表示一个位置超出范围的末尾。

于 2015-06-02T22:00:50.597 回答
3

您可以通过多种方式编写函数

bool find( int x ) 
{
    std::vector<int>::size_type i = 0;

    while (  i < bag.size() && bag[i] != x ) i++;

    return i != bag.size();
}

或者

std::vector<int>::size_type find( int x ) 
{
    std::vector<int>::size_type i = 0;

    while (  i < bag.size() && bag[i] != x ) i++;

    return i;
}

或者

#include <algorithm>

//...

std::vector<int>::iterator find( int x ) 
{
    return std::find( beg.begin(), bag.end(), x );
}

并通过以下方式对应使用功能

if ( find( x ) ) { /*...*/ }

if ( find( x ) != bag.size() ) { /*...*/ }

if ( find( x ) != bag.end() ) { /*...*/ }

至于你在帖子标题中的一般问题

如果我需要在 C++ 中区分 0 和 NULL 怎么办?

那么你需要使用nullptr而不是 NULL 来区分 0 和 NULL。:)

于 2015-06-02T22:12:03.833 回答
0
#define XOR_MSB(x) (x^0x80000000)

int find(bool found) {
    return found ? XOR_MSB(0) : NULL;
}

int main()
{
    int value = find(false);
    if (value == NULL) printf("not found\n");
    else printf("%d\n", XOR_MSB(value));
    value = find(true);
    if (value == NULL) printf("not found\n");
    else printf("%d\n", XOR_MSB(value));
    return 0;
}
于 2015-06-03T03:36:21.370 回答
-1

您说的是一种邪恶的做法,来自 Java 和 C# 开发人员,您可以在其中返回null无效结果。

好吧,你不能在 C++ 中做到这一点。Java 和 C# 几乎声明了堆上的所有内容,并且访问对象始终由引用完成。这意味着您始终可以从函数返回一个指针,并且您始终可以返回 null 作为返回值。

当函数不返回指针时,这在 C++ 中是不可能的。例如,该函数std::string returnString()不能将 null 作为返回值返回。

此外,您不应将 null 作为无效输出返回。即使在 C# 和 Java 中,这在很多层面上都是错误的!如果您的函数失败,只需抛出一个异常,或者将您的返回值作为引用参数传递,并使函数返回 true 或 false。

您还可以找到不太激进的解决方案,例如返回 -1(如indexOf()在 javascript 中)或返回类似std::string::nposstd::vector:end更多 C++ STL 调整的东西。

于 2015-06-02T22:04:57.723 回答
-2

这是boost::optional<T>为了什么。实际上,这种类型表示“可能有一个T,但可能没有一个T”。用户可以检查是否存在T。理想情况下,您不会依赖于任何特殊值,T而是使用 an optional<T>optional<T>是完全通用的,可能适用于您可能需要使用的几乎任何T东西,它不依赖于T.

boost::optional<int> find(int x) {
    for(int i=0;i<bag.size();i++){
        // if x is equal to data, return data
        if (bag[i]==x){
            return bag[i]; // ends loop as soon as one instance is found
        }
    }
    // if we made it this far, no match was found.
    return boost::none;    
}
int main() {
    if (auto opt = find(5))
        std::cout << *opt;
}

永远不要使用NULL,这是一件可怕的事情。始终使用nullptr更安全的方法,它更安全的原因之一是因为您的错误代码无法编译。

于 2015-06-02T22:08:48.667 回答