2017-10-12 55 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。 –