【发布时间】:2011-12-26 08:28:51
【问题描述】:
这是我工作中长期存在的问题,我意识到我仍然没有很好的解决方案...
C 天真地为 int 定义了所有的字符测试函数:
int isspace(int ch);
但是 char 通常是有符号的,并且一个完整的字符通常不适合 int 或任何用于字符串******的单个存储单元。
这些函数已经成为当前 C++ 函数和方法的逻辑模板,并为当前的标准库奠定了基础。事实上,它们仍然受到支持,afaict。
因此,如果您使用 isspace(*pchar),您最终可能会遇到符号扩展问题。它们很难看到,因此根据我的经验,它们很难防范。
同样,因为 isspace() 和它的同类都采用整数,并且因为一个字符的实际宽度通常是未知的,没有字符串分析 - 这意味着任何现代字符库本质上都不应该在 char 或 wchar_t 周围移动,但是只有指针/迭代器,因为只有通过分析字符流才能知道它有多少组成了一个逻辑字符,我不知道如何最好地解决这些问题?
我一直期待一个真正强大的库,它基于抽象出任何字符的大小因子,并且只使用字符串(提供诸如 isspace 等),但要么我错过了它,要么还有另一个更简单的库你们所有人(谁知道自己在做什么)都在使用的解决方案让我眼前一亮……
** 这些问题不会出现在可以完全包含完整字符的固定大小的字符编码中 - UTF-32 显然是具有这些特征的唯一选项(或将自身限制为 ASCII 或一些这样的)。
所以,我的问题是:
“你如何测试空白、可打印等,以一种不会遇到两个问题的方式:
1) 符号扩展,以及
2) 可变宽度字符问题
毕竟,大多数字符编码都是可变宽度的:UTF-7、UTF-8、UTF-16,以及诸如 Shift-JIS 之类的旧标准。如果编译器将 char 视为有符号的 8 位单元,即使扩展的 ASCII 也可能存在简单的符号扩展问题。
请注意:
无论你的 char_type 是什么大小,对于大多数字符编码方案来说都是错误的。
这个问题存在于标准C库中,也存在于C++标准库中;它仍然试图传递 char 和 wchar_t,而不是各种 isspace、isprint 等实现中的字符串迭代器。
实际上,正是那些类型的函数破坏了 std::string 的通用性。如果它只在存储单元中起作用,并且不试图假装将存储单元的含义理解为逻辑字符(例如 isspace),那么抽象会更诚实,并且会迫使我们程序员看在其他地方寻找有效的解决方案...
谢谢
所有参与的人。在这次讨论和WChars, Encodings, Standards and Portability 之间,我对这些问题有了更好的处理。虽然没有简单的答案,但每一点理解都会有所帮助。
【问题讨论】:
-
1.你为什么在乎? 2.
ctype.h中的函数不适用于宽字符,它们在wctype.h中。至于可变宽度 Unicode 字符,AFAIK 标准 C 库不支持它们。您可能需要使用诸如 ICU 之类的库来确定此类字符的特征。此外,字符并不总是 8 位宽。有几个流行的 16 位字符平台。您可以通过检查limits.h中的CHAR_BIT预处理器符号来确定字符大小。 -
至于为什么关心?因为它实际上是在国际软件中咬我的。我现在正在调试一个问题,归结为为我们的日本经销商签署多宽度字符扩展。每个人都应该关心,因为这是我亲自使用过的每个字符串库的根本失败——大多数开发人员甚至没有意识到这些库是不够的,并且由于围绕这个问题的思考不足,他们的代码充满了问题.
-
您一直在绝对地谈论标准未指定的事情。
wchar_t并不总是 16 位,它是由实现定义的。它的签名也是如此。这也适用于chars。如果您认真对待软件的国际化,您应该使用支持 Unicode 的库来处理字符串,而不是标准的 C 库。后者无法处理代理对之类的事情,例如,任何类型的 Unicode 编码。 -
我是认真的 - 所以 - 你说的这个“unicode 感知库”是什么? (此外,C/C++ 根本没有定义任何这些,这完全是一种逃避,有效地将这种混乱推倒在我们程序员身上——几乎为我们提供了有效的工具,但并不完全——至少对于任何 Unicode 编码都没有我知道——这肯定是我们在 98% 的计算领域都同意的事实标准,不是吗?)
-
char可能未签名。int总是如此。而char可能不是 8 位宽。
标签: c++ c character-encoding special-characters