C以便于携带和国际友好的方式删除换行符

C以便于携带和国际友好的方式删除换行符,c,parsing,localization,C,Parsing,Localization,这里有一个简单的问题和一个潜在的棘手的答案:我正在寻找一种可移植的和本地化友好的方法来删除C中的尾随换行符,最好是基于标准的 我已经知道以下解决方案: 分析\r和\n的某些组合。在处理Windows、*nix和Mac时,它们都使用不同的序列来表示新行,这真的很不好看。另外,其他语言是否对新行使用相同的转义序列?我预计这将在使用不同于英语的字形的语言中爆发(比如日语或类似语言) 删除尾随的n字节并替换最后的\0。这似乎是一种更为脆弱的方式 isspace看起来很诱人,但我只需要匹配换行符。其他空

这里有一个简单的问题和一个潜在的棘手的答案:我正在寻找一种可移植的本地化友好的方法来删除C中的尾随换行符,最好是基于标准的

我已经知道以下解决方案:

  • 分析
    \r
    \n
    的某些组合。在处理Windows、*nix和Mac时,它们都使用不同的序列来表示新行,这真的很不好看。另外,其他语言是否对新行使用相同的转义序列?我预计这将在使用不同于英语的字形的语言中爆发(比如日语或类似语言)

  • 删除尾随的
    n
    字节并替换最后的
    \0
    。这似乎是一种更为脆弱的方式

  • isspace
    看起来很诱人,但我只需要匹配换行符。其他空白被认为是有效的标记文本

  • C++有一个类可以做到这一点,但在纯C的世界里,它对我帮助不大

  • locale.h
    似乎是我想要的,但我看不到任何与提取换行符相关的内容

那么,这是一个我将不得不“推出我自己的”功能的实例,还是我遗漏了什么?谢谢


解决方案

最后,我分别结合了
风向标
Loic
中的两个答案,得出了最终的解决方案。有效的方法是使用方便的strcspn函数中断从Loic提供的链接中选择的第一个换行符。因此,我可以根据许多受支持的地区选择分隔符。这是一个很好的观点,在这个层面上,有太多的东西需要普遍支持;我甚至不知道西里尔语有几种不同的编码

通过这种方式,我可以在仍然使用标准库函数的情况下获得“足够好”的多国支持

因为我只能接受一个答案,所以我选择了风向标,因为他是我最后使用的。话虽如此,这两个答案对我来说真的很有用。

我所知道的最好的答案是

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

这是处理
\r
\n
所有组合的安全方法-两者都有,一个或没有。

我建议用一个标准空格(US-ASCII 0x20)替换一个或多个空白字符。仅考虑ISO-8859-1字符(),空白由0x00..0x20(C0控制字符和空格)和0x7F..0xA0(删除、C1控制字符和无中断空格)中的任何字节组成。请注意,US-ASCII是ISO-8859-1的子集

但要考虑到Windows 1251()为0x80..0x9F范围分配了不同的可见(非控制)字符。在这种情况下,如果不丢失文本信息,就不能用空格替换这些字节

有关空白字符的详细定义的参考资料:

还要考虑到可能会使用不同的编码,最常见的是:

  • ISO-8859-1()
  • UTF-8()
  • 视窗1251()
但在非西方国家(例如俄罗斯、日本),进一步的字符编码也很常见。存在许多编码,但尝试支持每种已知编码可能没有意义


因此,尝试定义和限制你的用例,因为它在完全通用性中执行意味着大量的工作。

< P>这个问题是针对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++函数。

Spffy,不知道关于代码> STRCSPN < /代码>。它是如何处理外国语言环境的?strcspn的MS文档中提到了语言环境,也许您可以跟进一下。啊,我在看Posix版本,它不包括locale参数(至少是
string.h
中的参数)。阅读评论,你建议用空格替换
CR
LF
。无论使用何种编码,这对于以换行符分隔的内容都没有用处。如果我误解了您的意思,我深表歉意(Thomas Dickey),但是
CR
LF
都是换行符;根据,我建议的范围包括ISO-8859-1的所有换行符(以及更多的控制字符)。但是,当然,总的想法必须根据具体的要求加以改进。