【问题标题】:How do I index a (not all ascii) utf8 string in C?如何在 C 中索引(不是所有 ascii)utf8 字符串?
【发布时间】:2019-06-19 00:02:09
【问题描述】:

我想索引不一定包含的 utf8 字符串中的字符 只有ASCII字符。我想要我在 javascript 中得到的同样的行为:

> str = "lλך" // i.e. Latin ell, Greek lambda, Hebrew lamedh
'lλך'
> str[0]
'l'
> str[1]
'λ'
> str[2]
'ך'

遵循UTF-8 Everywhere 的建议,我将我的混合字符长度字符串表示为与 c 中的任何其他字符串一样 - 并且不使用 wchars。

问题在于,在 C 语言中,无法访问字符串的第 16 个字符:只能访问第 16 个字节。因为λ 在utf-8 中用两个字节 编码,所以我必须访问字符串的第16 和第17 字节才能打印出一个λ

供参考,输出:

#include <stdio.h>                                                                                                    

int main () {                                                                                                         
  char word_with_greek[] = "this is lambda:_λ";                                                                       
  printf("%s\n",word_with_greek);                                                                                     
  printf("The 0th character is: %c\n", word_with_greek[0]);                                                           
  printf("The 15th character is: %c\n",word_with_greek[15]);                                                          
  printf("The 16th character is: %c%c\n",word_with_greek[16],word_with_greek[17]);                                    
  return 0;                                                                                                           
}   

是:

this is lambda:_λ
The 0th character is: t
The 15th character is: _
The 16th character is: λ

有没有一种简单的方法可以将字符串分解成字符?编写一个将字符串分解为 wchars 的函数似乎并不难——但我想有人已经写过这个但我找不到它。

【问题讨论】:

  • which breaks a string into wchars 不要。只是不要。 wchars 不是 解码 UTF-8 字符。 wchars 是另一种编码。如果您想/需要解码,则解码为 utf32 字符串。
  • 几乎所有关于 Unicode 的事情都不是微不足道的。所以我建议你试着找一个图书馆(有几个)来帮助你。如果在此处询问库,但您可以尝试the software recommendation stack exchange site
  • 你的问题有点矛盾。你声明你想迭代一个字符串。这是 UTF-8 的一个非常自然的概念。您有一个指向字符串的指针和一个函数,该函数告诉您要跳过多少字节才能到达下一个字符。但是你想访问第 16 个字符。那是 索引访问 - 不是迭代。再次检查您的要求。通常不需要索引访问。很可能这只是您过去实现字符串处理的一个旧习惯。
  • 迭代用于字符串处理。但是迭代不需要索引。要处理的字符的索引通常是无关紧要的。您只想访问迭代器当前位置的字符。 Unicode 的索引访问效率低下(参见 Schlemiel thepainter's Algorithm),使用当前位置的概念进行迭代很快。
  • 字符没有快速简单的定义。 oᷔ 是单个字符吗?为什么或者为什么不? o͡e怎么样,有多少?

标签: c unicode utf-8


【解决方案1】:

这取决于您的 unicode 字符可以是什么。大多数字符串仅限于Basic Multilanguage Plane。如果你是(不是偶然的,因为它们的性质:至少没有表情符号的风险......)你可以使用char16_t 来代表任何字符。顺便说一句,wchar_t 至少和char16_t 一样大,所以在这种情况下使用它是安全的。

如果您的脚本可以包含表情符号字符,或其他不在 BMP 中的字符,或者只是如果您不确定,唯一万无一失的方法是将所有内容转换为 char32_t,因为任何 unicode 字符(至少在 2019 年...)作为使用少于 32 位的代码。

将 UTF8 转换为 32(或 16)位 unicode 并不难,并且可以手动编码,Wikipedia 包含足够的信息。但是你会发现很多已经编码和测试过的库,主要是优秀的 libiconv,但是 C 标准库的 C11 版本包含用于 UTF8 转换的函数。没那么好,但可以使用。

【讨论】:

  • 16 位 unicode 具有与 utf8 相同的缺陷,只是频率较低,
  • 为了与 UTF16 兼容,所有 unicode 都可以适应 24 位。 32 位总是足够的。
  • @Jasen:C 标准没有为 24 位定义字符类型 :-)
  • @SergeBallesta:但一个代码点也是不够的。例如。组合字符:它们不应该在新字符串的开头(因此它们不能作为问题的“第二个字符”)。语义在任何情况下都在标准 C 之外。
  • 是的,字符、代码点和字形是三种不同的字符度量。
【解决方案2】:

你应该查阅emacs背后的代码,因为emacs不仅实现了所有可能的转换功能,而且实现得很好,比几乎所有其他编辑器都要好。

api concerning the multibyte chars开始阅读,看看它们是如何实现的。

【讨论】:

  • 为了了解 Unicode 的工作原理,应该阅读 Unicode 标准和/或有关 Unicode 的文章,而不是一些巨大的可能错误的实现,谁知道什么。
  • @n.m.我想知道你能在 emacs 中找到一些错误的实现:)))。并且 emacs 在用户级别也可以很好地记录 unicode。
猜你喜欢
  • 2011-01-21
  • 1970-01-01
  • 2013-03-13
  • 1970-01-01
  • 2010-10-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-11-10
相关资源
最近更新 更多