Если выполняется условие 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 
}