2015-06-02 28 views
-2

**请不要批评代码本身的目的。它来自Pat Morin的开放数据结构书。不是我的第一选择,它的分配阅读/练习。我只是想知道是否有办法区分,或者有更好的方法来解决这个问题。教材 - >http://opendatastructures.org/ods-cpp/ **如果我需要在C++中区分0和NULL,该怎么办?

**另注:我从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”。研究表明它是一样的。我如何指定或区分?除了返回一个不会出现在程序中的obsqure数字,因为我们可能并不总是有这样的奢侈品(比如-1或-9999999)。例如,搜索您的帐户余额。没有数字是不可能的。

+0

如果发现X(作为参数传递),什么是传递返回相同值的点作为参数?为什么不使用'bool'作为返回值呢? – Unda

+0

'NULL'并不意味着是'int' =>反正代码是错误的。作为搜索方法的错误值,'-1'通常是。 – deviantfan

+0

我是否理解如果找到该值,该函数返回与输入相同的值?如果是的话,你只需要返回任何其他号码,调用代码将能够知道它是否被发现。或者更好,只是让它返回真或假。 – user463035818

回答

8

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

+0

返回'可选'比发明一个特殊位置值更好 – Puppy

+0

@Puppy假设他使用Boost,这根本就不是微不足道的。 –

+1

@Puppy:不,它不是。当调用者已经知道这个值时,为什么你会构造一个不必要的对象? –

-1

你在谈论一个邪恶的做法,从Java和C#开发人员,你可以返回null为无效的结果来。

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

这是不是在C所以可能++当一个函数不返回一个指针。例如,函数std::string returnString()不能返回null作为返回值。

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

您还可以找到像返回-1(如javascript中的indexOf())或返回诸如std::string::nposstd::vector:end之类的较不积极的解决方案,它们是更多的C++ STL调优。

+0

这些都不是正确的答案。根据你的用例(在Java或C#中),返回'null'为“未找到”可以很好。诸如'indexOf()','std :: string :: npos'和朋友之类的东西都很糟糕,因为它们不是通用的。 'std :: vector :: end'稍微坏一点,因为它是通用的,但只是以特定的方式。 – Puppy

-2

这是boost::optional<T>的用途。实际上,这种类型表示“可能有T,但可能没有T”。用户可以检查是否存在T。理想情况下,您不会依赖T的任何特殊值,而是使用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这是更安全的,它更安全的原因之一是因为你的错误代码不会编译。

+0

我发现可以赞美'boost :: optional',但很容易忘记它会在调用站点创建“开销”,而在main中没有考虑到这个开销,从而导致潜在的错误代码。 –

+0

尝试使用基本而不是其他包含boost :: optional类型的关键字的库。 –

2

您可以编写功能以多种方式

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++的NULL区分0?

,那么你需要使用FO的nullptr代替NULL是从NULL区分0。:)

+1

显示算法首先鼓励使用stl而不是编写自己的循环会很有意义 –

+0

@Glenn Teitelbaum也许现在对他来说,将函数自己写成exersize更重要。 –

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; 
} 
相关问题