关于utf 8:使用getchar()在C语言中进行UTF-8编码

UTF-8 encoding in C with getchar()

我必须编写一个代码,用UTF-8编码字符并将它们"翻译"成Unicode。您可以在这里查看什么是utf-8 https://en.wikipedia.org/wiki/utf-8。我是C初学者,因此我有三个限制:

  • 我必须使用getchar()
  • 禁止使用阵列
  • 我只对1、2、3和4字节的Unicode字符感兴趣
  • 所以我有一个完全能用4字节的代码(我知道我必须对每个getchar();使用!= EOF,但现在这不是我的问题)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    #include <stdio.h>

    int main(void) {
            int ch1, ch2, ch3, ch4, c;
            ch1 = getchar();
            ch2 = getchar();
            ch3 = getchar();
            ch4 = getchar();
            if ((ch1 & 0xF8) != 0xF0 || (ch2 & 0xC0) != 0x80 ||
                            (ch3 & 0xC0) != 0x80 || (ch4 & 0xC0) != 0x80) {
                    printf("Error in UTF-8 4-byte encoding
    "
    );
                    return 1;
            }
            c = ((ch1 & 0x07) << 18) | ((ch2 & 0x3F) << 12) |
                            ((ch3 & 0x3F) << 6) | (ch4 & 0x3F);
            printf("c = %05X
    "
    , c);
            return 0;
    }

    我的问题是:我不明白如何使用getchar()来处理1-2-3字节。我的意思是,我必须先阅读所有的getchar函数,然后用ch1来表示1字节字符,用ch1ch2来表示2字节字符,否则我必须这样做。(顺便说一句,下面的代码是不起作用的,它给了我一个无限的循环;我只是用它作为我思想的一个例子。)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    #include <stdio.h>

    int main (void) {
            int ch1, ch2, ch3, ch4, c;

            if (c >=0x0000 && c<=0x007F ){
                 ch1=getchar();
                while (ch1 !=EOF){
                    if ((ch1 & 0x80) != 0x00) {
                        printf("Error in UTF-8 1-byte encoding
    "
    );
                        return 1;  
                       }
                     c = ((ch1 & 0x80) << 7);
                     printf("c = %05X
    "
    , c);
                    }
            }


    你不能先读四个字符,然后决定怎么做。如果字符是在0x00-0x7f中,则将丢弃其余的字符,或者必须以更困难的方式处理它们。

    正确的方法是读一个字符。它将告诉您需要多少额外的字符,如果有的话,基于最重要的位是1。然后读取额外的字符,并转换为适当的Unicode码位,通过移动和忽略最重要的位在需要时。

    您可以检查链接到的文档,以查看Unicode代码点的位是如何分布到几个字节的。以下是算法的简要说明:

      百万千克1读取一个字节百万千克1百万千克1如果最上面的位为零,则无需执行其他操作:代码点为0x00-0x7F百万千克1百万千克1如果最上面的三个位是110,则需要另外一个字节。从第一个字节中取五个最低的位,将它们左移六位,或从第二个字节中移到最低的六位,得到最终值。百万千克1百万千克1如果最上面的四位是1110,则需要两个额外的字节。取第一个字节的四个最低位,移动12位,或从第二个字节移动6位的六个最低位,最后是第三个字节的六个最低位。百万千克1百万千克1如果最上面的五位是11110,那么您需要三个额外的字节,并像以前一样读取它们、移位等。百万千克1百万千克1如果这些条件都不符合,则数据无效百万千克1百万千克1请注意,当读取额外的字节时,这些字节必须将10作为最重要的位;任何其他的都是无效的。百万千克1

    更低的代码甚至不起作用,因为c从未给定值,所以if条件将不定义。它也不能正确地检查字节,因此代码对您没有太大帮助。