Andrei Cristian Prodan
Andrei Cristian Prodan

Reputation: 1122

How do you define a constant in C?

I'm trying to build a switch and I get an "expression must have integral or enum type". I'm guessing the switch in winapi doesn't take variables with LPSTR type?

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;

Upvotes: 1

Views: 232

Answers (4)

harper
harper

Reputation: 13690

C don't have case on char arrays. Only integer values are supported.

When you know that the length of the string that you want to use as a switch parameter does not exceed the size of a integer type, you can reinterpret the characters of your char array as a number.

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

When you have this number you can use number constants in your switch statement:

// 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:
    ....
}

Upvotes: 0

Mike Kwan
Mike Kwan

Reputation: 24447

In the regular case, you need to compare the strings with a string comparison algorithm like so:

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

However, interestingly, if the strings can be uniquely identified by their first 4 bytes and you want a more optimised switch, you can do tricks like this:

#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;
}

This prints etc case to the console because we take the string pointer and treat it as a DWORD pointer. The pointer is then dereferenced as such and compared against the DWORD value of the string. In this case the string is only 3 characters long but if we consider the null terminator on the end it can be uniquely identified by its first 4 bytes.

Note: It should be noted that this trick works only on architectures which allow unaligned access to memory. The reason is that potentially the string might not be DWORD aligned.

Upvotes: 0

harper
harper

Reputation: 13690

I usually use a kind of dictionary pattern:

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:
    // ....
}

Upvotes: 1

Mat
Mat

Reputation: 206689

This has nothing to do with WinAPI, it is plain C. The only thing you can switch on are integral (int, char and similar) or enum types, like your compiler is telling your.

If you need to "switch" on strings, you'll need to build and if/else sequence yourself and use strcmp or a variant thereof.

Upvotes: 4

Related Questions