如何检查一个值是否与一个字符串匹配

5

我这里有一个结构体,类似于:

char *sname;
........
players[i].sname

需要检查各个数值是否相等,比如:

equalling "James"。

if (players[i].sname == 'Lee')

但我没有太好的运气。是否有一个str*函数可以使用,或者有没有办法修复我的if语句?


3
请注意,您需要使用双引号字符串而不是单引号多字符常量。 - Jonathan Leffler
是的 - 我想我会留下它,让其他人学习。 - Dominic Bou-Samra
请注意,这个问题的几乎重复版本是如何在C中正确比较字符串,是在多年之后提出的。还有一个问题是为什么strcmp()在输入相等时返回0 - Jonathan Leffler
4个回答

12

简短回答:strcmp()

长话短说:你有这个问题:

if(players[i].sname == 'Lee')

这段代码有几个问题。首先,在C中,单引号表示"字符字面量"而不是"字符串字面量"。

其次,更重要的是,"string1" == "string2"并不能比较字符串,它比较的是char *,或者说字符指针。它会告诉你两个字符串是否存储在相同的内存位置上。这意味着它们相等,但假结果并不意味着它们不相等。

strcmp()会基本上遍历并比较字符串中的每个字符,停在第一个不相等的字符处,并返回两个字符之间的差异(这就是为什么你必须用strcmp() == 0!strcmp()来判断相等性)。

还要注意函数strncmp()memcmp(),它们类似于strcmp()但更安全。


非常感谢 - 我知道有些根本性的错误。当你不知道哪一部分是错的,而有很多部分时,实际上很难查找 :P - Dominic Bou-Samra

11

你应该使用strcmp()函数:

if (strcmp(players[i].sname, "Lee") == 0) { ...

另外请注意,C语言中的字符串用双引号""括起来,单个字符则使用单引号''。我不确定你的编译器对'Lee'做了什么处理,但几乎肯定不是你想要的。


编译器可能会生成数字0x004c6565。我不确定在C89中是否允许使用多字节字符,但我相信它们是C99的一部分。 - Chris Lutz
多字符整数常量在C89及其后版本中是合法的,但它们的值是实现定义的。ISO/IEC 9899:2011 §6.4.4.4字符常量:_¶10 …包含多个字符(例如'ab')或包含不映射到单字节执行字符的字符或转义序列的整数字符常量的值是实现定义的。…_措辞在C89中基本上是等效的。(有趣的是,C89在最初的描述中有一个'ab'的例子;C99和C11都删除了多字符常量的早期示例。) - Jonathan Leffler

4
你需要在头文件<string.h>中使用strcmp()函数。
请注意,你需要一个字符串——'Lee'不是一个字符串,而是一个多字符常量,虽然编译器允许这样做,但很少有用,至少因为其表示由编译器定义,而非C标准。
如果你想比较两个字符串——把它们的指针称为firstsecond,那么你可以写:
```c strcmp(first, second) ```
if (strcmp(first, second) == 0)    // first equal to second
if (strcmp(first, second) <= 0)    // first less than or equal to second
if (strcmp(first, second) <  0)    // first less than second
if (strcmp(first, second) >= 0)    // first greater than or equal to second
if (strcmp(first, second) >  0)    // first greater than second
if (strcmp(first, second) != 0)    // first unequal to second

在我看来,这使得比较清晰明了,因此应该使用这种符号。请注意,strcmp()可能返回任何负值表示“小于”,或任何正值表示“大于”。

你会发现有些人更喜欢:

if (strcmp(first, second))    // first unequal to second
if (!strcmp(first, second))   // first equal to second

我认为,使用缩写虽然简洁,但与明确的零比较相比不够清晰。请注意,使用strncmp()而不是建议中的strcmp()需要谨慎。如果您有:

YMMV

if (strncmp(first, "command", 7) == 0)

如果first包含"commander",则匹配将有效。如果这不是你想要的,但你仍然想使用strncmp(),你可以写成:

if (strncmp(first, "command", sizeof("command")) == 0)

这将正确拒绝"commander"


0

strcmp函数很好用,只要其中一个字符串以null结尾。如果两个字符串都是最大长度且相同,则比较将会超出范围,并且很可能会在等式测试中给出错误的负面结果。如果一个字符串在strcmp本身内部被""标记固定,那么这不是问题,因为我们知道它是以null结尾的。

如果我们正在比较两个字符串变量,并且我们不知道它们是否达到了最大长度(最大长度的字符串没有以null结尾),那么我们需要使用strncmp,并在其中使用sizeof来获取第三个参数。这解决了问题,因为sizeof知道最大长度。如果其中一个字符串是双引号中的文字,则strcmp是100%安全的。


所有字符串都是以空字符结尾的。如果一个字符序列没有以空字符结尾,那么它就不是C字符串! - Toby Speight
字符串字面量始终以 null 结尾。字符数组则不能保证如此,如果你将一个 strcpy 处理过的字符串拷贝进去,它往往会以 null 结尾。但也有例外。如果你有一个 char[20] 数组,试图往里面放一个 20 个字符的字符串,那么 null 终止符会位于数组外部或不存在。你仍然可以使用这个数组,因为最大值是已知的。但是在这种情况下做 strcpy 的话可要小心了。 - Mr. Beeblebrox

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接