[英]Switch statement using string on an array
#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 语句。 如何解决问题,实际上?
C 中的 switch 语句不像在其他语言(例如 Java 7 或 Go)中发现的那样智能,您不能在字符串上切换(也不能将字符串与==
进行比较)。 Switch 只能对整数类型( int
、 char
等)进行操作。
在您的代码中,您使用以下命令调用 switch: switch(name[20])
。 这意味着switch(*(name + 20))
。 换句话说,打开 name 中的第 21 个char
(因为name[0]
是第一个)。 由于name
只有 20 个字符,因此您正在访问名称后的任何内存。 (这可能会做不可预测的事情)
此外,字符串"kevin"
被编译为包含字符串的char[N]
(其中N
是strlen("kevin") + 1
)。 当你做case "kevin"
。 仅当 name 位于存储字符串的完全相同的内存中时,它才会起作用。 因此,即使我将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)
。 它创建了一个常见的安全问题,使用fgets
是这样的:(也有一种使用scanf
的安全方法)
#define MAX_LEN 20
int main() {
char name[MAX_LEN];
fgets(name, MAX_LEN, stdin);
...
Switch 语句适用于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!");
}
有很多方法可以解决这个问题! 例如,使用一个...
#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));
}
不,您不能将 C 中的switch
语句与字符串或字符数组的值一起使用。 最接近的替代方法是使用某种数据结构映射字符串到函数指针。 可以在使用字符串查找后调用函数指针。
记住使用switch
语句时的规则。
开关约束
1. switch 语句的控制表达式必须具有“整数类型”。
2 、每个case标签的表达式必须是整数常量表达式,并且同一个switch语句中的两个case常量表达式转换后的值不能相同。 switch 语句中最多可能有一个默认标签。
3.任何封闭的 switch 语句都可能有一个默认标签或 case 常量表达式,其值与封闭的 switch 语句中的 case 常量表达式重复。
由于名称被声明为字符类型,如果在scanf()
方法中使用"%c"
而不是使用"%s"
会更好。
您可以使用“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;
}
如果您在对特定字符串执行特定操作之后,这意味着您事先知道这些字符串。 这反过来意味着它们的数量是有限的,是可数的,例如一组 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()
。 唯一的先决条件是要搜索的数组需要排序。
排序使用qsort()
也由 C 库证明。 为了让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()
查找它。 对于“COMMAND-2”,它看起来像这样:
... = 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
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.