C语言 在数组上使用字符串的 switch 语句
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/17984628/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Switch statement using string on an array
提问by PNC
#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();
}
It seems it will not work. Is this possible? I mean is there any way we can make a switch statement of a string. How to solve the problem, actually?
看来是行不通了。这可能吗?我的意思是有什么办法可以让一个字符串的 switch 语句。如何解决问题,实际上?
回答by Tris Healy
Switch statements in C aren't smart like one's found in other languages (such as Java 7 or Go) you cannot switch on a string (Nor can you compare strings with ==). Switch can only operate on integral types (int, char, etc).
C 中的 switch 语句不像其他语言(例如 Java 7 或 Go)中的那样智能,您不能在字符串上切换(也不能将字符串与 进行比较==)。交换机只能在整数类型(操作int,char等等)。
In your code you call switch with: switch(name[20]). That means switch(*(name + 20)). In other words switch on the 21st charin name (because name[0]is the first). As nameonly has 20 chars you are accessing whatever memory is after name. (which could do unpredictable things)
在你的代码调用交换机:switch(name[20])。这意味着switch(*(name + 20))。换句话说,char在名称中打开第 21 个(因为name[0]是第一个)。由于name只有 20 个字符,因此您正在访问名称后的任何内存。(这可能会做不可预测的事情)
Also the string "kevin"is compiled to a char[N](where Nis strlen("kevin") + 1) which contains the string. When you do case "kevin". It will only work if name is in the exact same piece of memory storing the string. So even if I copied kevininto name. It still would not match as it is stored in a different piece of memory.
字符串也"kevin"被编译为包含字符串的char[N](where Nis strlen("kevin") + 1)。当你这样做时case "kevin"。仅当 name 位于存储字符串的完全相同的内存中时,它才会起作用。所以即使我复制kevin到名称中。它仍然不会匹配,因为它存储在不同的内存中。
To do what you seem to be trying you would do this:
要做您似乎正在尝试的事情,您可以这样做:
#include <string.h>
...
if (strcmp(name, "kevin") == 0) {
...
}
String compare (strcmp) returns different values based on the difference in the strings. Eg:
String compare ( 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");
Side note: Dont use scanf("%s", name)in that form. It creates a common security problemuse fgetslike this: (there is a safe way to use scanftoo)
旁注:不要scanf("%s", name)以那种形式使用。它创建了一个共同的安全问题,使用fgets这样的:(有使用安全的方式scanf太)
#define MAX_LEN 20
int main() {
name[MAX_LEN];
fgets(name, MAX_LEN, stdin);
...
回答by chux - Reinstate Monica
Switch statements work on intvalues (or enum), but not on chararrays.
Switch 语句适用于int值(或enum),但不适用于char数组。
You could do
你可以做
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!");
}
回答by quasinymous
There are plenty of ways to go about this! For example, use a...
有很多方法可以解决这个问题!例如,使用一个...
3-letter hash
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));
}
回答by Jeyaram
Remember the rules while using switchstatements.
使用switch语句时请记住规则。
Switch constraints
开关约束
1.The controlling expression of a switch statement must have "integer type".
1.switch 语句的控制表达式必须具有“整数类型”。
2.The expression of each case label shall be an integer constant expression and no two of the case constant expressions in the same switch statement shall have the same value after conversion. There may be at most one default label in a switch statement.
2、每个case标签的表达式必须是整数常量表达式,并且同一个switch语句中的两个case常量表达式转换后的值不能相同。switch 语句中最多可能有一个默认标签。
3.Any enclosed switch statement may have a default label or case constant expressions with values that duplicate case constant expressions in the enclosing switch statement.
3.任何封闭的 switch 语句都可能有一个默认标签或 case 常量表达式,其值与封闭的 switch 语句中的 case 常量表达式重复。
回答by Eric Urban
No, you cannot use the switchstatement in C with the value of a string or character array. The closest alternative is to use some sort of data structure mapping strings to function pointers. The function pointer could be called after a string is used to look it up.
不,您不能将switchC 中的语句与字符串或字符数组的值一起使用。最接近的替代方法是使用某种数据结构映射字符串到函数指针。可以在使用字符串查找后调用函数指针。
回答by JULIE JOHN
since the name is declared as a char type ,it would be better if you use "%c"instead of using "%s"inside the scanf()method.
由于名称被声明为字符类型,如果您在方法内部使用"%c"而不是使用会更好。"%s"scanf()
回答by CyberSpy_zero
You can use "hash-string.h" library that converts strings into hash code integer. Create a header file and paste this code: http://www.opensource.apple.com/source/gcc/gcc-5484/intl/hash-string.h
您可以使用“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;
}
回答by alk
If you are after performing specific actions for specific strings this implies you know the strings in advance. This in turn implies their number is limited, is countable, like for example a set of N commands:
如果您在对特定字符串执行特定操作之后,这意味着您事先知道这些字符串。这反过来意味着它们的数量是有限的,是可数的,例如一组 N 个命令:
const char * commands[] = {
"command-1",
"command-2",
...
"command-N"
}
}
To address those commands inside the array above from your code using a swtich you need to know their index, which is error prone. So number them, give them an ID:
要使用 swtich 从您的代码中处理上面数组中的那些命令,您需要知道它们的索引,这很容易出错。所以给他们编号,给他们一个ID:
enum Command_id {
NO_COMMAND,
COMMAND_1,
COMMAND_2,
//...
COMMAND_N,
};
Now put the two above together using a struct:
现在使用结构将上面的两个放在一起:
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},
};
Now you have nice mapping of strings and their related IDs. To be able to map from string to ID during runtime the mapping above needs to be searched. To do this in a efficient manner you want to us binary search. The C library proveids bsearch()for this. The only prerequsite is that the array to be searched need to sorted.
现在您有了很好的字符串及其相关 ID 的映射。为了能够在运行时从字符串映射到 ID,需要搜索上面的映射。要以有效的方式执行此操作,您需要我们进行二分搜索。C 库为此bsearch()提供了证明。唯一的先决条件是要搜索的数组需要排序。
To sort use qsort()also proveid by the C library. For qsort()to work we you need a comparsion function:
排序使用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);
}
Call qsort()like this
qsort()像这样打电话
qsort(command_infos, sizeof command_infos / sizeof *command_infos, sizeof *command_infos, cmp_command_infos);
Now as the array is sorted one can look it up using bsearch(). For "COMMAND-2" this would look like this:
现在当数组被排序时,可以使用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);
Putting all this together could result in:
将所有这些放在一起可能会导致:
#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;
}
}
}
}
Call it like:
像这样称呼它:
./a.out command-1
giving:
给予:
Command = 'command-1' --> ID = 1
or:
或者:
./a.out command-bla
giving:
给予:
Command = 'command-bla' is unknown
or even
甚至
./a.out ""
giving:
给予:
Command = '' --> ID = 0

