Если выполняется условие A, условие B необходимо согласовать, чтобы выполнить действие C
Мой вопрос:
if (/* condition A */)
{
if(/* condition B */)
{
/* do action C */
}
else
/* ... */
}
else
{
/* do action C */
}
Можно ли просто написать код действия C один раз вместо двух?
Как его упростить?
Ответы
Ответ 1
Ваш первый шаг в таких проблемах всегда заключается в создании логической таблицы.
A | B | Result
-------------------
T | T | do action C
T | F | ...
F | T | do action C
F | F | do action C
После того, как вы создали таблицу, решение будет понятным.
if (A && !B) {
...
}
else {
do action C
}
Обратите внимание, что эта логика, хотя и короче, может быть трудной для будущих программистов.
Ответ 2
У вас есть два варианта:
-
Напишите функцию, которая выполняет "действие C" .
-
Измените свою логику так, чтобы у вас не было так много вложенных операторов if. Спросите себя, какие условия вызывают "действие C" . Мне кажется, что это происходит, когда либо "условие B" истинно, либо "условие A" является ложным. Мы можем написать это как "НЕ А ИЛИ В". Переведя это на C-код, получим
if (!A || B) {
action C
} else {
...
}
Чтобы узнать больше об этих выражениях, я предлагаю googling "логическая алгебра", "предикатная логика" и "исчисление предикатов". Это глубокие математические темы. Вам не нужно изучать все, просто основы.
Вы также должны узнать о "оценке короткого замыкания". Из-за этого порядок выражений важен для точного дублирования исходной логики. Хотя B || !A
логически эквивалентен, используя это как условие, будет выполняться "действие C" , когда B
истинно независимо от значения A
.
Ответ 3
Вы можете упростить утверждение следующим образом:
if ((A && B) || (!A)) // or simplified to (!A || B) as suggested in comments
{
do C
}
В противном случае поместите код для 'C' в отдельную функцию и вызовите его:
DoActionC()
{
....
// code for Action C
}
if (condition A)
{
if(condition B)
{
DoActionC(); // call the function
}
else
...
}
else
{
DoActionC(); // call the function
}
Ответ 4
В языке с сопоставлением с образцом вы можете выразить это решение таким образом, чтобы более прямо отражать таблицу истинности в ответе QuestionC.
match (a,b) with
| (true,false) -> ...
| _ -> action c
Если вы не знакомы с синтаксисом, каждый шаблон представлен символом | а затем значения, соответствующие (a, b), а подчеркивание используется в качестве подстановочного знака для обозначения "любых других значений". Поскольку единственный случай, когда мы хотим сделать что-то другое, кроме действия c, - это когда true и b является ложным, мы явно указываем эти значения как первый шаблон (true, false), а затем делаем все, что нужно сделать в этом случае. Во всех остальных случаях мы переходим к шаблону "подстановочные знаки" и делаем действие c.
Ответ 5
Оператор проблемы:
Если выполняется условие A, условие B необходимо согласовать, чтобы выполнить действие C
описывает implication: A подразумевает B, логическое предложение, эквивалентное !A || B
(как упоминалось в других ответах):
bool implies(bool p, bool q) { return !p || q; }
if (implies(/* condition A */,
/* condition B */))
{
/* do action C */
}
Ответ 6
Ух, это тоже сработало, но как указанному Code-Apprentice, нам гарантированно нужно do action C
или запустите nested- else
, поэтому код можно упростить до:
if (not condition A or condition B) {
do action C
} else {
...
}
Вот как мы сталкиваемся с тремя случаями:
- Вложенная
do action C
в вашей логике вопроса требуется condition A
и condition B
быть true
. В этой логике, если мы достигнем члена 2 nd в if
-statement, то мы знаем, что condition A
true
, поэтому все, что нам нужно оценить, состоит в том, что condition B
есть true
- Вложенная
else
-блока в вашей логике вопроса требуется condition A
быть true
и condition B
как false
- единственный способ, которым мы можем достичь else
-блока в этой логике было бы, если condition A
были true
и condition B
были false
- Внешний
else
-block в вашей логике вопроса требуется condition A
быть false
- В этой логике, если condition A
является ложным, мы также do action C
Репутация для Ученика Кодекса для выпрямления меня здесь. Я предлагаю принять его ответ, так как он правильно его представил без редактирования:/
Ответ 7
Несмотря на то, что уже есть хорошие ответы, я подумал, что этот подход может быть еще более интуитивным для того, кто является новым для булевой алгебры, а затем для оценки таблицы истинности.
Первое, что вы хотите сделать, это посмотреть, в каких условиях вы хотите выполнить C. Это тот случай, когда (a & b)
. Также при !a
.
Итак, у вас есть (a & b) | !a
.
Если вы хотите свести к минимуму, вы можете продолжать. Как и в "нормальных" арифметиках, вы можете размножаться.
(a & b) | !a = (a | !a) & (b | !a)
.
a |! a всегда верно, поэтому вы можете просто перечеркнуть его, что оставляет вас с минимальным результатом: b | !a
.
В случае, если порядок имеет значение, потому что вы хотите проверить b только в том случае, если! A истинно (например, когда! A - проверка с нулевым указателем, а b - операция над указателем, подобным @LordFarquaad, указанному в его комментарии), вы можете хотите переключить два.
Другой случай (/*... */) всегда будет выполняться, когда c не выполняется, поэтому мы можем просто положить его в случай else.
Также стоит упомянуть, что, вероятно, имеет смысл в любом случае поместить действие c в метод.
Это оставляет нам следующий код:
if (!A || B)
{
doActionC() // execute method which does action C
}
else
{
/* ... */ // what ever happens here, you might want to put it into a method, too.
}
Таким образом вы также можете свести к минимуму термины с большим количеством операндов, которые быстро становятся уродливыми с таблицами истинности. Другим хорошим подходом являются карты Карно. Но я не буду углубляться в это сейчас.
Ответ 8
В логической концепции вы можете решить эту проблему следующим образом:
f = a.b +! a
f =?
Как доказанная проблема, это приводит к f = !a + b
.
Есть несколько способов доказать эту проблему, например таблицу истинности, Карта Карно и т.д.
Итак, на языках с языком C вы можете использовать следующее:
if(!a || b)
{
// Do action C
}
P.S.: Карта Карно также используется для более сложных серий условий.
Это метод упрощения выражений булевой алгебры.
Ответ 9
Чтобы код выглядел больше как текст, используйте логические флаги. Если логика особенно неясна, добавьте комментарии.
bool do_action_C;
// Determine whether we need to do action C or just do the "..." action
// If condition A is matched, condition B needs to be matched in order to do action C
if (/* condition A */)
{
if(/* condition B */)
do_action_C = true; // have to do action C because blah
else
do_action_C = false; // no need to do action C because blarg
}
else
{
do_action_C = true; // A is false, so obviously have to do action C
}
if (do_action_C)
{
DoActionC(); // call the function
}
else
{
...
}
Ответ 10
if((A && B ) || !A)
{
//do C
}
else if(!B)
{
//...
}
Ответ 11
Я бы извлек C в метод, а затем выйду из функции как можно быстрее во всех случаях. else
предложения с единственной вещью в конце должны быть почти всегда перевернуты, если это возможно. Здесь представлен пошаговый пример:
Извлечь C:
if (A) {
if (B)
C();
else
D();
} else
C();
Инвертировать сначала if
, чтобы избавиться от первого else
:
if (!A) {
C();
return;
}
if (B)
C();
else
D();
Избавьтесь от второго else
:
if (!A) {
C();
return;
}
if (B) {
C();
return;
}
D();
И тогда вы можете заметить, что два случая имеют одно и то же тело и могут быть объединены:
if (!A || B) {
C();
return;
}
D();
Дополнительные вещи для улучшения:
-
зависит от контекста, но если !A || B
запутан, извлеките его в одну или несколько переменных, чтобы объяснить намерение
-
какой из C()
или D()
является не исключительным случаем, должен продолжаться последним, поэтому если D()
является исключением, то инвертируйте if
в последний раз
Ответ 12
Использование флагов также может решить эту проблему
int flag = 1;
if ( condition A ) {
flag = 2;
if( condition B ) {
flag = 3;
}
}
if(flag != 2) {
do action C
}