c++ - 您如何处理标准库中的 signed char -> int 问题?

标签 c++ c character-encoding special-characters

这是我工作中长期存在的问题,我意识到我仍然没有好的解决方案......

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之间我对这些问题的处理要好得多。虽然没有简单的答案,但每一点理解都会有所帮助。

最佳答案

How do you test for whitespace, isprintable, etc., in a way that doesn't suffer from two issues:
1) Sign expansion
2) variable-width character issues
After all, all commonly used Unicode encodings are variable-width, whether programmers realize it or not: UTF-7, UTF-8, UTF-16, as well as older standards such as Shift-JIS...

显然,您必须使用支持 Unicode 的库,因为您已经(正确地)证明了 C++03 标准库不是。 C++11 库得到了改进,但对于大多数用途来说仍然不够好。是的,一些操作系统有一个 32 位的 wchar_t,这使得它们能够正确处理 UTF32,但这是一个实现,并且不受 C++ 的保证,并且对于许多 unicode 任务来说远远不够,例如遍历字形(字母) .

IBMICU
Libiconv
microUTF-8
UTF-8 CPP, version 1.0
utfproc
以及更多 http://unicode.org/resources/libraries.html .

如果问题不是关于特定字符测试,而是关于一般代码实践:做你的框架做的任何事情。如果您正在为 linux/QT/networking 编码,请在内部以 UTF-8 格式保存所有内容。如果您使用 Windows 进行编码,请在内部以 UTF-16 格式保存所有内容。如果您需要弄乱代码点,请将所有内容保存在 UTF-32 内部。否则(对于可移植的通用代码),随心所欲,因为无论如何,您都必须为某些操作系统或其他操作系统进行翻译。

关于c++ - 您如何处理标准库中的 signed char -> int 问题?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8083083/

相关文章:

C程序中使用terminfo捕获字符串key

html - script 标签的 charset 属性的默认值是多少?

c++ - C++ 中的字符串操作和文件 IO?

c++ - 我应该在 C++ 中分离 cpp 和 h 文件吗?

c# - 将结构数组从 C++ 编码到 C#?

c - c语言打印动态数组

C 中的条件语句和数组(初学者)

mysql - PHP PDO : chars ÖÄÅ wont show

xml - 无法在 RSS 源中显示法语字符而不出现编码错误

c++ - Windows 上有用的开源库/项目