使用数组上的字符串切换语句

时间:2013-08-01 03:09:20

标签: c arrays string switch-statement

#include<stdio.h>

int main(){

    char name[20];

    printf("enter a name ");
    scanf("%s",name);
    switch(name[20]){
        case "kevin" : 
        printf("hello");
        break;
    }
    printf("%s",name);
    getch();
}

似乎无效。这可能吗?我的意思是我们有什么方法可以创建一个字符串的switch语句。实际上如何解决问题?

8 个答案:

答案 0 :(得分:8)

C语言中的切换语句不像其他语言(例如Java 7或Go)中的那样,不能打开字符串(也不能将字符串与==进行比较)。 Switch只能对整数类型(intchar等)进行操作。

在您的代码中,您使用以下代码调用开关:switch(name[20])。这意味着switch(*(name + 20))。换句话说,在名称中切换21 char(因为name[0]是第一个)。由于name只有20个字符,因此您可以访问名称后的内存。 (这可能做不可预测的事情)

此外,字符串"kevin"被编译为char[N](其中Nstrlen("kevin") + 1),其中包含字符串。当你case "kevin"时。它只有在名称与存储字符串的内存完全相同时才有效。即使我将kevin复制到名称中也是如此。它仍然不匹配,因为它存储在不同的内存中。

要做你似乎尝试的事情,你会这样做:

#include <string.h>
...
    if (strcmp(name, "kevin") == 0) {
        ...
    }

字符串比较(strcmp)根据字符串的不同返回不同的值。例如:

int ord = strcmp(str1, str2);
if (ord < 0)  
    printf("str1 is before str2 alphabetically\n");
else if (ord == 0) 
    printf("str1 is the same as str2\n");
else if (ord > 0)  
    printf("str1 is after str2 alphabetically\n");

旁注:请勿在该表单中使用scanf("%s", name)。它会像这样创建一个common security problem使用fgets :(有一种安全的方式来使用scanf

#define MAX_LEN 20
int main() { 
    name[MAX_LEN]; 
    fgets(name, MAX_LEN, stdin);
    ...

答案 1 :(得分:5)

切换语句适用于int值(或enum),但不适用于char数组。

你可以做到

if (strcmp(name, "kevin")==0) {
    printf("hello");
}
else if (strcmp(name, "Laura")==0) {
    printf("Allo");
}
else if (strcmp(name, "Mike")==0) {
    printf("Good day");
}
else  {
    printf("Help!");
}

答案 2 :(得分:2)

有很多方法可以解决这个问题!例如,使用...

3个字母的哈希

#include <stdio.h>

int main(){

    char name[20];

    printf("enter a name ");
    scanf("%s",name);
    switch((int)*name * (int)*(name+1) * (int)*(name+2)){
          case (1275226) : // "kevin"
            printf("hello %s.\n", name);
            break;
          case (1293980) : // "astro"
            printf("welcome %s.\n", name);
            break;
    }
    printf("%d",(int)*name * (int)*(name+1) * (int)*(name+2));
}

答案 3 :(得分:0)

不,您不能将C中的switch语句与字符串或字符数组的值一起使用。最接近的替代方法是使用某种数据结构映射字符串来实现指针。在使用字符串查找之后,可以调用函数指针。

答案 4 :(得分:0)

使用switch语句时请记住规则。

切换约束

1。 switch语句的控制表达式必须具有“整数类型”。

2. 每个案例标签的表达式应为整数常量表达式,而不是两个 同一switch语句中的case常量表达式应具有相同的值 转换后。在switch语句中最多可能有一个默认标签。

3. 任何封闭的switch语句都可能有一个默认的标签或大小写常量表达式,其值在封闭的switch语句中复制大小写常量表达式。

答案 5 :(得分:0)

因为名称被声明为char类型,所以如果您使用"%c"而不是"%s"方法中使用scanf()会更好。

答案 6 :(得分:0)

您可以使用“hash-string.h”库将字符串转换为哈希码整数。 创建头文件并粘贴此代码: http://www.opensource.apple.com/source/gcc/gcc-5484/intl/hash-string.h

#include <stdio.h>
#include <stdlib.h>
#include "hash-string.h"

int main(){

  char name[20];

  printf("Enter a name: ");
  scanf("%s",name);

  unsigned long nameInt = hash_string(name);

  switch(nameInt){
    case 7458046 /* "kevin" */: { printf("Hello %s", name); break; }
    default: { printf("You are not kevin"); }
  }

  printf("\n");
  return 0;
}

答案 7 :(得分:0)

如果您在对特定字符串执行特定操作后,这意味着您事先知道字符串。这反过来意味着它们的数量是有限的,是可数的,例如一组N个命令:

const char * commands[] = {
 "command-1",
 "command-2",
 ...
 "command-N"

}

要使用swtich从代码中解决上面数组中的那些命令,您需要知道它们的索引,这很容易出错。为他们编号,给他们一个ID:

enum Command_id {
  NO_COMMAND,
  COMMAND_1,
  COMMAND_2,
  //...
  COMMAND_N,
};

现在使用结构将上面两个放在一起:

struct Command_info {
  const char * command;
  enum Command_id id;
} command_infos[] = {
  {"", NO_COMMAND},
  {"command-1", COMMAND_1},
  {"command-2", COMMAND_2},
  // ...
  {"command-N", COMMAND_N},
};

现在您可以很好地映射字符串及其相关ID。为了能够在运行期间从字符串映射到ID,需要搜索上面的映射。要以有效的方式执行此操作,您需要我们二进制搜索。 C库证明bsearch()为此。唯一的先决条件是要搜索的数组需要排序。

要对C库使用qsort()进行排序。要使qsort()起作用,我们需要一个比较函数:

int cmp_command_infos(const void * pvCI1, const void* pvCI2)
{
  const struct Command_info * pCI1 = pvCI1;
  const struct Command_info * pCI2 = pvCI2;

  return strcmp(pCI1->command, pCI2->command);
}

像这样呼叫qsort()

qsort(command_infos, sizeof command_infos / sizeof *command_infos, sizeof *command_infos, cmp_command_infos);

现在,当数组已排序时,可以使用bsearch()查找它。对于&#34; COMMAND-2&#34;这看起来像这样:

    ... = bsearch(&(struct Command_info){"COMMAND-2", NO_COMMAND}, command_infos, sizeof command_infos / sizeof *command_infos, sizeof *command_infos, cmp_command_infos);

将所有这些放在一起可能会导致:

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


enum Command_id {
  NO_COMMAND,
  COMMAND_1,
  COMMAND_2,
  //...
  COMMAND_N,
};

struct Command_info {
  const char * command;
  enum Command_id id;
} command_infos[] = {
  {"", NO_COMMAND},
  {"command-1", COMMAND_1},
  {"command-2", COMMAND_2},
  // ...
  {"command-N", COMMAND_N},
};


int cmp_command_infos(const void * pvCI1, const void* pvCI2)
{
  const struct Command_info * pCI1 = pvCI1;
  const struct Command_info * pCI2 = pvCI2;

  return strcmp(pCI1->command, pCI2->command);
}


int main(int argc, char ** argv)
{
  qsort(command_infos, sizeof command_infos / sizeof *command_infos, sizeof *command_infos, cmp_command_infos);


  {
    enum Command_id command_id = NO_COMMAND;
    struct Command_info * pCI = bsearch(&(struct Command_info){argv[1], NO_COMMAND}, command_infos, sizeof command_infos / sizeof *command_infos, sizeof *command_infos, cmp_command_infos);

    if (NULL == pCI)
    {
      printf("Command = '%s' is unknown\n", argv[1]);
    }
    else
    {
      printf("Command = '%s' --> ID = %d\n", pCI->command, pCI->id);


      switch(command_id)
      {
        case COMMAND_1:
          /* perform action on COMMAND 1 here */
          break;

        case COMMAND_2:
          /* perform action on COMMAND 1 here */
          break;

        default:
          /* unknow command, do nothing */
          break;
      }
    }
  }
}

称之为:

./a.out command-1

,并提供:

Command = 'command-1' --> ID = 1

或:

./a.out command-bla

,并提供:

Command = 'command-bla' is unknown

甚至

./a.out ""

,并提供:

Command = '' --> ID = 0