Каков альтернативный способ выполнения функции switch-case (и if-else) в c? - PullRequest
1 голос
/ 13 июля 2009

Каков альтернативный способ выполнения функции switch-case (и if-else) в c?

Ответы [ 4 ]

3 голосов
/ 13 июля 2009

Функциональные указатели являются одной из альтернатив. Рассмотрим следующий фрагмент, который вызывает функцию через массив указателей на функции:

#include <stdio.h>

void fn0(int n) { printf ("fn0, n = %d\n",n); }
void fn1(int n) { printf ("fn1, n = %d\n",n); }
void fn2(int n) { printf ("fn2, n = %d\n",n); }
void fn3(int n) { printf ("fn3, n = %d\n",n); }

static void (*fn[])(int) = {fn0, fn1, fn2, fn3};

int main(void) {
    int i;
    for (i = 0; i < 4; i++)
        fn[i](10-i);
    return 0;
}

Это генерирует:

fn0, n = 10
fn1, n = 9
fn2, n = 8
fn3, n = 7

Конструкция такого типа позволяет очень легко реализовать такие вещи, как конечные автоматы, где вместо массивного оператора switch или почти неуправляемого вложенного if можно просто использовать целочисленную переменную состояния для индексации в массив указателей на функции.

2 голосов
/ 13 июля 2009

Вы всегда можете использовать gotos ...: -p

1 голос
/ 13 июля 2009

Существует несколько различных способов обработки сценариев условного ветвления и переключения в C.

Типичными шаблонами, которые вы сами упоминаете, являются операторы switch () и группы if / else if / else. Однако иногда эти конструкции управления потоком не являются лучшим выбором для определенных проблем. Конкретные случаи, такие как:

  • Высокопроизводительное ветвление на большом домене
  • Ветвление на доменах значений, известных только во время выполнения
  • Изменение путей ветвления во время выполнения на основе других условий

В этих случаях я считаю полезными две схемы:

  1. Шаблон Стратегии с прямой рассылкой
  2. Шаблон Стратегии с цепной отправкой

В первом подходе вы отображаете каждое значение из вашего домена в коллекцию указателей на функции. Каждая функция обрабатывает конкретный случай (значение) из вашего домена. Это позволяет вам «переходить» прямо к правому обработчику для конкретного случая. Этот шаблон хорошо работает, когда каждый случай отделен от всех остальных, и мало или совсем нет пересекающейся логики.

Во втором подходе вы объединяете все методы диспетчеризации вместе и вызываете каждый из них для всех случаев. Каждый отправленный метод решает, обрабатывает ли он регистр или нет, и либо сразу возвращается, либо выполняет некоторую обработку. Этот шаблон полезен, когда есть перемычки между обязанностями некоторых обработчиков. Он несколько менее производительный, так как вызывается несколько обработчиков, и каждый решает, нужно ли ему выполнять свою обработку. Однако это один из самых простых способов справиться с перекрывающейся логикой - такой, который вы обычно можете обрабатывать в операторе switch () в условиях сбоя (или перехода).

Вы должны использовать только один из этих методов, если проблема действительно требует этого, поскольку они менее очевидны для будущих разработчиков и могут привести к ненужным сложностям и проблемам обслуживания, если они плохо реализованы. Это также делает ваш код более трудным для понимания, по сравнению с более распространенными конструкциями, такими как switch или if / else.

1 голос
/ 13 июля 2009

Функциональные указатели и полу-реализация шаблона стратегии:)

.. хотя вам потребуется некоторая логика, чтобы определить, какую функцию вызывать

...