C 以可移植和国际友好的方式删除换行符

C Removing Newlines in a Portable and International Friendly Way

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

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

因此,这是我必须 "roll my own" 功能的一个实例,还是我遗漏了什么?谢谢!


解决方案

我最终结合了 Weather VaneLoic 的两个答案,作为我的最终解决方案。有用的是使用方便的 strcspn 函数在 Loic 提供的链接中 selected 的第一个换行符处中断。因此,我可以 select 基于许多支持的语言环境的定界符。很好的一点是,在这个级别上有太多的一般支持;我什至不知道西里尔字母有几种相互竞争的编码。

这样我就可以在使用标准库函数的同时实现"good enough"多国支持

由于我只能接受一个答案,所以我 selecting 了 Weather Vane,因为他是我使用的最后一个调用。话虽如此,这两个答案确实对我有用。

我知道的最好的是

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

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

我建议用一个标准 space (US-ASCII 0x20) 替换一个或多个白色 space 字符。仅考虑 ISO-8859-1 字符(https://en.wikipedia.org/wiki/ISO/IEC_8859-1),whitespace 由 0x00..0x20(C0 控制字符和 space)和 0x7F..0xA0(删除, C1 控制字符和不间断 space)。请注意,US-ASCII 是 ISO-8859-1 的子集。

但要考虑到 Windows1251 (https://en.wikipedia.org/wiki/Windows-1251) 将不同的可见(非控制)字符分配给范围 0x80..0x9F。在这种情况下,这些字节无法在不丢失文本信息的情况下被 spaces 替换。

有关白色 space 字符的广泛定义的资源:

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

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

因此尝试定义和限制您的用例,因为完全通用地实现它意味着大量工作。

此答案适用于遇到相同问题的 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++ 函数。