2015-04-23 27 views
1

簡單的問題,有可能引起棘手的答案刪除換行符這裏:我在尋找一個便攜式本地化友好的方式來取消C尾隨換行,最好是一些基於標準的。下,在便攜式和國際友好的方式

我已經知道了以下解決方案:

  • 解析爲\r\n某種組合。在處理Windows,* nix和Mac時,真的不是很漂亮,所有這些都使用不同的序列來表示一條新線。另外,其他語言甚至使用相同的轉義序列換行?我期望這會在使用英文不同字形的語言(比如說日文等)中爆炸。

  • 刪除尾部n字節並替換最終的\0。看起來像更脆弱的方式來做到上述。

  • isspace看起來很誘人,但我只需要匹配換行符。其他空格被認爲是有效的標記文本。

  • C++有一個類來做到這一點,但它是在純-C世界一點幫助我。

  • locale.h看起來像我之後,但我看不出有關提取換行符的任何內容。

因此,這是一個例子,我將不得不「滾動我自己」的功能,或者是有什麼,我已經錯過了?謝謝!


解決方案

我結束了兩個答案來自Weather VaneLoic,分別結合我的最終解決方案。有效的方法是使用方便的strcspn函數打開從Loic提供的鏈接中選擇的第一個換行符。因此,我可以根據許多支持的語言環境來選擇分隔符。在這個層面上,有太多不足以支持這一點的人很好。我甚至不知道有幾種競爭性的西里爾文編碼。

這樣,我可以同時仍使用標準庫函數實現「足夠好」的跨國公司的支持。

因爲我只能接受一個答案,我選擇風向標的他是最後我用調用。這就是說,這真的是兩個答案一起工作對我來說。

回答

1

最好的一個我所知道的是

buffer [ strcspn(buffer, "\r\n") ] = 0; 

這是處理的\r\n所有組合的安全的方式 - 無論是,一個或沒有。

+0

Spiffy,不知道'strcspn'。它如何處理國外的語言環境? – phobos51594

+0

'strcspn'的MS文檔中提到了語言環境,也許你可以按照它進行操作。 https://msdn.microsoft.com/en-us/library/xe8sk0x7.aspx –

+0

啊,看着Posix版本,它不包含locale參數(至少string.h中沒有) 。 – phobos51594

1

我建議用一個標準的空間(US-ASCII爲0x20)來替換一個或多個空格字符。僅考慮ISO-8859-1字符(https://en.wikipedia.org/wiki/ISO/IEC_8859-1),空白在於0x00..0x20(C0控制字符和空格)和0x7F的任何字節的..0xA0(刪除,C1控制字符和不間斷空格)。請注意,US-ASCII是ISO-8859-1的子集。

但考慮到Windows 1251(https://en.wikipedia.org/wiki/Windows-1251)將不同的可見(非控制)字符分配給範圍0x80..0x9F。在這種情況下,這些字節不能被空格替換而不丟失文本信息。

爲空白字符一個廣泛的定義

資源:

還採取到帳戶,可以使用不同的編碼,最常見的:

但在非西方國家(如俄羅斯,日本),進一步字符編碼也很平常。存在許多編碼,但嘗試支持每個已知編碼可能沒有意義。

因此,嘗試定義和限制您的用例,因爲以完全通用的方式實現它意味着很多工作。

+0

閱讀評論,你建議用空格替換'CR'和'LF'。對於由* newlines *分隔的內容,這無關緊要,無論使用什麼編碼。 –

+0

我很抱歉,如果我誤解了你(托馬斯迪基),但'CR'和'LF' *是*新行;根據http://en.wikipedia.org/wiki/Newline#Unicode,我建議的範圍涵蓋了ISO-8859-1的所有換行符(還包括進一步控制字符)。但是,當然,總體思路必須根據特定的要求進行改進。 – Loic

0

此答案適用於C++用戶,但有相同的問題。

匹配任何語言環境和字符類型換行符可以這樣做:

#include <locale> 

template<class Char> 
bool is_newline(Char c, std::locale const & loc = std::locale()) 
{ 
    // Translate character into default locale and character type. 
    // Then, test against '\n', which is the only newline character there. 
    return std::use_facet< std::ctype<Char>>(loc).narrow(c, ' ') == '\n'; 
} 

現在,刪除所有尾隨換行符可以這樣做:

void remove_trailing_newlines(std::string & str) { 
    while (!str.empty() && is_newline(*str.rbegin()) 
    str.pop_back(); 
} 

這應該是絕對可移植的,因爲它僅依賴於標準的C++函數。