Могу ли я использовать препроцессор, чтобы сделать это один понятнее?

голоса
2

Я пишу немного функции исходного файла для моего PIC32 и я получил stucked на одну вещь. Это в основном программа , которая должна хранить Incomming charданных в буфер , а затем, если '\r'будет получено, он сравнивает буфер против списка команд (в массиве names), и если совпадение найдено, то индекс элемента возвращается.

Эта часть из заголовка:

#define NAMECNT 6    
static const char names[NAMESCNT][10] = {   // 6commands, max 10 char each
        korr,         // 1
        adc,          // 2
        fft,          // 3
        data,         // 4 
        pr,           // 5
        prsc};        // 6

/* functions */
extern int comm(char cdata);

В главном файле, есть один большой переключатель:

switch( comm(recieved_ch) ){
case 1: foo1(); break; 
case 2: foo2(); break;
...
}

Теперь, для большей ясности, я хотел бы использовать вместо 1, 2, ... оригинальных имен (как case KORR: case ADC:) , поэтому я написал deffinitions для каждого из них

#define KORR 1
#define ADC 2

Но мне не нравится это решение, потому что я хочу использовать этот исходный файл в более проектах и есть буду по- другому списка команд для каждого. Есть ли способ , как это сделать? Лучше всего было бы создать имена массивов в препроцессоре, но я сомневаюсь , что это вообще возможно. Я думал об использовании перечислимого типа (которые будут иметь одни и те же элементы , как список команд names), но я не уверен , как бы это пойти.

Задан 05/09/2016 в 13:17
источник пользователем
На других языках...                            


2 ответов

голоса
2

Вы можете использовать X-макросы для построения enumи заполнить массив, то вы можете использовать enumзначение в switch:

#define VARS \
    X(korr) \
    X(adc)  \
    X(fft)  \
    X(data) \
    X(pr)   \
    X(prsc)

static const char names[][10] = {   // 6commands, max 10 char each
#define X(name) #name,
    VARS
#undef X
};

enum evars {
#define X(name) name, 
    VARS
#undef X
};

extern int comm(char cdata);

int main(void)
{
    char x = 1;

    switch (comm(x)) {
        case korr:
            printf("korr");
            break;
        case adc:
            printf("adc");
            break;
        /* ... and so on */
    }
    return 0;
}

Расширение Xсоставляет:

static const char names[][10] = {

 "korr", "adc", "fft", "data", "pr", "prsc",

};

enum evars {

 korr, adc, fft, data, pr, prsc,

};

Изменить: Как отметили @ 5gon12eder, вам не нужно жёстко 6 в первом измерении массива (вы можете оставить его неопределенным).

Ответил 05/09/2016 в 13:49
источник пользователем

голоса
2

Препроцессор может сделать вещи более четкие здесь, я думаю, с помощью оператора concatentation ##, но он не будет давать преимущество в производительности. switchЗаявление может быть оптимизировано компилятором, но это зависит от конкретной реализации.

Вместо «один большой переключатель,» использовать массив указателей на функции. Что-то вроде

func_ptrs[comm(received_ch) - 1]();

будет вызывать соответствующую функцию, где foo1находится в индексе 0, foo2в 1и т.д. Чтобы добавить команду, просто добавьте имя команды в список команд и указатель на функцию func_ptrs.

В конце концов, вы убиваете двух зайцев: создать простой способ для добавления команды и повышения производительности.


Кроме того, линейный поиск через массив строк довольно неэффективен. Хэш-таблица даст преимущество в производительности.

Ответил 05/09/2016 в 13:26
источник пользователем

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more