即使在 c 中添加 null 终止符后,从文件中读取的字符串也不是 null 终止符?

String read from file not null terminating even after adding null terminator in c?

提问人:Dr-Galunga 提问时间:5/26/2023 最后编辑:Dr-Galunga 更新时间:5/27/2023 访问量:81

问:

让我先说一个事实,即我已经查看了其他相关的堆栈溢出问题,但它们都只是简单地说要添加空终止符,我一直在这样做,所以我不知道发生了什么。

我正在编写一个 opengl 程序,需要将从其他文件获取的着色器解析为字符串,以便 opengl 可以用它们发挥它的魔力。但是,由于某种原因,我在用 c 编写非常非常基本的文件解析器时遇到了麻烦。有人告诉我,在读取文件后,您需要在 char 数组的末尾添加自己的终止字符,因此我 malloc'd 了一个额外的字符并将其设置为“\0”。但是,每当我打印出字符串时,我仍然会得到一个尾随垃圾字符,我假设它只是恰好位于该内存位置的任何数字的 ascii 解释。有人知道如何解决这个问题吗?我试过添加更多空间,在空间上写字等等,但真的不知道该怎么做。

函数如下:

char* parse_shader(const char* path)
{
    char* buffer = 0;
    long length = 0;
    //Look up how to read in from file
    FILE* source = fopen(path, "r");
    if(!source)
        ERROR_RETURN(NULL, "Failed to load source: %s\n", path);
    
    fseek(source, 0, SEEK_END);
    length = ftell(source);
    fseek(source, 0, SEEK_SET);
    buffer = malloc(length + 1);
    if(!buffer)
        ERROR_RETURN(NULL, "Failed to allocate memory for file: %s\n", path)
    fread(buffer, 1, length, source);

    buffer[length] = '\0';

    fclose(source);

    return buffer;
}

正如你所看到的,该函数接受一个路径,找到文件的长度,用一个额外的字节来分配空格,将内容添加到缓冲区,然后使最后一个索引成为空终止符。出于某种原因,这不起作用。

下面是一个示例输出:

#version 330 core
layout(location = 0) in vec3 a_pos;

void main()
{
    gl_Position = vec4(a_pos, 1.0);
}╪

编辑: 在文本编辑器中进一步查看文件并通过 printf 进行一些调试后,我发现它说该文件的长度为 112 字节,但当添加到缓冲区时,它显示为 106 字节。

阅读其中一条评论后,似乎是因为窗口将文件中的换行符存储为“回车换行符对”。

我假设 ftell() 正确获取文件的大小,这意味着它包含 \r,但是当字符串读入缓冲区时,\r 不包括在内,因此缓冲区末尾有额外的空间。

有没有人知道如何解决这个问题。

根据另一个评论请求,我在 Windows 上使用 gcc。

C 字符串 文件 解析 IO

评论

1赞 Some programmer dude 5/26/2023
您是否查看过文件本身,例如十六进制编辑器,以查看它真正包含的内容?也许额外的字节在原始文件中?
3赞 BoP 5/26/2023
请注意,当文件以二进制模式打开时,ftell 仅提供文件大小(以字节为单位)。
2赞 Some programmer dude 5/26/2023
您是否使用的是 Windows 系统,其中文件中的换行符存储为回车符换行符对,当您从文件中读取时,它将转换为单个换行符?
3赞 Aconcagua 5/26/2023
fread返回它实际读取的字节数,因此您可能没问题 - 并且您可能想要检查并确定读取是否真的成功。buffer[fread(...)] = 0;feofferror
2赞 Some programmer dude 5/26/2023
OT:你的函数名字很糟糕......它不解析任何内容。它加载的文件可以是任何文件,而不仅仅是着色器文件。也许可能是一个更合适的名字?:)read_file

答: 暂无答案