【问题标题】:Why does puts() function gives me a heart symbol?为什么 puts() 函数会给我一个心形符号?
【发布时间】:2017-07-21 08:46:56
【问题描述】:

我试图弄清楚如何用单个字符填充已知大小的字符串。然后我写了这个简单的代码来解决我遇到的一个更大的问题 (动态填充未知大小的字符串) .当我试图编译和运行这段代码时,我遇到了一个输出有一个心形符号的问题!我不知道它是从哪里来的。

#include <stdio.h>
#include <stdlib.h>

int main()
{
    int i;
    char str[3];
    for(i=0;i<=2;i++){
        str[i]=getc(stdin);
    }
    puts(str);
    return 0;
}

谢谢。

【问题讨论】:

  • 在 C 中 char 字符串实际上被称为 null 终止 字节字符串。 “空终止”部分很重要。如果您没有将它放在字符串中,那么所有字符串函数在搜索它时都会超出范围,并且您将有 未定义的行为,这会使您的程序 格式错误 i> 并且无效。
  • @某程序员老兄_谢谢。为什么它不跳过额外的输入?我知道索引是 0,1,2 并且 index-2 是空终止的。如果我输入堆栈为什么它不跳过 ack ?
  • 但是您终止str中的字符串,您读取了三个字符并将它们放入数组中。如果要读取三个字符,则数组需要 四个 个字符大,最后一个元素是终止符(您需要明确地对其进行初始化)。
  • @某程序员老兄_你说得对。
  • 或者,也许运行时只是喜欢你:)

标签: c arrays string output codeblocks


【解决方案1】:

C strings 是由null character 终止的字符序列(即代码为0 的字符)。可以表示为'\0''\x0'或简单的0

您的代码用三个字符填充str,但未能生成null 终止符。因此,puts() 打印它在内存中找到的任何字符,直到它到达第一个 null 字符。

您的代码公开了Undefined Behaviour。它可以做任何事情,这不是它的错。

为了修复它,您必须确保字符串以 null 终止字符结尾:

#include <stdio.h>
#include <stdlib.h>

int main()
{
    int i;
    // Make room for 3 useful chars and the null terminator
    char str[4];
    // Read three chars
    for(i = 0; i < 3; i ++) {
        str[i] = getc(stdin);
    }
    // Add the null terminator for strings
    str[3] = 0;

    puts(str);
    return 0;
}

更新

正如@JeremyP 在评论中指出的那样,如果您从 (stdin) 读取的文件在代码读取 3 字符之前结束,fgetc() 将返回同样有趣的 EOF(文件结尾)字符不可打印的字符,让您想知道它们来自哪里。

编写此代码的正确方法是在读取输入文件之前检查输入文件是否达到其 EOF (feof()):

#include <stdio.h>
#include <stdlib.h>

int main()
{
    int i;
    // Make room for 3 useful chars and the null terminator
    char str[4];
    // Read at most three chars
    for(i = 0; i < 3 && !feof(stdin); i ++) {
        str[i] = getc(stdin);
    }
    // Add the null terminator for strings
    str[i] = 0;

    puts(str);
    return 0;
}

【讨论】:

  • 如果我不将 'str[3] = 0' 带入我的代码?
  • 如果你不加str[3] = 0;那么你的情况和以前一样。 getc() 设置了 3 个字符,第四个字符是执行代码时发生在内存中的字符;之前执行的一些其他代码的剩余部分。 str 是一个局部变量;它在分配时没有用任何东西初始化。
  • 您的代码仍然不正确。 getc() 返回 int 以便在遇到文件结尾时返回 EOF。按照目前的情况,如果文件短于三个字符,缓冲区将被(char)EOF 字符填满,可能是0xff
  • @JeremyP 我同意。
  • @Ceeker 你是在谈论离开声明str[3] = 0; 吗?这是未定义的行为(UB)。 UB 不排除正确的行为。有时有效,有时无效。也许它总是可以在您的计算机上运行,​​并在不同的计算机、操作系统、编译器、同一编译器的版本等上崩溃。它也可以,表面上工作,但实际上它可能有隐藏的影响,您可能稍后才会注意到。
【解决方案2】:

c 中的字符串需要以 null 结尾,因此可能是您忘记在 str 的末尾添加 '\0' 字符。心形符号出现的原因是当 puts() 尝试写出一个字符串时,它会一直读取内存中的下一个字符,直到它到达一个空终止符 '\0'。由于它没有遇到一个,它只是继续读入内存并碰巧找到了我猜的心形符号。希望这会有所帮助。

【讨论】:

  • 谢谢你亲爱的尼古拉斯。
  • 可能是你忘了加'\0',不,不是可能是,他真的 忘记添加\0 字符。
  • @MichaelWalz,我只是想保持礼貌。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2022-01-05
  • 2012-11-28
  • 2013-06-18
  • 1970-01-01
  • 2023-02-25
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多