256

我正在尝试让一个程序让用户输入一个单词或字符,存储它,然后打印它,直到用户再次键入它,退出程序。我的代码如下所示:

#包括<stdio.h>整型main(){字符输入[40];字符检查[40];整数i=0;printf(“Hello!\n请输入单词或字符:\n”);获取(输入);/*过时的功能:不要使用*/printf(“我现在将重复此操作,直到您将其键入给我。”);while(检查!=输入){printf(“%s\n”,输入);获取(检查);/*过时的功能:不要使用*/}printf(“再见!”);返回0;}

问题是我一直在打印输入字符串,即使用户输入(检查)与原件匹配(输入). 我是不是把两者比较错了?

5

11答案11

重置为默认值
376

您不能(有用地)使用!===,您需要使用字符串比较函数:

while(strcmp(检查,输入)!=0)

这是因为!===将只比较这些字符串的基址。不是字符串本身的内容。

6
  • 12
    java中也是如此,只需与地址进行比较即可。 评论 2014年9月6日16:29
  • 44
    写作while(strcmp(检查,输入))足够了,被认为是良好的做法。
    – 什拉文
    评论 2015年6月28日15:53
  • 10
    使用strncmp更安全!不要缓冲区溢出!
    – 弗洛姆
    评论 2017年11月10日18:36
  • 1
    @弗洛姆如果你实际上没有字符串,但有已知长度的非零字符的零填充序列,那当然是正确的咒语。但这完全不同! 评论 2019年2月1日21:18
  • 1
    @AD贝弗里奇buffer[strlen(buffer)-1]='\0';并不总是有效,实际上是危险的。fgets()并不总是返回以换行结尾的字符串,因此代码可以删除有效数据;事实上fgets()可以返回零长度的字符串,这意味着buffer[strlen(buffer)-1]=“\0”;将在数组边界外写入并调用未定义的行为。请参见从fgets()输入中删除尾随换行符 评论 2023年3月16日9:40
45

好的,有几件事:得到不安全并应替换为fgets(输入,sizeof(输入),标准输入)这样就不会发生缓冲区溢出。

接下来,要比较字符串,必须使用字符串比较函数,其中返回值0表示两个字符串匹配。使用相等运算符(即。!=)将两个字符串的地址与单个字符串的地址进行比较烧焦就在里面。

还要注意,虽然在本例中它不会引起问题,fgets公司存储换行符,“\n”缓冲器中也有;获取()没有。如果您比较来自的用户输入fgets()到字符串文本,例如“abc”它永远不会匹配(除非缓冲区太小“\n”不适合它)。

  • 您能澄清“\n”和字符串文字的关系/问题吗?我在比较一个文件的字符串(行)和其他整个文件时得到了不同的结果。
    – 无能的
    评论 2019年7月17日16:32
  • 1
    @不称职-如果你用fgets(),那么字符串可能是“abc\n”因为fgets()保持换行。如果你将其与“abc”,您将得到“不相等”,因为空字节终止之间存在差异“abc”和读取数据中的换行符。所以,你必须快速换行。可靠的单线方法是buffer[strcspn(buffer,“\n”)]=“\0”;它的优点是无论缓冲区中是否有任何数据,或者该数据是否以换行结束,都能正常工作。其他击倒新线的方式很容易崩溃。 评论 2020年1月16日3:39
  • 这个答案准确地解决了代码的问题,而投票最多和被接受的答案只回答了问题的标题。特别是提到最后一段是很好的+1 评论 2020年5月30日9:49
19

使用字符串比较函数.

这是在字符串。小时图书馆,很受欢迎。字符串比较函数如果字符串相等,则返回0。请参见为了更好地解释什么字符串比较函数返回。

基本上,你必须做到:

while(strcmp(检查,输入)!=0)

while(!strcmp(检查,输入))

while(strcmp(检查,输入))

你可以检查,关于的教程字符串比较函数.

0
12

不能像这样直接比较数组

数组1==数组2

你应该逐个字符比较它们;为此,可以使用函数并返回布尔值(True:1,False:0)。然后可以在while循环的测试条件中使用它。

试试这个:

#包括<stdio.h>int检查器(char input[],char check[]);整型main(){字符输入[40];字符检查[40];整数i=0;printf(“Hello!\n请输入单词或字符:\n”);扫描(“%s”,输入);printf(“我现在将重复此操作,直到您将其键入给我。”);扫描(“%s”,检查);while(!checker(输入,检查)){printf(“%s\n”,输入);扫描(“%s”,检查);}printf(“再见!”);返回0;}int checker(字符输入[],字符检查[]){整数i,结果=1;for(i=0;输入[i]!='\0'||检查[i];='\0';i++){if(输入[i]!=检查[i]){结果=0;断裂;}}返回结果;}
4
  • 1
    能否请您添加有关解决方案的更多详细信息? 评论 2015年4月6日9:48
  • 是的,这是在不使用string.hheader@Jongware的情况下替代strcmp函数和孤立 评论 2015年4月6日10:02
  • 这不起作用。何时检查器发现'\0'在其中一个字符串中,它不检查另一个字符串'\0'。函数返回1(“相等”),即使一个字符串只是另一个字符串的前缀(例如,“foo”“foobar”). 评论 2017年10月6日14:16
  • 2
    我会用||而不是&&. 评论 2017年10月6日14:28
11

欢迎学习指针。一代又一代的初学者都发现这个概念难以捉摸,但如果你想成为一名称职的程序员,你最终必须掌握这个概念——而且,你已经在问正确的问题了。那很好。

你清楚地址是什么吗?见下图:

----------     ----------|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(input1,input2);并且应该使用名为#包括<string.h>

尝试此代码:

#包括<stdio.h>#包括<stdlib.h>#包括<string.h>整型main(){ char s[]=“STACKOVERFLOW”;字符s1[200];printf(“输入要检查的字符串\n”)//输入输入字符串扫描(“%s”,s1);if(strcmp(s,s1)==0)//比较两个字符串{printf(“两个字符串都匹配\n”);} 其他的{printf(“输入的字符串不匹配\n”);} 系统(“暂停”);}
0
4

你可以:

使用strcmp()字符串。小时,哪个版本更容易

或者,如果你想自己滚,你可以这样使用:

int strcmp(常量字符*s1,常量字符*s2){对于(i=0;s1[i]!='\0'|s2[i];='\0';i++){如果(s1[i]!=s2[i]){return(unsigned char)s1[i]<(unsinged char)s2[i]-1 : 1;}}返回0;}

我会用strcmp()以这样的方式:

while(strcmp(检查,输入)){//此处输入代码}
  • 你可能是想把返回0;在strcmp函数的末尾
    – 哈里森
    评论 2021年7月19日22:50
  • 不需要,但是的,这是一个很好的实践
    – 动漫17
    评论 2021年7月20日15:19
  • 我冒昧地修复了您的字符串比较函数功能。它必须根据不同字符串参数的字典顺序返回负值或正值,而您忘记了初始化0:a对于循环比虽然循环。此外,如果其中一个字符串是另一个字符串的前缀,则代码返回0。决赛返回是必需的,否则函数将对相同字符串具有未定义的行为。
    – 切克利
    评论 2023年8月10日20:53

如何正确比较字符串?

字符输入[40];字符检查[40];strcpy(输入,“Hello”);//以某种方式分配的输入strcpy(勾选,“Hello”);//以某种方式分配支票//不足while(检查!=输入)//很好while(strcmp(检查,输入)!=0)//或while(strcmp(检查,输入))

让我们深入挖掘看看为什么?检查!=输入还不够.

在C中,一串是标准的库规范。

A类一串是以第一个空字符结尾并包含该空字符的连续字符序列。
C11第7.1.1条1

输入上面不是一串.输入char的数组40.

的内容输入可以成为一串.

在大多数情况下,当在表达式中使用数组时,它被转换为其第一个元素的地址。

以下转换检查输入与第一个元素的各自地址进行比较。

检查!=输入//比较地址,而不是地址引用的内容

要进行比较,我们需要使用这些地址,然后查看它们指向的数据。
strcmp()做这份工作. §7.23.4.2

int strcmp(常量字符*s1,常量字符*s2);

这个字符串比较函数函数比较指向的字符串第1页指向指向的字符串s2秒.

这个字符串比较函数函数返回一个大于、等于或小于零的整数,相应地,作为所指向的字符串s1大于、等于或小于s2秒.

代码不仅可以发现字符串是否属于相同的数据,还可以发现当它们不同时,哪个更大/更少。

当字符串不同时,以下是正确的。

strcmp(检查,输入)!=0

有关详细信息,请参见创建我自己的strcmp()功能

你需要使用strcmp()你需要#包括<string.h>

这个!===运算符只比较这些字符串的基址。不是字符串的内容

while(strcmp(检查,输入))

示例代码:

#包括<stdio.h>#包括<string.h>整型main(){字符输入[40];char check[40]=“end\n”//不要忘记检查\nwhile(strcmp(check,input))//strcmp如果相等则返回0{printf(“请输入名称:\n”);fgets(输入,sizeof(输入),标准输入);printf(“我的名字是:%s\n”,输入);}printf(“再见!”);返回0;}

注1:获取()不安全。使用fgets()相反

注2:使用时fgets()你需要检查一下“\n”也有新线字符

-2
#包括<stdio.h>#包括<string.h>整型main(){字符s1[50],s2[50];printf(“输入字符串的字符:”);获得(s1);printf(“\n输入要重复的字符串的不同字符:\n”);while(strcmp(s1,s2)){printf(“%s\n”,s1);获得(s2);}返回0;}

这是一个非常简单的解决方案,您可以根据需要获得输出。

  • 获取();自C11以来,不属于标准C的一部分。 评论 2019年1月10日15:11
  • strcmp(s1,s2)UB是s2秒首先未指定内容。 评论 2019年1月10日15:12
  • 如果您也能以某种形式提供此代码段的输出,那就太棒了。
    – 非2qubit
    评论 2019年7月10日12:05
-2

我刚开始编码,并开始在youtube上观看cs50视频。我遇到了一个问题,即无法使用“==”比较两个字符串。所以我尝试了一下:

#包括<iostream>使用命名空间标准;整型main(){字符串str[]={“汤姆”,“克里斯”};if(str[0]==“tom”){返回0;}返回1;}

由于某些原因,程序工作并返回0。视频和这里的帖子都不这么说。

1
  • 4
    由于数组的第一个元素和字符串文字“汤姆”在比较中,恰好是相同的以null结尾的全局数组烧焦。这很常见,但C标准不保证。此外,这种比较对任何其他字符串都不起作用。不要依赖这种巧合和使用strcmp().
    – 切克利
    评论 2023年8月10日11:12

不是你想要的答案吗?浏览标记的其他问题问你自己的问题.