C GTK字符计数与字节索引

C GTK字符计数与字节索引,c,string,encoding,gtk,cyrillic,C,String,Encoding,Gtk,Cyrillic,在GtkTextBuffer中 我可以看到GTK+将西里尔字符存储在两个字节中(这让我有点困惑,我认为它存储的是UTF-8编码的字符,因此每个字符都必须在一个字节中?) 这导致了一个问题-我正在扫描循环中作为字符串的文本,我需要根据循环中的索引引用相应的字符位置,但是它们不再具有相应的索引,因为文本包含西里尔文。字符数为8310,字符串大小约为11300 如果我在正在扫描的字符串上使用g\u str\u to_ascii(),稍后,当我在树状视图小部件上显示字符串的某些内容时,它会将西里尔字符显

在GtkTextBuffer中

我可以看到GTK+将西里尔字符存储在两个字节中(这让我有点困惑,我认为它存储的是UTF-8编码的字符,因此每个字符都必须在一个字节中?)

这导致了一个问题-我正在扫描循环中作为字符串的文本,我需要根据循环中的索引引用相应的字符位置,但是它们不再具有相应的索引,因为文本包含西里尔文。字符数为8310,字符串大小约为11300

如果我在正在扫描的字符串上使用
g\u str\u to_ascii()
,稍后,当我在树状视图小部件上显示字符串的某些内容时,它会将西里尔字符显示为
s

我该如何避开这个问题


如果我放置西里尔字母字符,这将打印出
[1][2]
,如果我分别放置两个西里尔字母字符,这将打印出
[2][4]

这些是西里尔字母“а”(char/dec)的字节:


您想做什么还不完全清楚,但是如果您只需要一次处理一个Unicode字符的整个UTF-8字符串,这些函数可能会有所帮助,请参见例如g_UTF_next_char()和g_UTF_get_char()

这不会改变字符是Unicode的事实,因此可能是多字节字符


如果您的目标是能够基于匹配的单词修改缓冲区,那么您应该查看GtkTextIter API:作为一个示例,您可以使用它来获取可以直接在GtkTextBuffer API中使用的开始和结束ITER。这样你就不需要处理实际的字符或字节索引。

这里有一个关于UTF-8的误解:它是一种可变长度编码(每个字符1-4字节),这就是你看到的原因。@jku我明白了。我的专业领域不是编码,我确实很困惑。我认为它是UTF-8,它是一种字节长度编码:)但是如果我最后不解决这个问题,我将不得不创建一个西里尔字母到拉丁字母的音译器,并用拉丁字母替换西里尔字母。UTF-8可以使用1到4个字节来编码字符。一个选项:您可以将UTF-8缓冲区转换为UTF-16,并使用后者的索引。换句话说,想象字符串“Hello World”,并将其设置在gtk文本缓冲区上。我想从索引6中获取文本缓冲区中“W”的字符位置。这是编码问题。直接访问索引6处的字符是不可能的(除了通过所有字符并在索引6处停止的代码)。。。。但我认为,如果你解释你真正想要实现的目标,可能还有其他解决方案:你为什么要这样做?索引6从何而来?我已经解释过我正在扫描文本缓冲区的内容作为字符串。假设我想匹配某个单词并在文本缓冲区中选择它。我不认为你解释说你实际上想匹配某个单词并在缓冲区中选择它:)好的,通过正确的处理和使用
GtkTextIter
API,我做到了。我希望不会慢很多。
G_MODULE_EXPORT void on_textbuffer_changed (GtkTextBuffer* textbuffer, gpointer user_data)
{
    GtkTextIter start   = {0};
    GtkTextIter end     = {0};
    gchar*      text    = NULL;

    gtk_text_buffer_get_bounds(textbuffer, &start, &end);

    text = gtk_text_buffer_get_text(textbuffer, &start, &end, FALSE);

    printf("[%i][%i]\n", gtk_text_buffer_get_char_count(textbuffer), strlen(text));

    g_free(text);
}