2012-03-31 3 views
1

Я пытаюсь создать переключатель, и я получаю выражение, которое должно иметь интегральный или перечисляемый тип. Я предполагаю, что переключатель в winapi не принимает переменные с типом LPSTR?Как вы определяете константу в C?

char testbuf[ 51 ]; // allocate space for 50 characters + termination 
LPSTR test = testbuf; 
scanf("%50s", test); // read at most 50 characters 
printf("%s", test); 
switch (test) { 
    case "etc" : 
     { 

     } 
    break; 

ответ

1

Я обычно использую вид словаря шаблона:

enum { 
    keyETC, 
    keyOther, 
    keyUnknown 
}; 
struct SDictionary{ 
    int key; 
    char *name; 
} dict[] = { 
    { keyETC, "etc" }, 
    { keyOther, "bla" }, 
    { 0 } 
}; 

// lookup 
struct SDictionary *pCandidate = dict; 
int key = keyUnknown; 

while (pCandidate->name) 
{ 
    if (0 == strcmp(test, pCandidate->name) 
    { 
     key = pCandidate->key; 
     break; 
    } 
} 

switch (key) 
{ 
    case keyETC: 
    // .... 
} 
4

Это не имеет ничего общего с WinAPI, то ясно, C. Единственное, что вы можете switch на одно целое (int, char и подобные) или типы перечислений, как ваш компилятор говорит ваш.

Если вам нужно «переключиться» на строки, вам нужно будет построить и if/else последовательность самостоятельно и использовать strcmp или его вариант.

0

В регулярном случае, вам нужно сравнить строки с помощью алгоритма сравнения струнный следующим образом:

if(strcmp(test, "etc") == 0) { 
    ... 
} 

Однако, что интересно, если строки могут быть однозначно определены первые 4 байта и вы хотите более оптимизированный переключатель, вы можете делать трюки, как это:

#include <Windows.h> 
#include <stdio.h> 

int main(void) 
{ 
    LPSTR test = "etc"; 

    switch(*(DWORD *)test) { 
    case 'cte': 
    puts("etc case"); 
    break; 
    default: 
    puts("not hit"); 
    break; 
    } 

    return ERROR_SUCCESS; 
} 

печатается etc case на консоль, потому что мы берем указатель на строку и рассматривать его как DWORD указатель. Затем указатель разыменовывается как таковой и сравнивается с значением строки DWORD. В этом случае строка длиной всего 3 символа, но если мы рассмотрим нулевой ограничитель на конце, ее можно однозначно идентифицировать по ее первым 4 байтам.

Примечание. Следует отметить, что этот трюк работает только на архитектурах, которые обеспечивают неравномерный доступ к памяти. Причина в том, что, возможно, строка не может быть выровнена по DWORD.

+0

Это неопределенное поведение: вы не имеете гарантии, что первый байт массива символов, где 'тест 'указывает на выравнивание по DWORD. Эта операция разыменования может вызвать исключение UNALIGNED. Дальше это не должно работать с большой конечной машиной, не так ли? – harper

+0

Чтобы облегчить ваши проблемы с выравниванием, '* (WORD *) (test + 1) == 'ct' && * (WORD *) (test) == 'te'' будет оценивать значение true. Тривиально 'test + 1' и' test' не могут быть скорректированы с помощью WORD :) Система абстрагирует неровный доступ. См. Здесь для получения дополнительной информации: http://msdn.microsoft.com/en-us/library/aa290049(v=vs.71).aspx. Фактически, именно поэтому неприглаженный доступ в цикле - такой убийца производительности! –

+0

Кроме того, Windows работает только на небольших конечных машинах: http://support.microsoft.com/kb/102025 и http://blogs.msdn.com/b/larryosterman/archive/2005/06/07/426334.aspx –

0

C не имеют дела на массивы символов. Поддерживаются только целые значения.

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

char *test = "etc"; 
int NumericalValue = 0; 
int size = min(sizeof(NumericalValue), strlen(test) + 1); 
memcpy(&NumericalValue, test, size) 

Если у вас есть этот номер, который вы можете использовать числовые константы в вашем переключателе заявлении:

// you need to adapt the actual values to your architecture's representation of numbers. 
const int keyETC = 0x00635445; 

switch (NumericalValue) 
{ 
case keyETC: 
    puts("etc case"); 
    break; 
default: 
    .... 
} 
Смежные вопросы