2017-08-04 31 views
12

我有三個LPCWSTR字符串變量,稱爲A,。檢查C++中是否只有一個字符串變量不爲nullptr

我從另一個函數中指定它們,如果出現錯誤,有時可能返回nullptr。像這樣:

A = MyFunc(); 
B = MyFunc(); 
C = MyFunc(); 

現在,對一些東西用這些變量,我需要檢查,如果只有這些變量中的一個不nullptr(只有一個變量被分配)。

我想這個做自己喜歡:

if ((A == nullptr) && (B == nullptr) && (C <> nullptr)) {} 

有關如何做到這一點,歡迎任何想法。

+1

難道你不能連鎖'xor',然後否定結果嗎?像'!(A^B^C)'這樣的東西。 '^'是按位,但它可能工作?只是吐球。 – Carcigenicate

+0

@Carcigenicate謝謝!但是我從來沒有在C++中使用'xor' :-(無論如何都會試一試。 – Blueeyes789

+1

我們可以假設你不在乎哪一個是空的,只要其中一個是空的? – user4581301

回答

15

足夠容易做:

int numSet = 0; 
A = MyFunc(); if (A != nullptr) numSet++; 
B = MyFunc(); if (B != nullptr) numSet++; 
C = MyFunc(); if (C != nullptr) numSet++; 
if (numSet == 1) // only one is set 

你也可以封裝用輔助函數的行爲:

LPCWSTR MyFuncWithCount(int &countSetProperly) { 
    LPCWSTR retVal = MyFunc(); 
    if (retVal != nullptr) countSetProperly++; 
    return retVal; 
} 

int numSet = 0; 
A = MyFuncWithCount(numSet); 
B = MyFuncWithCount(numSet); 
C = MyFuncWithCount(numSet); 
if (numSet == 1) // only one is set 

下一步從那裏將使用基於範圍的循環連同支撐在它列表,按照下列完整的程序:

#include <iostream> 
#include <vector> 

typedef void * LPCWSTR; // Couldn't be bothered including Windows stuff :-) 

int main() { 
    // Only set two for test purposes. 

    LPCWSTR A = nullptr, B = nullptr, C = nullptr; 
    LPCWSTR D = &A,  E = nullptr, F = &A; 

    int numSet = 0; 
    for (const auto &pointer: {A, B, C, D, E, F}) 
     if (pointer != nullptr) 
      numSet++; 

    std::cout << "Count is " << numSet << std::endl; 
} 

或者你可以通過使用lambda函數擁抱在其所有的榮耀現代C++,按以下操作:

#include <iostream> 
#include <vector> 

typedef void * LPCWSTR; // Couldn't be bothered including Windows stuff :-) 

int main() { 
    // Only set two for test purposes. 

    LPCWSTR A = nullptr, B = nullptr, C = nullptr; 
    LPCWSTR D = &A,  E = nullptr, F = &A; 

    int numSet = 0; 
    [&numSet](const std::vector<LPCWSTR> &pointers) { 
     for (const auto &pointer: pointers) 
      if (pointer != nullptr) 
       numSet++; 
    } (std::vector<LPCWSTR>{A,B,C,D,E,F}); 

    std::cout << "Count is " << numSet << std::endl; 
} 

這可能但是,你的具體情況矯枉過正:-)

+0

謝謝!這起泡沫很好。不過,我也會看看異或。 :-) – Blueeyes789

+0

難道你不能使用'std :: initializer_list'而不是'std :: vector'來避免分配。那和......'std :: count'。 –

+4

我以前從來沒有在C++中見過立即調用的lambda表達式...爲什麼不是'for(const auto&pointer:{A,B,C,D,E,F}){...'? –

7

這裏有一個簡單的方法:

每個
int not_null = 0; 
not_null += A != nullptr; 
not_null += B != nullptr; 
not_null += C != nullptr; 
if (not_null == 1) { 
    /* Do stuff */ 
} 

檢查是nullptr和遞增計數,如果事實並非如此。如果計數最終以1的形式出現,請執行您的操作。

11

與標準,你可以這樣做:

const auto vars = {A, B, C}; // Create initializer list. 
const bool onlyOneNotNull = 
    (std::count(vars.begin(), vars.end(), nullptr) == (vars.size() - 1); 
// then you may use find_if to retrieve the non null variable. 
4

在C++中,爲了與C向後兼容,關係運算符的返回值是int等於01。所以,你可以這樣做:

if ((a != nullptr) + (b != nullptr) + (c != nullptr) == 1) 

如果你想使用邏輯運算符僅作爲邏輯運算符,也有析取範式與合取範式,儘管有更多的操作。

if ((a && !b && !c) || (!a && b && !c) || (!a && !b && c)) 

 

if ((a || b || c) && (!a || !b) && (!a || !c) && (!b || !c)) 

前者不難在這個簡單的例子看,相比於大多數其他的解決方案,但它會很快得到太冗長,如果有更多的可能的解決方案。

您也可以將它們粘貼在任何容器中,例如std::array<LPCWSTR, 3>,以及std::count(pointers.begin(), pointers.end(), nullptr)(如Jarod42建議的那樣)。

2

我不是一般使用以下技術的狂熱粉絲,但是您可以使用這樣一個事實,即任何指標ptr!!ptr對空指針評估爲0,對於寫空指針評估爲1

if (!!A + !!B + !!C == 1) { 
    ... 
} 

作爲一種密集的方式來得到這個工作。它基本上與@ Davislor的解決方案相同,但是具有更緊湊的「test if null」檢查。

這種方法幾乎不像已接受的方法那麼好,讀起來也比較麻煩,但根據你的讀者和誰在閱讀代碼,它可能會很好地實現這個技巧。

+0

如果這是代碼高爾夫你會贏!我認爲我不會那樣寫,但它很聰明。 – Davislor

相關問題