【问题标题】:why strlen() function is giving wrong value为什么 strlen() 函数给出错误的值
【发布时间】:2020-11-10 14:36:28
【问题描述】:

我不明白为什么strlen() 只为第一个字符串提供错误值(即:9)。之后,这些值就会正确出现。

#include <stdio.h>
#include <string.h>

int main() {
    int m, i, j;
    i = 2;
    j = 5;
    char a[i][j];
    for (i = 0; i <= 2; i++)  {
        scanf("%s", a[i]);
    }
    m = strlen(a[0]);
    printf("%d\n", m); //here the problem is coming//
    m = strlen(a[1]);
    printf("%d\n", m);
    m = strlen(a[2]);
    printf("%d\n", m);

    return 0;
}

输入:

heyman
jack
bro

输出:

9
4
3

【问题讨论】:

  • 字符串最多只能有4 个字符,因为j == 5
  • heyman 写入越界。
  • @fly_high j=5 会给你 5 个字符来写,从 04,但字符串需要在末尾有一个额外的字符 \0 否则 C 没有不知道字符串实际上已经结束了。这意味着你必须从你的最大长度中减去1 来解释这个终结符\0
  • @fly_high a[5] 表示您有可用的位置a[0], a[1], a[2], a[3], a[4],即5 空格,而不是数组将上升到a[5]
  • 行和列是一样的。数组 a[2] 只有 2 个元素,索引为 0..1

标签: c input string-length strlen


【解决方案1】:

a 的每一行只有 5 个字节。当您将heyman 读入a[0] 时,它会溢出到a[1]。所以你有:

a[0] = "heyma"
a[1] = "n\0"

那么当你读入a[1],你就有了

a[0] = "heyma"
a[1] = "jack\0"

请注意,a[0] 中没有空终止符。因此,当您调用strlen(a[0]) 时,它会越过a[0] 的末尾并继续在a[1] 中搜索空字节。 a[0] 有 5 个字节,a[1] 有 4 个字节,因此长度为 9。从技术上讲,这是未定义的行为,但在实际实现中会发生这种情况,因为二维数组是连续的。

此外,当您读入a[2] 时,您完全位于a 数组之外,从而导致未定义的行为。

【讨论】:

  • 我想知道从a[0]溢出到a[1]是不是ub(显然用a[2]做任何事情都是)。
  • @PaulHankin 我想我读过关于它的相互矛盾的答案。
  • 哇,这真的很有趣,我明白了所有的想法......谢谢@Barmar
  • 标准中的附录 J.2 明确列出了这种越界多维数组访问作为未定义行为的示例:An array subscript is out of range, even if an object is apparently accessible with the given subscript (as in the lvalue expression a[1][7] given the declaration int a[4][5])
  • 溢出到a[1]时是UB
【解决方案2】:

由于您的数组的长度为[2][5],因此您最多可以存储2 长度为4 的单词,每个单词除了字母之外还有终止字符\0

您输入heyman 意味着您写了太多字母并且没有足够的空间来存储\0。尝试使用较短的单词或将长度从 5 更改为 7

您还将3 单词存储在长度为2 的数组中,长度是指存储的元素数量,而不是您可以达到的数量。长度2 将具有可用位置01,因此当您将第三个单词作为输入传递时,您试图在数组边界之外写入。

【讨论】:

  • 他需要将长度改为至少7:heyman有6个字符加上null
  • @Barmar 哦,是的,你是对的,出于某种原因,我在 heyman 中计算了 5 个字符而不是 6 个
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-08-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-04-27
  • 2013-03-27
相关资源
最近更新 更多