如何正确比较 C 中的字符串?
Posted
技术标签:
【中文标题】如何正确比较 C 中的字符串?【英文标题】:How do I properly compare strings in C? 【发布时间】:2021-09-03 21:56:44 【问题描述】:我试图让一个程序让用户输入一个单词或字符,存储它,然后打印它,直到用户再次输入它,退出程序。我的代码如下所示:
#include <stdio.h>
int main()
char input[40];
char check[40];
int i=0;
printf("Hello!\nPlease enter a word or character:\n");
gets(input); /* obsolete function: do not use!! */
printf("I will now repeat this until you type it back to me.\n");
while (check != input)
printf("%s\n", input);
gets(check); /* obsolete function: do not use!! */
printf("Good bye!");
return 0;
问题是我不断打印输入字符串,即使用户的输入(检查)与原始(输入)匹配。我是否错误地比较了两者?
【问题讨论】:
gets( )
已从标准中删除。请改用fgets( )
。
请注意,answer 到 Why does strcmp()
return zero when its inputs are equal 解释了如何比较字符串的相等、不相等、小于、大于、小于或等于以及大于或等于。并非所有字符串比较都是为了相等。区分大小写的比较再次不同;其他特殊比较(例如字典顺序)需要更专业的比较器,并且有用于更复杂比较的正则表达式。
还要注意,有一个基本重复的问题How do I check if a value matches a string 在此之前几年就被问过了。
这能回答你的问题吗? How do I check if a value matches a string
这个问题很好,但是使用gets()
是不行的。自 C11 起,它也已从标准中删除 -> 请阅读Why is the gets function so dangerous that it should not be used?
【参考方案1】:
您不能(有用地)使用!=
或==
比较字符串,您需要使用strcmp
:
while (strcmp(check,input) != 0)
这是因为!=
和==
只会比较这些字符串的基地址。不是字符串本身的内容。
【讨论】:
java中也一样,可能只是和地址比较。 写while (strcmp(check, input))
就足够了,被认为是好的做法。
了解更多...codificare.in/codes/c/…
使用strncmp更安全!不希望缓冲区溢出!
@craigB 很抱歉打破你的泡沫,但strcmp()
说"abcde"
大于"abc"
,不等于它。【参考方案2】:
好的一些事情:gets
is unsafe,应该替换为fgets(input, sizeof(input), stdin)
,这样你就不会出现缓冲区溢出。
接下来,要比较字符串,您必须使用strcmp
,其中返回值 0 表示两个字符串匹配。使用相等运算符(即!=
)比较两个字符串的地址,而不是其中的单个char
s。
还要注意,虽然在本例中不会引起问题,但fgets
将换行符、'\n'
也存储在缓冲区中; gets()
没有。如果您将来自fgets()
的用户输入与"abc"
等字符串文字进行比较,它将永远不会匹配(除非缓冲区太小以至于'\n'
无法放入其中)。
【讨论】:
你能澄清一下“\n”和字符串文字的关系/问题吗?在将文件的字符串(行)与其他整个文件进行比较时,我得到的结果不相等。 @incompetent — 如果您从带有fgets()
的文件中读取一行,那么字符串可能是"abc\n"
,因为fgets()
保留换行符。如果将其与"abc"
进行比较,您将得到“不等于”,因为以"abc"
结尾的空字节与读取数据中的换行符之间存在差异。因此,您必须删除换行符。可靠的单行方法是buffer[strcspn(buffer, "\n")] = '\0';
,它的优点是无论缓冲区中是否有任何数据,或者该数据是否以换行符结尾,都能正常工作。换行的其他方式很容易崩溃。
此答案准确地解决了代码问题,而最受好评和接受的答案仅涵盖回答问题的标题。尤其要提最后一段超级棒。 +1【参考方案3】:
使用strcmp
。
这是在string.h
库中,非常受欢迎。 strcmp
如果字符串相等则返回 0。请参阅 this 以更好地解释 strcmp
返回的内容。
基本上,你必须这样做:
while (strcmp(check,input) != 0)
或
while (!strcmp(check,input))
或
while (strcmp(check,input))
您可以查看this,strcmp
上的教程。
【讨论】:
【参考方案4】:你不能像这样直接比较数组
array1==array2
您应该逐个字符地比较它们;为此,您可以使用一个函数并返回一个布尔 (True:1, False:0) 值。然后就可以在while循环的测试条件中使用了。
试试这个:
#include <stdio.h>
int checker(char input[],char check[]);
int main()
char input[40];
char check[40];
int i=0;
printf("Hello!\nPlease enter a word or character:\n");
scanf("%s",input);
printf("I will now repeat this until you type it back to me.\n");
scanf("%s",check);
while (!checker(input,check))
printf("%s\n", input);
scanf("%s",check);
printf("Good bye!");
return 0;
int checker(char input[],char check[])
int i,result=1;
for(i=0; input[i]!='\0' || check[i]!='\0'; i++)
if(input[i] != check[i])
result=0;
break;
return result;
【讨论】:
能否请您添加有关您的解决方案的更多详细信息? 是的,这是 strcmp 函数和 solition 的替代品,不使用 string.h 标头 @Jongware 这不起作用。当checker
在其中一个字符串中找到'\0'
时,它不会检查另一个字符串中的'\0'
。即使一个字符串只是另一个字符串的前缀(例如,"foo"
和 "foobar"
),该函数也会返回 1
("equal")。
我会使用||
而不是&&
。【参考方案5】:
当您尝试比较字符串时,请根据每个字符比较它们。为此,您可以使用名为 strcmp(input1,input2); 的内置字符串函数。你应该使用名为#include<string.h>
的头文件
试试这个代码:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int main()
char s[]="***";
char s1[200];
printf("Enter the string to be checked\n");//enter the input string
scanf("%s",s1);
if(strcmp(s,s1)==0)//compare both the strings
printf("Both the Strings match\n");
else
printf("Entered String does not match\n");
system("pause");
【讨论】:
【参考方案6】:欢迎来到指针的概念。 一代又一代的初级程序员发现这个概念难以捉摸,但是如果你想成长为一个称职的程序员,你最终必须掌握这个概念——而且,你已经在问正确的问题。这很好。
你清楚地址是什么吗?看这张图:
---------- ----------
| 0x4000 | | 0x4004 |
| 1 | | 7 |
---------- ----------
在图中,整数 1 存储在内存中的地址 0x4000。为什么在一个地址?因为内存很大,可以存储很多整数,就像一个城市很大,可以容纳很多家庭一样。每个整数都存储在一个内存位置,因为每个家庭都住在一个房子里。每个内存位置都由一个地址标识,就像每个房子都由一个地址标识一样。
图中的两个框代表两个不同的内存位置。你可以把它们想象成房子。整数 1 位于地址 0x4000 的内存位置(想想“4000 Elm St.”)。整数 7 位于地址 0x4004 的内存位置(想想“4004 Elm St.”)。
您认为您的程序将 1 与 7 进行比较,但事实并非如此。它正在比较 0x4000 和 0x4004。那么当你遇到这种情况时会发生什么?
---------- ----------
| 0x4000 | | 0x4004 |
| 1 | | 1 |
---------- ----------
这两个整数相同,但地址不同。您的程序会比较地址。
【讨论】:
【参考方案7】:你需要使用strcmp()
,你需要#include <string.h>
!=
和 ==
运算符仅比较这些字符串的基地址。不是字符串的内容
while (strcmp(check, input))
示例代码:
#include <stdio.h>
#include <string.h>
int main()
char input[40];
char check[40] = "end\n"; //dont forget to check for \n
while ( strcmp(check, input) ) //strcmp returns 0 if equal
printf("Please enter a name: \n");
fgets(input, sizeof(input), stdin);
printf("My name is: %s\n", input);
printf("Good bye!");
return 0;
注意1:gets()
不安全。请改用fgets()
注意2:使用fgets()
时,你也需要检查'\n'
换行符
【讨论】:
【参考方案8】:你可以:
使用string.h
中的strcmp()
,这是更简单的版本
或者如果你想自己滚动,你可以使用这样的东西:
int strcmp(char *s1, char *s2)
int i;
while(s1[i] != '\0' && s2[i] != '\0')
if(s1[i] != s2[i])
return 1;
i++;
return 0;
我会以这样的方式使用strcmp()
:
while(strcmp(check, input))
// code here
【讨论】:
您可能打算在 strcmp 函数的末尾添加一个return 0;
不需要,但是,这是一个很好的做法【参考方案9】:
如何正确比较字符串?
char input[40];
char check[40];
strcpy(input, "Hello"); // input assigned somehow
strcpy(check, "Hello"); // check assigned somehow
// insufficient
while (check != input)
// good
while (strcmp(check, input) != 0)
// or
while (strcmp(check, input))
让我们更深入地了解为什么check != input
还不够。
在 C 中,string 是标准库规范。
上面的字符串 是一个连续的字符序列,以第一个空字符终止并包括第一个空字符。 C11 §7.1.1 1
input
不是字符串。 input
是 array 40 of char。
input
的内容可以变成字符串。
在大多数情况下,当在表达式中使用数组时,它会被转换为其第一个元素的地址。
下面将check
和input
转换为它们各自的第一个元素的地址,然后比较这些地址。
check != input // Compare addresses, not the contents of what addresses reference
要比较字符串,我们需要使用这些地址,然后查看它们指向的数据。strcmp()
完成这项工作。 §7.23.4.2
int strcmp(const char *s1, const char *s2);
strcmp
函数将s1
指向的字符串与s2
指向的字符串进行比较。
strcmp
函数返回一个大于、等于或小于零的整数, 因此,s1
指向的字符串大于、等于或小于s2
指向的字符串。
代码不仅可以找出字符串是否属于相同的数据,而且当它们不同时,哪个更大/更少。
当字符串不同时,以下情况为真。
strcmp(check, input) != 0
如需深入了解,请参阅Creating my own strcmp()
function
【讨论】:
【参考方案10】: #include<stdio.h>
#include<string.h>
int main()
char s1[50],s2[50];
printf("Enter the character of strings: ");
gets(s1);
printf("\nEnter different character of string to repeat: \n");
while(strcmp(s1,s2))
printf("%s\n",s1);
gets(s2);
return 0;
这是一个非常简单的解决方案,您可以根据需要获得输出。
【讨论】:
gets();
自 C11 起不再是标准 C 的一部分。
strcmp(s1,s2)
是 UB,因为 s2
最初没有指定内容。
如果你也能以某种形式提供这个 sn-p 的输出,那就太好了。以上是关于如何正确比较 C 中的字符串?的主要内容,如果未能解决你的问题,请参考以下文章