Язык Си. Управляющие операторы if, switch, ?:


Управляющие операторы - if, switch, ?:




if - условный оператор, оператор выбора. Если результат выражения не равен 0 то выполняется блок после оператора, иначе присутствует(если нужно) оператор else.
if( выражение )
{
   выполняется если выражение не равно 0
}
else
{
   выполняется если выражение равно 0
}
Также допускается вложенность этих операторов, но большая вложенность усложняет чтение кода, и увеличивает вероятность ошибок.
Ниже функция которая выполняет деление двух вещественных чисел, с проверкой деления на ноль(если вы не знаете, на 0 делить нельзя, зачастую приводит к падению программы).
В данном случае результат деления будет неверным, если вторым аргументом будет 0., но вопрос обработки ошибок это совершенно отдельная тема.

float div(float a, float b)
{
  if(b == 0.0f)
    return 0.0;
  return a / b;
}
int max(int a, int b)
{
  if(a > b)
    return a;
  return b;
}
if(enemy_in_range())
  attack();
else
  move_to_enemy();
if(   (range_to_enemy() >= 10 )
   && (range_to_enemy() <= 30 ))
{
  if(laser_reloaded())
    attack_by_laser();
  else
    move_to_enemy();
}
else if(range_to_enemy() < 10)
  attacked_by_bow();
else
  move_to_enemy();
/*
 * -1 - pressed n (no)
 *  0 - unknown
 *  1 - pressed y (yes)
*/
int getYesNo_v1(char aCh)
{
  if(aCh == 'n')
    return -1;
  if(aCh == 'y')
    return 1;
  return 0;
}
/*
 * -1 - pressed n/N (no)
 *  0 - unknown
 *  1 - pressed y/Y (yes)
*/
int getYesNo_v2(char aCh)
{
  if(aCh == 'n' || aCh == 'N')
    return -1;

  if(aCh == 'y' || aCh == 'Y')
    return 1;
}
!!Избегайте!! сложных выражений в операнде if
  int i = 0;
  if(++i && i || isOk(i))
    i = 0;


switch - оператор выбора. 
switch( выражение )
{
  case ? :
    break;
  default:
    break;
}
выражение должно быть целочисленным.  Оператор switch можно назвать оператором принятия решений, решение принимается основываясь на выражении и сравнивается с описаными константами в case, если же там нет требуемой константы и описан блок default то выполнение программы переходит в этот блок.
Выше вы видели примеры по if, посмотрите на последние 2 примера, getYesNo_v1(), getYesNo_v2(), ниже эти 2 примера с использованием оператора switch

/*
 * -1 - pressed n (no)
 *  0 - unknown
 *  1 - pressed y (yes)
*/
int getYesNo_v1(char aCh)
{
  switch(aCh)
  {
    case 'n':
      return -1;
    case 'y':
      return 1;
  }
  return 0;
}

/*
 * -1 - pressed n (no)
 *  0 - unknown
 *  1 - pressed y (yes)
*/
int getYesNo_v2(char aCh)
{
  switch(aCh)
  {
    case 'n':
    case 'N':
      return -1;

    case 'y':
    case 'Y':
      return 1;
  }
  return 0;
}

Как вы видите, в условиях когда нам нужно сделать выбор, основываясь на целоцисленном значении, которое можно сравнить с константами, то выбор в пользу switch очевиден.
Также в switch(может поддерживаться не всеми компиляторами), можно проверять на попадание значения в указанный диапазон.
/*
 * -1 - lower case
 *  0 - not char
 *  1 - upper case
*/
int getUpperLowerInfo(char aCh)
{
  switch(aCh)
  {
    case 'a' ... 'z':
      return -1;
    case 'A' ... 'Z':
      return 1;
  }
  return 0;
}
Управление роботом, который двигается к точка загрузки, загружается, потом двигается к точке разгрузки, затем опять к точка загрузки , и т.д.
  // robot state
  switch(state)
  {
    case 0: // move to point of unloading
    {
      if(!is_point_unload())
        move();
      else
        state = 1;
      break;
    }
    case 1: // unloading
    {
      unloading();
      if(empty())
        state = 2;
      break;
    }
    case 2: // move to point of loading
    {
      if(!is_point_load())
        move();
      else
        state = 3;
      break;
    }
    case 3: // loading 
    {
      loading();
      if(full())
        state = 0;
      break;
    }
    case 4: // stop doing
    default:
    {
      safe_mode();
      break;
    }
  }

Тернарный оператор ?: -  операнд_1 операнд_2 операнд_3
Тернарным оператором он называется потому что у оператора 3 операнда.
Этот оператор возвращает некоторое выражение, основываясь на первом операнде. Если первый операнд не равен 0 то возвращается 2й операнд, иначе возвращается 3й операнд. Это некий аналог оператора if - else
К примеру вернуть максимальное значение у двух операндов a и b
int max = a > b ? a : b;
или тоже самое с помощью if-else
  int max = 0;
  if(a > b)
    max = a;
  else
    max = b;
Тернарный оператор также поддерживает вложенность, но не рекомендую увлекаться, код должен быть простым, иначе увеличивается время его чтения, ухудшается возможность модификации из-за сложных выражений и т.д.
  int val = 0;
  // так лучше не делать
  val =    some_expr_a() 
        ? (some_expr_b() ? 1 : -1) 
        : (some_expr_c() ? 10);

  // лучше так
  if(some_expr_a())
    val = some_expr_b() ? 1 : -1;
  else
    val = some_expr_c() ? 10;


Что нужно помнить при использовании тернарного оператора:
Избегайте операндов с различными типами
1 ? 'A' : 1;
В этом примере будет выведен тип char но мы еще не знаем тип первого операнда, 
  int val = 0;
  val = 1 ? 'A' : 1;
А вот здесь, мы знаем тип первого операнда(int), значит будет неявное приведение типа char в int.
Иногда вот такие неявные приведения типов могут сыграть злую шутку, и в коде будет потенциальная ошибка, ИЗБЕГАЕМ операндов с различными типами! На крайний случай, если так делать нужно, то используем явное приведение типа.
  int val = 0;
  val = 1 ? (int)'A' : 1;
Вот это уже лучше, так как здесь мы явно приводим операнд к общему типу выражения, и другой программист читая этот код, поймет что вы это сделали намеренно, и знаете какой может быть результат, чего не скажешь о коде который был ранее, о котором можно подумать что вы допустили оплошность.
Или ниже второй пример, где явная ошибка, данные получаем не те которые ожидаем
  short a = 300;
  short b = 400;
  char res = 0;

  // много строк кода

  res = 1 ? a : b;

Если подвести итог, то!
Избегайте сложных выражение везде где это возможно, в том числе и в условных операторах.
Избегайте выражений у которых операнды с различными типами, или же явно приводите их к общему типу выражения.
Оператор switch работает только с целочисленными значениями, и операнды для case должны быть также целочисленными константами. Но если вы попробуете подставить туда не целочисленный тип, вам об этом напомнит компилятор :-)

Комментарии

  1. ВСЕ ПРОЧИТАЛИ ЭТО СВИДЕТЕЛЬСТВО О том, КАК Я ПОЛУЧИЛ ССУД ОТ ЮРИДИЧЕСКОЙ И НАДЕЖНОЙ КРЕДИТНОЙ КОМПАНИИ Меня зовут Кьерстин Лис, я искал ссуду для погашения своих долгов, все, с кем я встречался, обманывали и забирали мои деньги, пока я наконец не встретил г-на Бенджамина Брейл Ли Он смог дать мне ссуду в размере 450 000 рэндов и помог некоторым другим моим коллегам. Я говорю как самый счастливый человек во всем мире сегодня, и я сказал себе, что любой кредитор, который спасет мою семью из нашей бедной ситуации, я скажу имя всему миру, и я так счастлив сказать, что моя семья вернулся навсегда, потому что я нуждался в ссуде, чтобы начать свою жизнь с самого начала, так как я мать-одиночка с 3 детьми, и весь мир казался, что это висело на мне, пока я не имел в виду, что БОГ послал кредитора, который изменил мою жизнь и что из моей семьи, БОГ, боящийся кредитора, мистер Бенджамин, он был Богом Спасителем, посланным, чтобы спасти мою семью, и сначала я подумал, что это будет невозможно, пока я не получу ссуду, я пригласил его к моей семье получить -вместе вечеринка, от которой он не отказался, и я посоветую любому, кто действительно нуждается в ссуде, связаться с г-ном Бенджамином Брейлом Ли по электронной почте (247officedept@gmail.com), потому что он самый понимающий и добрый кредитор. когда-либо встречались с заботливым сердцем. Он не знает, что я делаю это, распространяя его доброжелательность ко мне, но я чувствую, что должен поделиться этим со всеми вами, связавшись с соответствующей кредитной компанией по электронной почте через: 247officedept@gmail.com или whatsapp + 1-989-394-3740. .

    ОтветитьУдалить

Отправить комментарий