【问题标题】:Why is NOT std::string defined in program equal to std::string loaded from file when printing out using prinft() and string::c_str()?为什么在使用 prinft() 和 string::c_str() 打印输出时,程序中定义的 std::string 不等于从文件加载的 std::string?
【发布时间】:2020-10-03 08:49:25
【问题描述】:

当我创建 std::string 并像这样在程序中定义它并将其打印到控制台时,它看起来像这样:

std::string shader = "#version 330\nlayout(location = 0) in vec3 vp;void main(){gl_Position = vec4(vp, 1.0);}";
printf("Original: %s\n", shader.c_str());

输出:

但是当我以下面的方式从文件中加载 std::string 然后将其打印到控制台时,它看起来像这样:

std::string shader;
std::ifstream inputStream(path, std::ifstream::in);
if (inputStream.is_open())
{
    while (inputStream.good())
    {
        std::string line;
        getline(inputStream, line);
        shader.append(line);
    }
}
printf("LOADED: %s\n", shader.c_str());

文本文件:

#version 330\n
layout(location=0) in vec3 vp;
void main ()
{
     gl_Position = vec4 (vp, 1.0);
}

输出:

从文件加载时我需要它做同样的事情。更具体地说,我需要它使用特殊字符 \n。

当我尝试删除“\n”时:

这里的问题是我需要在“..330”和“布局...”之间换行

【问题讨论】:

  • 只是不要把\n放在你的文件里?
  • 我想到了这一点,但我需要它在新行上并且删除它不会有帮助。
  • 如果您删除\n,请证明您遇到的问题。
  • 是的,我编辑了帖子,你现在可以看到我删除后的问题\n
  • 你报告的输出怎么和你的文本文件不对应?

标签: c++ printf ifstream stdstring


【解决方案1】:

\n 和类似的格式称为"escape sequences",编译器在翻译您的代码时会处理它们。

所以像printf 这样的函数永远看不到它们,也不知道如何处理它们。 相反,他们看到的是真正的“换行”字符,它是不可见的,字符代码为 10 (0x0a)。

当您在文本编辑器(如记事本)中编写文本时,每次按下 Enter 键时都会自动添加该字符,并将其保存到文件中。 如果您使用十六进制编辑器查看,则可以在任何文本文件中看到这些字符。

(注意,在 Windows 上,可能会添加 2 个字符“换行”和“回车”,即 13 或 0x0d)

所以,你有两个选择:

  1. 不要在您的输入文件中使用\n,而是像往常一样将行拆分,并使用istream::read 或类似函数来读取文件中的所有字节。

  2. 如果不允许更改输入文件,请编写一个函数,在字符串中搜索“\n”(2 个字符的子字符串)并将它们替换为单个文字 \n (0x0a)

网上有很多例子,这里有一个:Convert string with explicit escape sequence into relative character

不幸的是,标准库中没有预先存在的函数可以做到这一点,但是自己编写的代码很短很简单,如果只需要翻译\n而没有其他转义,那就更简单了字符。

【讨论】:

  • Re: '写一个函数来搜索字符串中的 "\n" ' -- 代码必须搜索"\\n"。那是两个字符,一个反斜杠后跟字母 n。 "\n" 是一个字符。 +1。
【解决方案2】:

getline 只是逐行读取输入,在它找到的第一个回车处停止。在文件中手动添加 \ 和 n 只会使 getline 将其解释为更多文本,它只是等待真正的回车符返回。 您所要做的就是在 .append() 调用中添加 \n。

【讨论】:

  • 但是没有用 \n 调用 .append 就没有办法了吗?
  • 因为我不知道当我正在加载的文件变大时我需要多少新行。
  • @Wortig 看来您想读取并输出整个文件。因此,只需一次读取一个字符并将所有字符附加到您的字符串中即可。没有必要以任何方式将换行符视为特殊的。
  • @john 非常感谢,看来它解决了我在阅读每个字符时遇到的问题。
  • @Wortig 哪里绝对不需要,使用 getline 工作,你为什么不能添加一个 "\n" ?
【解决方案3】:

解决方法是按每个字符读取文本文件,然后打印字符串是正确的。

std::string shader;
std::ifstream inputStream(path, std::ifstream::in);
char character;
if (inputStream.is_open())
{
    while (inputStream.get(character))
    {
        shader += character;
    }
}

打印着色器时的输出:

在每个 getline 之后添加 \n 也应该有效。

【讨论】:

    猜你喜欢
    • 2018-05-13
    • 2012-04-17
    • 1970-01-01
    • 2011-11-04
    • 2023-01-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-01
    相关资源
    最近更新 更多