可携式行末标识符

21

有没有办法根据使用的操作系统自动使用正确的EOL字符?

我在想像 std::eol 这样的东西吗?

我知道使用预处理器指令非常容易,但我很好奇是否已经有这个功能。

我感兴趣的是,我通常在我的应用程序中有一些消息,稍后将它们组合成一个字符串,并且我希望它们用 EOL 分隔。我知道我可以使用 std::stringstream << endl,但有时候似乎相比于常规附加而言有些过度。

5个回答

19

std::endl被定义为除了向流中写入'\n'并刷新它之外不做任何事情(§27.6.2.7)。对于stringstream, 刷新被定义为不做任何事情,因此您只能通过这种方式来表达 mystringstream << '\n'。您所在的操作系统上的标准库实现将适当地转换\n,所以这不是您要考虑的。

因此,endl已经是最佳性能和可移植性,您唯一可能需要的是<< '\n',如果您想要高效地写入文件(而不是stringstream)。好吧,<< '\n'还可以消除对stringbuf::flush的无意义虚拟调用。除非剖析显示该空函数调用占用时间,否则不要考虑它。


我发现在任何地方都使用'\n'是完全没问题的,操作系统(比如Windows)会自动处理它,使其变成\r\n当我写入控制台和文件时。对我来说,这已经足够了。 - Andrew
@Potatoswatter:也许你指的是(假设它是C++标准)现在的第§27.7.3.8节? - sturmer
@sturmer 是的,这是对当时流行的C++03的引用。数字可能会改变,但该部分的名称为[lib.ostream.manip]。无论如何,在那里真的没有什么可看的。它只是说“效果:调用os.put(os.widen(’\n’) ),然后os.flush()。” - Potatoswatter
我想指出_flush_并不是毫无意义的。如果您正在使用_cout_语句进行调试,最好使用_endl_,否则不能保证在您期望打印语句时它会被打印出来。对于多线程控制台输出也是如此(尽管即使使用_endl_,这种情况也很混乱)。 - autonomy
@autonomy 此回答需要在上下文中阅读。这个流不是 cout。多线程需要使用互斥锁,刷新可能似乎有助于减轻竞态条件的症状,但这并不是解决方法。 - Potatoswatter

11
如果您想将一行分隔符写入流中:
std::cout << '\n';
或者
std::cout << "\n";
或者
std::cout << "whatever you were going to say anyway\n";

如果流是文本模式,并且操作系统使用的分隔符不是LF,它将被转换。

如果您想要写入一个行分隔符并刷新流:

std::cout << std::endl;
如果你有任何原因需要二进制模式输出,并且想要写入特定于平台的换行符,那么我认为你可能需要间接地实现它(将 '\n' 写入文本流,然后在二进制模式下检查得到的结果)。也许有一些直接从实现中获取换行序列的方法,但我不知道。无论如何,这并不是一个好主意:如果你正在以二进制模式写入或读取文件,那么它应该采用独立于操作系统的定义换行的格式,或者根本没有行。这就是二进制模式存在的目的。

2

只需以文本模式打开文件即可

FILE *fp = fopen( "your_file.txt", "w+t" );

然后

fprintf( fp, "some string and integer %d\n", i );
fclose(fp);

操作系统会根据其标准自动处理EOL。


1
嘿嘿,我是老派的 XD。 - Simone Margaritelli
2
现在你忘记关闭文件了。 :P - GManNickG
2
请不要在生产代码中使用fopen(),因为这会影响异常安全。请使用STL RAII替代方案。 - Pavel Radzivilovsky
3
得了吧,这只是一个例子,你难道也期望在生产环境中有一个名为“your_file.txt”的文件吗? - Simone Margaritelli
1
@Simone:很容易看出文件名需要从你的例子中进行调整。但很难发现不应该使用C标准库来处理文件。 - sbi
我不明白操作系统如何处理EOL。在这个例子中,EOL字符将是\n,操作系统不应该更改它。 - Natalie Adams

1

嗯,STL有std::endl,你可以用它作为换行符。

std::cout << "Hi five!" << std::endl;

请注意,除了添加一个换行符,std::endl还会清空缓冲区,这可能会对性能产生不良影响。

2
哎呀,那不是STL,那是iostreams。 - Billy ONeal
我同意BillyONeal的观点。此外,当你只需要一个 '\n' 时,只需写 '\n',而不是 std::endl。我曾经看到过将无用的 std::endl 替换为 '\n' 后加速了8倍的情况。 - sbi
哦,我不知道它们是独立的实体。我只是以为它们因为共享命名空间而已。感谢您的纠正。 - dimatura

1

即使是文本文件,文件也经常在不同的机器之间传输,因此“特定于操作系统的换行符”是个自相矛盾的说法。

尽管如此,操作系统对此有所规定,特别是Windows这样的操作系统,尽管许多Windows程序可以正确读取\n分隔的文件,但winapi多行编辑控件却不能。我建议您仔细考虑什么才是适合您的:不一定是您的操作系统推荐的。如果您的文件将存储在可移动介质上,请勿使用操作系统标准。请使用全局标准0xA。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接