2015-06-02 95 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; 
} 
相關問題