我们可以在c中使用带有字符串的switch-case语句吗?

时间:2017-12-28 10:32:28

标签: c string switch-statement

int a = 0 , b = 0;
char* c = NULL;

int main(int argc , char ** argv){

    c = argv[2];
    a = atoi(argv[1]);
    b = atoi(argv[3]);

    switch(c){

        case "+": printf(a+b);
                  break;
    }

    printf("\n\n");

    return 0;
}

7 个答案:

答案 0 :(得分:3)

不,你不能。 switch的case标签需要是具有整数类型的编译时可评估常量表达式。

但是像int这样的'+'文字满足了这个要求。 (正如enum那样的值。)

有些人喜欢使用实现定义的多字符文字(例如'eax')作为case标签,因为他们声称它有助于提高可读性,但在那时,你放弃了一致的行为不同的平台。

如果您需要对NUL终止的char数组的值进行分支,请使用if块。

答案 1 :(得分:2)

不,你不能。 Switch用于比较数字类型和扩展字符类型。 相反,您应该使用字符串标题中包含的 strcmp 函数:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

int main(int argc, char * argv[]) {
  if (argc != 4) {
    puts("Incorrect usage");
    return 1;
  }
  /* You should check the number of arguments */

  char * op = argv[1];
  int a = atoi(argv[2]);
  int b = atoi(argv[3]);
  /* You should check correct input too */

  if (strcmp(op, "+") == 0)
    printf("%d + %d = %d\n", a, b, a + b);
  else if (strcmp(op, "-") == 0)
    printf("%d - %d = %d\n", a, b, a - b);
  /* Add more functions here */

  return 0;
}

答案 2 :(得分:1)

不,那是不可能的。

引用C11,章节§6.8.4.2

  

switch语句的控制表达式应具有整数类型。

答案 3 :(得分:1)

在您的情况下,您似乎不需要字符串,而是switch语句中传递的字符串的第一个(也是唯一的字符),在这种情况下,可能使用case语句中的字符文字(具有整数类型):

if (strlen(c)==1)
{
  switch(c[0]){

    case '+': printf(a+b);
              break;
    ...
  }
}
当字符串有多个字符时,best way to switch on a string in C中描述了一些其他好的选择。

答案 4 :(得分:1)

答案有两种情况..

首先6.8.4.2switch案例)

  

switch语句的控制表达式应该是整数   型

其次 6.8.4.2 case陈述)

  

每个案例标签的表达式应为整数常量   表达式并且没有两个case常量表达式相同   switch语句在转换后应具有相同的值

长话短说 - 你不能像这样使用字符串文字。在切换控制表达式和case中都没有。

您可以使用strcmp进行字符串比较,然后进行if-else调节。您提出此问题的上下文,您只需传递字符+argv[2][0]),而不是传递整个文字。这样您就可以将char传递给switch表达式,然后相应地工作。

答案 5 :(得分:0)

不直接。但是,你可以。

#include <ctype.h>
#include <stdio.h>
#include <string.h>

// The way you store and search for names is entirely 
// up to you. This is a simple linear search of an 
// array. If you have a lot of names, you might choose
// a better storage + lookup, such as a hash table.
int find( const char** ss, int n, const char* s )
{
  int i = 0;
  while (i < n)
    if (strcmp( ss[i], s ) == 0) break;
    else                         i += 1;
  return i;
}

// A bevvy of little utilities to help out.
char* strupper( char* s )
{
  char* p = s;
  while ((*p = toupper( *p ))) ++p;
  return s;
}

char* zero( char* p ) { if (p) *p = 0; return p; }

#define STRINGIFY(S) STRINGIFY0(S)
#define STRINGIFY0(S) #S

int main()
{
  // Our list of names are enumerated constants with associated
  // string data. We use the Enum Macro Trick for succinct ODR happiness.
  #define NAMES(F) \
    F(MARINETTE) \
    F(ADRIAN) \
    F(ALYA) \
    F(DINO)
  #define ENUM_F(NAME) NAME,
  #define STRING_F(NAME) STRINGIFY(NAME),
  enum names { NAMES(ENUM_F) NUM_NAMES };
  const char* names[ NUM_NAMES ] = { NAMES(STRING_F) NULL };
  #undef STRING_F
  #undef ENUM_F
  #undef NAMES

  // Ask user for a name
  char s[ 500 ];
  printf( "name? " );
  fflush( stdout );
  fgets( s, sizeof( s ), stdin );
  zero( strchr( s, '\n' ) );

  // Preprocess and search for the name  
  switch (find( names, sizeof(names)/sizeof(*names), strupper( s ) ))
  {
    case MARINETTE: puts( "Ladybug!" ); break;
    case ADRIAN:    puts( "Chat Noir!" ); break;
    case ALYA:      
    case DINO:      puts( "Best friend!" ); break;
    default:        puts( "Who?" );
  }
}

请记住,这是纯粹的,纯粹的魔术技巧,不适合大量文本值。

此外,匹配的有效性完全取决于您预处理用户输入的程度。在这个例子中,我们只忽略大小写,但更高级的应用程序可能会执行更复杂的匹配。

答案 6 :(得分:0)

正如其他人在C中指出的那样,不能使用字符串作为开关的参数,也不能使用它的case-labels。

要解决此限制,可以将每个字符串映射到特定的整数,并将其传递给交换机。

查找映射需要搜索地图,这可以使用标准C bsearch()功能完成。

示例可能如下所示:

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <search.h>

enum Operation {
  OP_INVALID = -1,
  OP_ADD,
  OP_SUBTRACT,
  OP_MULTIPLY,
  OP_DIVIDE,
  OP_MAX
};

struct Operation_Descriptor {
  char * name;
  enum Operation op;
};

struct Operation_Descriptor operations [] = {
  {"add", OP_ADD},
  {"subtract", OP_SUBTRACT},
  {"multiply", OP_MULTIPLY},
  {"divide", OP_DIVIDE}
};

int cmp(const void * pv1, const void * pv2)
{
  const struct Operation_Descriptor * pop1 = pv1;
  const struct Operation_Descriptor * pop2 = pv2;

  return strcmp(pop1->name, pop2->name);
}

int main(int argc, char ** argv)
{
  size_t s = sizeof operations / sizeof *operations;

  /* bsearch() requires the array to search to be sorted. */
  qsort(operations, s, sizeof *operations, cmp);

  {
    struct Operation_Descriptor * pop = 
      bsearch(
        &(struct Operation_Descriptor){argv[1], OP_INVALID}, 
        operations, s, sizeof *operations, cmp);

    switch(pop ?pop->op :OP_INVALID)
    {
      case OP_ADD:
        /* Code to add goes here, */
        break;

      case OP_SUBTRACT:
        /* Code to subtract goes here, */
        break;

      case OP_MULTIPLY:
        /* Code to multiply goes here, */
        break;

      case OP_DIVIDE:
        /* Code to divide goes here, */
        break;

      case OP_INVALID:

      default:
        fprintf(stderr,  "unhandled or invalid operation '%s'\n", argv[1]);
        break;
    }
  }
}

如果在POSIX上,甚至可以使用哈希表,这是查找映射的最快方法。

示例可能如下所示:

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <search.h>

enum Operation {
  OP_INVALID = -1,
  OP_ADD,
  OP_SUBTRACT,
  OP_MULTIPLY,
  OP_DIVIDE,
  OP_MAX
};

struct Operation_Descriptor {
  char * name;
  enum Operation op;
};

struct Operation_Descriptor operations [] = {
  {"add", OP_ADD},
  {"subtract", OP_SUBTRACT},
  {"multiply", OP_MULTIPLY},
  {"divide", OP_DIVIDE}
};

int main(int argc, char ** argv)
{
  if (0 == hcreate(5))
  {
    perror("hcreate() failed");
    exit(EXIT_FAILURE);
  }

  for (size_t i = 0; i < s; ++i)
  {
    if (!hsearch((ENTRY){operations[i].name, &operations[i].op}, ENTER))
    {
      perror("hsearch(ENTER) failed");
      exit(EXIT_FAILURE);
    }
  }

  {
    ENTRY * ep = hsearch((ENTRY){argv[1], NULL}, FIND);

    switch(ep ?*((enum Operation *)ep->data) :OP_INVALID)
    {
      case OP_ADD:
        /* Code to add goes here, */
        break;

      case OP_SUBTRACT:
        /* Code to subtract goes here, */
        break;

      case OP_MULTIPLY:
        /* Code to multiply goes here, */
        break;

      case OP_DIVIDE:
        /* Code to divide goes here, */
        break;

      case OP_INVALID:

      default:
        fprintf(stderr,  "unhandled or invalid operation '%s'\n", argv[1]);
        break;
    }
  }

  hdestroy(); /* Clean up. */
}