Проверьте, не является ли только одна строковая переменная nullptr в C++
у меня есть три LPCWSTR
строковые переменные называются A
, B
, C
.
Я назначаю их из другой функции, которая иногда может возвратить nullptr
если что-то пойдет не так. вот так:
A = MyFunc();
B = MyFunc();
C = MyFunc();
теперь, для некоторых вещей с этими переменными, мне нужно проверить, не является ли только одна из этих переменных nullptr
(назначается только одна из переменных).
Я попытался сделать это сам, как:
if ((A == nullptr) && (B == nullptr) && (C <> nullptr)) {}
любые идеи о том, как это сделать добро пожаловать.
5 ответов
достаточно легко сделать с:
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
следующий шаг оттуда будет использовать диапазон на основе цикла в сочетании с braced init list, согласно следующей программе:
#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;
}
Это, наверное, перебор для вашего конкретного случая, однако :-)
С std, вы можете сделать:
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.
вот один простой способ:
int not_null = 0;
not_null += A != nullptr;
not_null += B != nullptr;
not_null += C != nullptr;
if (not_null == 1) {
/* Do stuff */
}
проверьте каждый дляnullptr
и увеличьте количество, если это не так. Если граф выходит как 1
в конце концов, делай свое дело.
в C++ для обратной совместимости с C возвращаемым значением реляционного оператора является int
равна 0
или 1
. Так что вы можете сделать:
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).
Я не большой поклонник используя методы, такие как следующие в целом, но вы можете использовать тот факт, что для любого указателя ptr
что !!ptr
вычисляет 0 для нулевого указателя и 1 для ненулевого указателя для записи
if (!!A + !!B + !!C == 1) {
...
}
как плотный способ заставить это работать. Это по существу то же самое, что и решение @Davislor, но с более компактной проверкой "test if null".
этот подход не масштабируется почти так же хорошо, как принятый подход, и его сложнее читать, но в зависимости от вашей аудитории и кто читает код, это может сделать трюк красиво.