Мой вопрос:
if (/* condition A */)
{
if(/* condition B */)
{
/* do action C */
}
else
/* ... */
}
else
{
/* do action C */
}
Можно ли просто написать код действия C один раз вместо двух?
Как это упростить?
Мой вопрос:
if (/* condition A */)
{
if(/* condition B */)
{
/* do action C */
}
else
/* ... */
}
else
{
/* do action C */
}
Можно ли просто написать код действия C один раз вместо двух?
Как это упростить?
Ответы:
Ваш первый шаг в решении подобных проблем - создание логической таблицы.
Как только вы сделали таблицу, решение станет ясным.
Обратите внимание, что эта логика, хотя и короче, может быть трудной для будущих программистов.
источник
B
имеет побочные эффекты, логическая таблица должна это учитывать.A && !B
дело не в опере:!(A && !B)
это эквивалентно тому,!A || B
что вы можете сделатьif (!A || B) { /* do action C */ }
и избежать пустого блока.if (A && !B)
будущим программистам действительно трудно поддерживать, то им действительно нет никакой помощи.У вас есть два варианта:
Напишите функцию, которая выполняет «действие C».
Переставьте свою логику, чтобы у вас не было так много вложенных операторов if. Спросите себя, какие условия вызывают «действие С». Мне кажется, что это происходит, когда «условие В» истинно или «условие А» ложно. Мы можем написать это как «НЕ А ИЛИ Б». Переводя это в C-код, мы получаем
Чтобы узнать больше о такого рода выражениях, я предлагаю поискать «булеву алгебру», «логику предикатов» и «исчисление предикатов». Это глубокие математические темы. Вам не нужно изучать все это, только основы.
Вы также должны узнать о «оценке короткого замыкания». Поэтому порядок выражений важен для точного дублирования вашей исходной логики. Хотя
B || !A
логически эквивалентно, использование этого в качестве условия будет выполнять «действие C», когдаB
оно истинно, независимо от значенияA
.источник
...
есть практическое различие . Если это вообще ничего (т. Е. «Делай С, если эти условия выполняются; в противном случае ничего не делай»), тогда это явно лучшее решение, так как тогда этоelse
утверждение можно просто пропустить.Вы можете упростить утверждение следующим образом:
В противном случае поместите код для «C» в отдельную функцию и вызовите его:
источник
if (!A || B)
B || !A
будет работатьtrue
только в том случае , еслиB
естьtrue
, без фактической проверки на наличиеA
короткого замыканияA
и чтоB
означает.На языке с сопоставлением с образцом вы можете выразить решение так, чтобы оно более непосредственно отражало таблицу истинности в ответе на вопрос C.
Если вы не знакомы с синтаксисом, каждый шаблон представлен знаком | за ними следуют значения, совпадающие с (a, b), и подчеркивание используется в качестве подстановочного знака для обозначения «любых других значений». Поскольку единственный случай, когда мы хотим сделать что-то кроме действия c, это когда a истинно, а b ложно, мы явно указываем эти значения как первый шаблон (истина, ложь) и затем делаем все, что должно быть сделано в этом случае. Во всех остальных случаях мы переходим к шаблону «подстановочный знак» и выполняем действие c.
источник
Постановка проблемы:
описывает импликацию : A подразумевает B , логическое утверждение, эквивалентное
!A || B
(как упомянуто в других ответах):источник
inline
для C,constexpr
а также для C ++?Тьфу, это тоже сбило меня с толку , но, как указывает Code-Apprentice, нам гарантированно понадобится
do action C
или запустит вложенныйelse
блок, поэтому код можно упростить до:Вот как мы попали в 3 случая:
do action C
в логику вашего вопроса требуетсяcondition A
иcondition B
должна быть ...true
В этой логике, если мы достигнем 2- го слагаемого вif
утверждении, тогда мы знаем, чтоcondition A
,true
таким образом, все, что нам нужно оценить,condition B
этоtrue
else
-блок в логике вашего вопроса долженcondition A
бытьtrue
иcondition B
должен бытьfalse
- Единственный способ, которым мы можем достичьelse
-блока в этой логике, был бы, если быcondition A
былtrue
иcondition B
былfalse
else
-блок в логике вашего вопроса долженcondition A
бытьfalse
- В этой логике, еслиcondition A
ложь, мы такжеdo action C
Реквизиты Code-Apprentice за то, что выправили меня здесь. Я бы предложил принять его ответ , так как он представил его правильно, без редактирования: /
источник
B
будет оцениваться, только если!A
ложно. Таким образом, оба должны потерпеть неудачу для выполненияelse
операторов.!A || B
ложна именно тогда, когда оба!A
иB
ложны. Следовательно,A
будет верно, когдаelse
исполняется. Не нужно переоцениватьA
.В концепции логики вы можете решить эту проблему следующим образом:
Как доказанная проблема, это приводит к
f = !a + b
. Есть несколько способов доказать эту проблему, такие как таблица истинности, карта Карно и так далее.Так что в языках на основе C вы можете использовать следующее:
PS: Карта Карно также используется для более сложной серии условий. Это метод упрощения выражений булевой алгебры.
источник
Хотя уже есть хорошие ответы, я подумал, что этот подход может быть еще более интуитивным для того, кто плохо знаком с булевой алгеброй, чем для оценки таблицы истинности.
Первое, что вы хотите сделать, это посмотреть, при каких условиях вы хотите выполнить C. Это тот случай, когда
(a & b)
. Также когда!a
. Так и есть(a & b) | !a
.Если вы хотите свести к минимуму, вы можете продолжать. Как и в «обычной» арифметике, вы можете умножить.
(a & b) | !a = (a | !a) & (b | !a)
, а | ! А всегда верно, так что вы можете просто пересечь его, который оставляет вас с свернутым результатом:b | !a
. В случае, если порядок имеет значение, потому что вы хотите проверить b, только если! A истинно (например, когда! A является проверкой нулевого указателя, а b является операцией над указателем, как @LordFarquaad указал в его комментарии), вы можете хочу поменять два.Другой случай (/ * ... * /) всегда будет выполняться, когда c не выполняется, поэтому мы можем просто поместить его в другой случай.
Также стоит упомянуть, что, вероятно, имеет смысл использовать способ c в методе.
Что оставляет нас со следующим кодом:
Таким образом, вы также можете минимизировать термины с помощью большего числа операндов, что быстро уродливо с таблицами истинности. Еще один хороший подход - карты Карно. Но я не буду углубляться в это сейчас.
источник
Чтобы код выглядел больше как текст, используйте логические флаги. Если логика особенно неясна, добавьте комментарии.
источник
источник
Я извлек бы C в метод, а затем выйду из функции как можно скорее во всех случаях.
else
пункты с одной вещью в конце почти всегда должны быть инвертированы, если это возможно. Вот пошаговый пример:Извлечь C:
Обрати сначала,
if
чтобы избавиться от первогоelse
:Избавьтесь от второго
else
:И тогда вы можете заметить, что два случая имеют одинаковое тело и могут быть объединены:
Необязательные вещи для улучшения будут:
зависит от контекста, но если
!A || B
сбивает с толку, извлеките его в одну или несколько переменных, чтобы объяснить намерениекакой бы из
C()
илиD()
не был исключительный случай должен идти последним, так что еслиD()
это исключение, то инвертироватьif
последний разисточник
Использование флагов также может решить эту проблему
источник