我正在尝试检查两个字符串是否相等。下面是我的代码。我得到了错误的结果,并且我不知道自己在做错什么。
#include<stdio.h>
#include<cs50.h>
int main(void){
string a = get_string("ENTER YOUR NAME FOR READING\n");
if (a == "david")
;
{
printf("...");
}
}
您的代码有三个问题:
if (a == "david")
[a
衰减到指向数组a
的第一个元素的指针。
"david"
是字符串文字。
使用if
语句,您尝试将数组a
的地址与字符串文字"david"
的地址进行比较。字符串比较在C中无法正常工作。
使用strcmp()
-标头string.h
比较字符串。
strcmp()
如果字符串相等则返回0。要使if
条件变为true
,您需要使用!
求反运算符。
;
条件和if
主体之间的if
放错了位置。删除它。
不赞成使用cs50.h
。不要使用它。
#include <stdio.h>
#include <string.h>
int main (void) {
char a[20];
printf("ENTER YOUR NAME FOR READING:\n");
if (scanf("%19s",a) != 1)
{
fputs("Failure at input", stderr);
// further Error routine.
}
if (!strcmp(a,"david"))
{
printf("...");
}
}
您不能使用比较运算符在c中比较两个字符串。尝试使用
strcmp(const char* one, const char* two)
也就是说,在您的情况下使用
#include<stdio.h>
#include<cs50.h>
int main(void){
char[] a = get_string("ENTER YOUR NAME FOR READING\n");
char[] b = "david";
if (!strcmp(a,"david"))
{
printf("...");
}
}
此外,c中的字符串未声明为字符串。它们被声明为char数组
比较两个类似char *a, *b; a == b;
的char指针已被编译器接受,但是如果使用这种语法比较字符串值,则可能无法获得预期的结果。有时它可能会评估为true
或有时会评估为false
。原因是程序检查a
和b
是否指向相同的地址,而不是它们是否具有相同的字符串值。考虑下面的程序。
#include <stdio.h>
int main()
{
char* a = "test";
char* b;
if ((b="test") == a)
printf("Impossible\n");
else
printf("Thought so\n");
printf("%p %p\n", a, b);
return 0;
}
输出
Impossible
0x55b6bd52d004 0x55b6bd52d004
如从输出中看到的,if
块被评估为true
。原因也是在输出中。 a
和b
指向相似的地址。为什么?
它来自string-pooling,是编译器优化之一。即使
a
和b
在程序中的不同点处初始化,因为它们引用的是相同的字符串常量,所以字符串常量仅由编译器初始化一次。
这里是可执行文件的objdump
。
$ objdump -s -j .rodata
a.out: file format elf64-x86-64
Contents of section .rodata:
2000 01000200 74657374 00496d70 6f737369 ....test.Impossi
2010 626c6500 54686f75 67687420 736f0025 ble.Thought so.%
2020 70202570 0a00 p %p..
test
仅初始化一次。为了快速检查,请考虑该程序的输出及其objdump
。
#include <stdio.h>
int main()
{
char* a = "test";
char* b;
if ((b="test1") == a)
printf("Impossible\n");
else
printf("Thought so\n");
printf("%p %p\n", a, b);
return 0;
}
输出
Thought so
0x557a96aa9004 0x557a96aa9009
objdump
$ objdump -s -j .rodata a.out
a.out: file format elf64-x86-64
Contents of section .rodata:
2000 01000200 74657374 00746573 74310049 ....test.test1.I
2010 6d706f73 7369626c 65005468 6f756768 mpossible.Though
2020 7420736f 00257020 25700a00 t so.%p %p..
从输出中可以明显看出a
和b
指向不同的位置,并且它们都具有不同的字符串值,这些值由编译器分别初始化。那么,如果a
和b
具有相似的字符串值,那么a==b
是否总是等于true?考虑下面的程序。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
char* a = malloc(sizeof(char) * 5);
strcpy(a, "test");
char* b;
if ((b="test") == a)
printf("Impossible\n");
else
printf("Thought so\n");
printf("%p %p\n", a, b);
return 0;
}
输出
Thought so
0x5607d9938260 0x5607d91fb004
即使a
和b
具有相同的字符串值,if
仍将评估为false
。为什么?由a
创建的地址malloc()
指向的文件属于可执行文件的堆部分,而b
指向的地址属于可执行文件的数据部分,它们的确不同。
那么我们应该怎么做才能比较字符串值?
很好,很简单,已经有可以执行此任务的库函数。您可以将它们与string.h
一起使用。考虑下面的代码。
#include <stdio.h> #include <stdlib.h> #include <string.h> int main() { char* a = malloc(sizeof(char) * 5); strcpy(a, "test"); char* b = "test"; char* c; if (strcmp((c="test"), a) == 0) printf("Impossible\n"); else printf("Thought so\n"); if (strcmp(b, a) == 0) printf("Impossible\n"); else printf("Thought so\n"); if (strcmp(b, c) == 0) printf("Impossible\n"); else printf("Thought so\n"); printf("%p %p %p\n", a, b, c); return 0; }
输出
Impossible Impossible Impossible 0x556debf41260 0x556deac28004 0x556deac28004
无论
a
,b
和c
指向何处,如果它们都具有相同的字符串值,则strcmp()
返回0
。