// gets valid 2-bytes utf-8 symbol
// returns remap russian unicode to 0 ... 65 (А = 0 ... я = 63; Ё = 64, ё = 65)
// or unicode for other (not russian) 2-bytes utf-8
// call this function only if utf8_symbol() (well, may be utf8_len() too) returns 2
// see https://symbl.cc/en/unicode/blocks/cyrillic/
int
get_rus_code (const char *s)
{
int u_code = ((s[0] & 0x1f) << 6) | (s[1] & 0x3f); // unicode for 2-bytes utf-8
// remap russian unicode to 0 ... 63,
if (u_code >= 0x410 && u_code <= 0x44f)
return u_code - 0x410; // А ... я
if (u_code == 0x401)
return 64; // Ё
if (u_code == 0x451)
return 65; // ё
return u_code; // for other valid 2-bytes utf-8 the result is from 0x80 to 0x7FF
}
// returns position of word in `s[]`
// or EOF if there are no words
// puts length of the word (in bytes) into `*wlen`
int
get_word (const char *s, int *wlen)
{
#define W_SEPARATORS " \n\r\t"
int pfx_l = strspn(s, W_SEPARATORS); // skip initial spaces
if (!s[pfx_l])
return EOF;
*wlen = strcspn(s + pfx_l, W_SEPARATORS); // all non-spaces are taken as a word
return pfx_l;
}
除了 strchr/islower/toupper 和其他使用单个字符的函数外,所有字符串函数(嗯,也许几乎所有)都可以很好地使用 utf-8(如果 strtok/strspn 等中的分隔符是正常的 ascii(在典型任务中这几乎总是这样。
虽然可以使用 strstr 代替 strchr,但一些面向 utf-8 的函数仍然有用。
例如,这是这两个:
基于它
utf8_len()
,很容易制作一个strlen()
以 utf-8 字符返回字符串长度的模拟(很明显,utf8_len 的工作速度比 utf8_symbol 快一个数量级,utf8_symbol 做了很多额外的工作)。可以检查返回的
utf8_symbol
unicode 是否包含在西里尔字符范围内(从 0x0400 到 0x04ff,俄语字母从 0x0410 到 0x044f,0x0401 (Ё) 和 0x0451 (ё)),并生成 is_rus_letter () 函数或类似的函数。如果您专注于使用俄文字母,那么通常您可以进行以下转换:
使用此功能,可以轻松地将俄语字母分析为大写/小写(前 32 个为大写)、元音/辅音(位掩码属于
uint64_t
)。(顺便说一句,在这里你可以看到字母
Ёё
在我们的语言中显然是多余的 - ))好吧,作为补充(以及答案第一段的说明),这里有一个函数可以让您逐字读取 utf-8 中的字符串:
及其使用示例:
如果您有任何问题,请随时在评论中提问