为什么我的文件读取功能将空终止符放置在多余的CR LF笔架的位置?

 收藏

今天,我尝试将一个简单的OpenGL着色器类放到一起,该类从文件中加载文本,并根据一些(相当不错的)自定义语法进行一点解析,以构建一对顶点和片段着色器(例如,编写“ .varying [type] [name];”将允许您在两个着色器中定义一个可变变量,而只编写一次,与“ .version”相同,)然后使用这两个着色器编译OpenGL着色器程序,然后标记着色器类当且仅当着色器代码正确编译时,才将其设置为“就绪”。

现在,我完成了所有这些工作,但是随后遇到了最奇怪的(坦率地说有点吓人)问题。我进行了所有设置,使用包含有效着色器代码的文件声明了一个新的“ tt :: Shader”,只是让它告诉我着色器无效,但是当我问到错误是什么时给了我一个空字符串(这意味着OpenGL给了我一个空字符串,因为它是从那里获取的。)

我再次尝试,这次使用明显无效的着色器代码,虽然它确定着色器无效,但仍然没有给出关于错误的信息,只是一个空字符串(从中我可以认为错误识别部分它也和以前一样。)

感到困惑,我手动将两个着色器(有效着色器和无效着色器)重新编写为字符串,并直接使用该字符串再次编译类,而没有文件访问权限。这样做,错误消失了,第一个错误正确编译,第二个失败,但正确地识别出错误是什么。

更困惑的是,我开始将文件中的字符串与自己编写的字符串进行比较。事实证明,尽管印刷了前者,但前者比梯子还要长一点。经过一些计数之后,我意识到这些字符必须是Windows CR LF行结束符,在导入过程中已被截断。

为了对此进行测试,我拿了手写的琴弦,在要切掉它们的地方插入了笔架,然后再次运行了琴弦比较测试。这次,它评估了长度是相同的,但是还告诉我,两者仍然不相等,这很令人困惑。

因此,我编写了一个简单的for循环来遍历两个字符串的字符,然后依次打印然后彼此打印,然后转换为整数,以便可以看到它们的索引值。我运行了该程序,浏览了(很长)的列表,并得出了一些颇有见地的答案,尽管答案不够明确:隐藏的字符在正确的位置,但是它们不是回车符……它们是零终止符!

这是我正在使用的文件读取功能的代码。没什么特别的,只是标准库的东西。

// Attempts to read the file with the given path, returning a string of its contents.
// If the file could not be found and read, an empty string will be returned.
// File strings are build by reading the file line-by-line and assembling a single with new lines placed between them.
// Given this line-by-line method, take note that it will copy no more than 4096 bytes from a single line before moving on.
inline std::string fileRead(const std::string& path) {


    if (!tt::fileExists(path))
        return "";


    std::ifstream a;


    a.open(path);


    std::string r;


    const tt::uint32 _LIMIT = 4096;


    char r0[_LIMIT];


    tt::uint32 i = 0;


    while (a.good()) {


        a.getline(r0, _LIMIT);


        if (i > 0)
            r += "\n";


        i++;


        r += std::string(r0, static_cast<tt::uint32>(a.gcount()));
    }


    // TODO: Ask StackOverflow why on earth our file reading function is placing null characters where excess carriages should go.

    for (tt::uint32 i = 0; i < r.length(); i++)
        if (r[i] == '\0')
            r[i] = '\r';


    a.close();


    tt::printL("Reading file '" + path + "' ...");


    return r;
}

如果你们所有人都可以阅读并告诉我它到底是怎么回事,那真是太棒了,因为我完全不知道它对字符串造成的影响。

最后,我明白了为什么空终止符没有出现在我身上,但对于OpenGL却如此,梯子使用C字符串,而我只用std :: string对象做所有事情,其中​​存储基于给定长度的东西它们几乎只是花哨的std :: vector对象。

回复