【问题标题】:can we use switch-case statement with strings in c? [duplicate]我们可以在c中使用带有字符串的switch-case语句吗? [复制]
【发布时间】:2018-06-08 21:41:25
【问题描述】:
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;
}

【问题讨论】:

  • 不,这是不可能的,但你可以用字符切换。将它们转换为 int 并根据 ASCII 码进行切换。

标签: c string switch-statement


【解决方案1】:

不,这是不可能的。

引用C11,第 6.8.4.2 章

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

【讨论】:

    【解决方案2】:

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

    if (strlen(c)==1)
    {
      switch(c[0]){
    
        case '+': printf(a+b);
                  break;
        ...
      }
    }
    

    当字符串有多个字符时,best way to switch on a string in C 中描述了一些不错的其他替代方案。

    【讨论】:

    • 我相信你知道这一点,但在 C 中,'+' 是 int 类型。
    • " 在 C 中,字符文字被视为 int 类型,而在 C++ 中,字符文字被视为 char 类型”但我不知道这种区别,只是查了一下。很高兴知道。谁说 C++ 是 C 的子集?
    【解决方案3】:

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

    但是 int 像 '+' 这样的字面量满足这个要求。 (enum 的值也是如此。)

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

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

    【讨论】:

      【解决方案4】:

      答案有两种情况..

      首先6.8.4.2(switch案例)

      switch 语句的控制表达式应为整数 输入

      其次是6.8.4.2(case 语句)

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

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

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

      【讨论】:

        【解决方案5】:

        不,你不能。 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;
        }
        

        【讨论】:

        • 是的!我已经试过了,它的工作!但这只是做这些事情的方法吗??
        • @RuchiM.Mewada:还有其他人,但他们正在与语言进行不必要的斗争。这是迄今为止最好的方法:虽然我更喜欢!strcmp 而不是strcmp == 0。不过仍然得到了支持。
        • 不过,与交换机相比,这里的性能可能会成为问题。至少它对每个值的执行不相等。
        • @alk: 是的,对于我上面提到的相同代码...如果是 if(!(strcmp(c == "*"))...它给了我 123 的 pf (%s,c) 而不是 * ...任何人都可以解释一下吗?这是将 * 作为算术多操作还是取消引用操作??
        【解决方案6】:

        不直接。但是,是的,你可以。

        #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?" );
          }
        }
        

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

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

        【讨论】:

        • 感谢你们所有人!我理解并修复它! tq
        【解决方案7】:

        正如其他人在 C 中指出的那样,不能将字符串用作开关的参数,也不能用作其大小写标签。

        要绕过这个限制,可以将每个字符串映射到一个特定的整数并将其传递给开关。

        查找映射需要搜索映射,这可以使用标准 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. */
        }
        

        【讨论】:

          猜你喜欢
          • 2012-10-24
          • 2012-03-03
          • 2011-08-03
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2022-06-22
          • 1970-01-01
          • 2015-11-07
          相关资源
          最近更新 更多