Как вы определяете константу в C? - PullRequest
1 голос
/ 31 марта 2012

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

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;

Ответы [ 4 ]

4 голосов
/ 31 марта 2012

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

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

1 голос
/ 31 марта 2012

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

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:
    // ....
}
0 голосов
/ 31 марта 2012

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

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

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

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

// 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:
    ....
}
0 голосов
/ 31 марта 2012

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

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.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...