【问题标题】:Why is the size of my string changing? (C)为什么我的字符串的大小会发生变化? (C)
【发布时间】:2015-01-18 14:06:26
【问题描述】:
    fseek(fp, 0L, SEEK_SET);
        int i; char c;
        i = 0;
        for (c = getc(fp); c != EOF; c = getc(fp)) {
            c = tolower(c);
            file_string[i] = c;
            i++;
        }

在这段代码中,我通读了文件的每个字符,将其转换为小写,并将其放入字符串中。现在,假设我为 file_string 分配了 21 个字节 * sizeof(char)。有时,在此处显示的这段代码之后,strlen(file_string) 将返回 30,而不是预期的 20。也许我的指针算法有问题?我收集的一些东西:

1 - 这只在某些时候发生。

2 - 我已确保为 file_string 分配了正确数量的字节(这发生在此代码之前的行)。代码如下:

fseek(fp, 0L, SEEK_END);
file_len = ftell(fp);
file_string = malloc( sizeof(char) * (file_len+1) );

打印 file_len 输出预期的长度。

3 - 我打印出 i 的值以确保它的迭代次数与 file_string 的长度一样,确实如此。

4 - 现在,直接在这段代码之后(关闭文件之后),当我打印出 file_string 的长度时,有时它会突然增加到更大的大小。这一直在我的代码中的其他地方引起问题。

现在,我想我可以将空终端字符插入其中并解决问题(也许这会导致进一步的错误),但我更想知道这里发生了什么。

这是我的调试示例,显示了前后大小的变化。请记住,之前的长度对应于 file_len 变量。

>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> file_len: 24
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>i: 0
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>i: 1
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>i: 2
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>i: 3
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>i: 4
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>i: 5
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>i: 6
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>i: 7
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>i: 8
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>i: 9
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>i: 10
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>i: 11
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>i: 12
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>i: 13
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>i: 14
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>i: 15
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>i: 16
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>i: 17
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>i: 18
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>i: 19
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>i: 20
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>i: 21
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>i: 22
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>i: 23
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> strlen(file_string): 30

【问题讨论】:

  • 三件事:(1)显示的代码中没有任何内容可以阻止缓冲区溢出,(2)您没有创建字符串,因为您没有终止字符串(并且您必须确保你 null 终止字符串;C 不会为你做这件事——如果你想被保姆,去学习 Java 或其他东西),并且(3)getc() 返回一个int,而不是char,因为它可以返回任何有效的char 值加上一个不同的值 EOF。使用int c; 而不是char c;。标准循环习惯用法是while ((c = getc(fp)) != EOF)
  • 感谢您的提醒。

标签: c string string-length c-strings


【解决方案1】:

现在,我想我可以将空终端字符插入其中并解决问题(也许这会导致进一步的错误),但我更想知道这里发生了什么。

这就是真正的解决方案。 strlen 正在缓冲区中搜索 NULL 终止符,但没有找到,因为您从未添加过终止符。在您阅读代码之后,您应该明确添加 NULL 终止符(即file_string[i] = '\0')。

请记住,malloc 返回的存储空间没有归零,它基本上是随机数据(嗯...malloc 返回的存储内容是未定义的)。发生的事情是你跑出了缓冲区的末尾并进入了随机内存,然后它恰好跑到了更远的零字节并假设这是字符串的结尾。

【讨论】:

  • 当你不是真的谈论一个字符串时,可能想要替换缓冲区。
  • @Deduplicator - 好点。缓冲真的是正确的术语吗?我想说它在给定指针之后的某处搜索空终止符,但这感觉太复杂了。
  • 是的,缓冲区没有说明它包含什么。如果您想更具体但仍然正确,事情就会变得困难。
  • 哈哈哎呀,我仍然需要添加一个空终止符字符是有道理的。我担心记忆中发生了其他事情。谢谢。
  • @Deduplicator - 是的,很公平。我会保持现在的状态:)
猜你喜欢
  • 2018-05-01
  • 1970-01-01
  • 2017-08-22
  • 2018-04-14
  • 2012-05-21
  • 1970-01-01
  • 2018-10-04
  • 2017-02-10
  • 1970-01-01
相关资源
最近更新 更多