strcmp 总是返回 1,即使它等于 [关闭]

问题描述 投票:0回答:1

即使它们不相同,它也总是返回 1 我想知道为什么我必须在 scanf_s 中记下缓冲区大小 如果我不这样做,scnaf_s 就不起作用

int main(void) {
    char str1[30] = "push";
    char str2[30] = { 0 };
    scanf_s("%s", &str2,2);
    int result = strcmp(str1, str2);
    printf("%d\n", result);
    printf("%d %d", strlen(str1), strlen(str2));
    return 0;
}

比较str1和str2s的长度 我试图使用 strlen 但结果是 4 和 0 str2怎么可能是0?

c string strcmp strlen string.h
1个回答
1
投票

它总是返回 1,即使它们不相同,我想知道为什么我必须在 scanf_s 中记下缓冲区大小,如果我不这样做的话,scnaf_s 不起作用

如果可以避免,请不要使用

scanf_s()
或微软的其他所谓的安全增强功能。它们是非标准的*,并不比它们更传统的对应物特别安全,尽管微软的断言与此相反。在这种特殊情况下,他们咬了你。硬

当我使用
scanf_s
说明符时,为什么我必须将缓冲区大小传递给
%s

因为你做。这是该功能的一个有据可查的特征。目的是它允许函数避免溢出为接收结果而提供的缓冲区。但当然,要成功做到这一点,程序员必须传递一个实际上不超过实际缓冲区大小的缓冲区长度。还有其他更好的方法来解决这个问题。

strcmp() 总是返回 1,即使它们 [原文如此] 不同

strcmp()
should 当字符串不同时返回非零值。我假设您的意思是当
相同时strcmp()返回1,但您错了。程序中的 
strcmp()
调用不可能比较相等的字符串,因为被比较的字符串之一,
"push"
是四个字符长,而这个
scanf_s()
调用 ...

    scanf_s("%s", &str2,2);

...无论您输入什么,都不会读取超过一个字符的字符串。指定的 2 字节缓冲区大小必须容纳字符串字符和终止 null。

str2的长度怎么会是0呢?

很容易。根据文档,

当令牌太大而不适合时,除非有宽度规范,否则不会将任何内容写入缓冲区。

“太大”是指相对于您传递的缓冲区大小 (2),并且您没有提供宽度规范,因此如果您尝试输入大于将适合的字符串(即大于 1 个字符;见上文)

str2
没有任何内容。您注意将其初始化为全零(对您有好处),因此第一个字符是字符串终止符——因此是零长度字符串。

你怎么解决它?

如果必须使用

scanf_s
,则传递反映实际缓冲区大小(30 字节)的缓冲区大小参数。建议还包含一个宽度说明符:

    char str2[30] = { 0 };
    scanf_s("%29s", &str2, (unsigned int) sizeof(str2));

如果你不需要使用

scanf_s()
那么你有很多可能性。其中最好的是
fgets()

    fgets(str2, sizeof(str2), stdin);

但是你也可以使用传统的

scanf()

    scanf_s("%29s", &str2);

请注意,在这种情况下,适当的宽度说明符(如所示)足以避免缓冲区溢出。


*Microsoft 设法将这些函数的版本作为可选附件添加到 C 语言规范中,但它们自己的实现不符合要求,而且很少有其他 C 库提供任何版本。

© www.soinside.com 2019 - 2024. All rights reserved.