How to correctly use a switch case

0

Hello, I can usually do a check by doing an if:

static const wchar_t *example=L"myprogram";

    if (!lstrcmpW(((LVITEMW*)lparam)->pszText, example))//The lparam is a LVITEM* struct.
            {
                return 0;
            }

But now I wanted to try to do it from a switch case ..:

switch ( ((LVITEMW*)lparam)->pszText ) {
  case L"pro.exe":            // Note the colon, not a semicolon
    return 0;
    break;
  default:     
    break;
  }

However I get the following errors:

dllmain.cpp:29:40: error: switch quantity not an integer
switch ( ((LVITEMW*)lparam)->pszText ) {
^
:30:10: error: could not convert '"p
static const wchar_t *example=L"myprogram";

    if (!lstrcmpW(((LVITEMW*)lparam)->pszText, example))//The lparam is a LVITEM* struct.
            {
                return 0;
            }
0r
switch ( ((LVITEMW*)lparam)->pszText ) {
  case L"pro.exe":            // Note the colon, not a semicolon
    return 0;
    break;
  default:     
    break;
  }
0o
dllmain.cpp:29:40: error: switch quantity not an integer
switch ( ((LVITEMW*)lparam)->pszText ) {
^
:30:10: error: could not convert '"p%pre%0r%pre%0o%pre%0.%pre%0e%pre%0x%pre%0e%pre%0%pre%0"' from 'const wchar_t [8]' to '<type error>'
case L"pro.exe": // Note the colon, not a semicolon
0.%pre%0e%pre%0x%pre%0e%pre%0%pre%0"' from 'const wchar_t [8]' to '<type error>' case L"pro.exe": // Note the colon, not a semicolon

What am I doing wrong? The problem esque has to be a wchar_t because ((LVITEMW*)lparam)->pszText ) will be a wchar_t.

    
asked by jeronimo urtado 31.03.2017 в 03:08
source

2 answers

0

As I mentioned in this other answer , the switch statement can only be used with some native types ... and an array of characters is not a native type.

However there are ways to simulate this behavior.

You can, as commented by @Trauma, calculate a hash for each string (the hash should be able to be stored in a basic C ++ numeric type) and use that hash to program the switch . The problem with this solution is that you would only get a clean solution from the C ++ 17 standard:

template<class LENGTH>
constexpr int GetHash(const wchar_t(&cadena)[LENGTH])
{
  // Calculo del hash
  // aqui no se puede usar ni memoria dinamica ni funciones no constexpr
}

int main()
{
  int i = 5;
  const wchar_t * cadena = /* ... */

  switch(GetHash(cadena))
  {
    case GetHash("OPCION1"):
      /* ... */
      break;

    case GetHash("OPCION2"):
      /* ... */
      break;

    // ...
  }
}

In previous versions you would have to precalculate the value of the different hashes.

Another possibility is to use a map to solve the operation by us:

void func(const wchar_t* cadena)
{
  // Tambien se podria usar std::unordered_map
  static std::map<wchar_t*,int> tablaConversion;

  // Para rellenar la tabla (solo se ejecuta la primera vez)
  if( tablaConversion.empty() )
  {
    // Se rellena el mapa...
    tablaConversion.insert(std::make_pair(L"OPCION1",1));
    tablaConversion.insert( /* ... */ );
  }

  auto it = tablaConversion.find(cadena);
  if( it != tablaConversion.end() )
  {
    switch( it->second )
    {
      case 1: // OPCION1
        /* ... */
        break;

      // ...
    }
  }
  else
    // aqui el contenido de la etiqueta "default"
}

This last version would admit a further twist and would consist of the map itself storing a pointer to the code to be executed in each case:

void func(const wchar_t* cadena)
{
  // std::function disponible a partir de C++11
  static std::map<wchar_t*,std::function<void()> tablaConversion;

  // Para rellenar la tabla (solo se ejecuta la primera vez)
  if( tablaConversion.empty() )
  {
    // Se rellena el mapa...
    tablaConversion.insert(std::make_pair(L"OPCION1",[](){ std::cout << "1"; }));
    tablaConversion.insert( /* ... */ );
  }

  auto it = tablaConversion.find(cadena);
  if( it != tablaConversion.end() )
  {
    it->second(); // Ejecutamos el codigo correspondiente a la opcion elegida
  }
  else
    // el texto no se encuentra en el mapa
}

There would be cleaner ways to fill in the map but they are not available in all versions of C ++ ... I leave it that way because I think it is easier to understand for everyone.

And finally, you can always replace the switch with a string of if-else .

    
answered by 31.03.2017 в 08:49
-1

As the options of the switch must be of the same type, I recommend that you put them in constants:

static const opcion1 *example=L"myprogram1";
static const opcion2 *example=L"myprogram2";

wchar_t var1 = ((LVITEMW*)lparam)->pszText;
switch ( var1 ) {
    case opcion1:
        return 1;
        break;
    case opcion2:
        return 2;
        break;
    default:     
        break;
}
    
answered by 31.03.2017 в 08:49