2017-08-04 15 views
12

ABCという3つの文字列変数があります。C++で文字列変数がnullptrでないか確認してください

何か問題が起きた場合にはnullptrを返すことがある別の関数から割り当てます。このように:

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

さて、これらの変数を持ついくつかのもののために、私は一つだけ、これらの変数のがnullptrでない場合(変数の一つだけが割り当てられている)を確認する必要があります。

私は自分自身が好きこれを実行しようとしました:

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

これを行う方法についての任意のアイデアは歓迎されています。 nullptrであるし、そうでない場合はカウントを増やすため

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

チェック各:

+1

'xor'をチェーンできませんでしたか? '!(A^B^C)'のようなものです。 '^'はビット単位ですが、うまくいくでしょうか?ちょうどボールを吐き出す。 – Carcigenicate

+0

@Carcigenicateありがとう!しかし、私は決して 'xor'をC++で使ったことはありません:-(それはとにかく試してみます。 – Blueeyes789

+1

実際に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; 
} 

それとも、以下のとおり、ラムダ関数を使用することによって、そのすべての栄光に現代の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

ありがとう!これはうまくいった。しかし、私はXORも見ていきます。 :-) – Blueeyes789

+0

割り当てを避けるために 'std :: vector'ではなく' std :: initializer_list'を使用できませんでした。それと... 'std :: count'。 –

+4

私はこれまでにC++で直ちに呼び出されたラムダ式を見たことがありません。なぜなら、for(const auto&pointer:{A、B、C、D、E、F}){... –

7

は、ここに1つの簡単な方法です。最終的にカウントが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との下位互換性のために、関係演算子の戻り値は、0または1に等しいintです。だから、行うことができます。

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のソリューションと同じですが、よりコンパクトな「nullの場合のテスト」チェックと同じです。

このアプローチは、受け入れられたアプローチとほぼ同じだけでなく、読みにくいですが、オーディエンスやコードを読んでいる人によってはうまくやっているかもしれません。

+0

これはコードゴルフだったら勝てます!私は実際にはそれをそのように書いているとは思わないが、それは賢明だ。 – Davislor

関連する問題