2017-10-12 74 views
2

我有下面的代码:如何获得std :: endl在必要时输出“ r n”?

std::cerr << "Hello" << std::endl; 
std::cerr << "World" << std::endl; 

...这通常是巨大的。

但:我在一个Erlang的port程序中运行它,而Erlang已经完成了......终端意味着“\ n”不再转换为CRLF,这意味着我的输出显示as ...

Hello 
    World 

Erlang做了什么我的终端?我如何检测它?在这种情况下,我如何获得std::endl以输出\r\n

注意:它可能(可能)不仅仅是Erlang从我的程序中摄取stderr并搞砸了换行符。如果我在NIF中使用plain-ol'printf("Hello\n"),我会看到同样的问题。

回答

3

首先不要使用::std::endl。它并没有真正做到你想要的。它始终输出'\n'并刷新流。冲洗河流是大部分时间内巨大且不必要的性能损失。

而我的意思是'\n'。一个实际的文字,'\n'。它不会做任何翻译或任何人们认为它的做法。即使在Windows上,也只是一个平面'\n'和一个刷新。您在windows下获得的换行符由较低级别的iostream工具处理,并由流是否处于binary模式进行控制。

Erlang对您的终端做了什么可能会将其置于CBREAK模式。这里有一个很好的问题,其答案描述了Unix中原始,熟化和Cbreak终端驱动程序模式之间的区别。

您可能可以手动将您的终端设置回烹饪模式。 Erlang会这样做的唯一原因是,通常你只能得到人们输入时输入的内容。 CBREAK可让您在输入字符时获取每个角色。

你也可以自己测试一下终端在哪种模式.Linux(和后来的Pos​​ix版本)已经明显地用各种标志替代了三种终端模式,它们的组合效果导致了与旧终端模式非常相似的行为。

首先,你可能想要使用isatty(1)(在标准输出上调用isatty),在尝试其他任何事情之前查看你的输出是否真的是终端。

然后,您可以使用tcgetattr将各个位的当前设置读入struct termios。此结构包含一个名为c_oflag的成员用于输出模式位。在这种情况下的相关位可能是ONLCR,也许(但我怀疑不是)OPOST

+0

我假设Erlang将终端设置为CBREAK模式有一个很好的理由,所以我不想设置它(可能会打破Erlang的输出)。如何检测模式?有了这个,我可以发明'我的:: endl'并做正确的事情... –

+0

@RogerLipscombe - 我编辑了评论我删除到我的答案,因为它回答“我如何检测它?”你的问题的一部分。 – Omnifarious

+1

“CBREAK可让您在输入字符时获取每个角色。” - 这就是为什么Erlang把它放在这种模式下。它默认运行REPL。 –