如何将C字符数组中的变音转换为十六进制代码?

xdnvmnnf  于 2023-05-28  发布在  其他
关注(0)|答案(2)|浏览(128)

我的任务是将一个包含多个变音符号的字符数组转换为一个对应ANSI十六进制代码的字符数组,以便在终端中正确显示。
ASCII ANSI

  • 'ī0x8E
  • 0x84
  • 'Ö' 0x99
  • 'ö' 0x94
  • 'Ü' 0x9A
  • 'ü' 0x81
  • 'ß' 0xE1

我的尝试看起来像这样:

#include <iostream>

using namespace std;

int main()
{
    char lied[] = "ÄäÖöÜüß\r\n";  // this syntax must remain the same

    cout << lied << endl;

    for (char* p = lied; *p != '\0'; ++p)
    {
        char c;
        switch (*p)
        {
        case 'Ä': c = '\x8e'; break;
        case 'ä': c = '\x84'; break;
        case 'Ö': c = '\x99'; break;
        case 'ö': c = '\x94'; break;
        case 'Ü': c = '\x9a'; break;
        case 'ü': c = '\x81'; break;
        case 'ß': c = '\xe1'; break;
        default:
            c = *p;
            break;
        }

        *p = c;
    }
    
    cout << lied << endl;
}

显然我的解决方案不起作用,因为我发现字符不能以这种方式进行比较。看起来每个变音符号都由数组中的2个字符组成(这两个字符都有负值)。如果我是对的,变音符号需要被解释为无符号字符,因为它们需要更多的内存来表示额外的符号。如何使用C风格的char数组和指针来实现这一点?

  • (我只允许使用基本的C,除了C++输入/输出流)*

我可以简单地覆盖变音符号吗?或者我应该在循环时直接输出字符并在必要时替换它们吗?* 我宁愿先试试第一种方法 *

e37o9pze

e37o9pze1#

你的问题并不友好,因为它没有直接给予重要的内容。我可以从细节中猜到:
您的 ASCII ANSI 表显示您需要Windows代码页850编码以下字符ÄäÖöÜüß

  • 看起来每个变音符号都由数组中的2个字符组成(都有负值)*:这意味着您的源文件当前是UTF-8编码的。

下面是你需要的转换表:

char      utf-8   cp850
    Ä  "\xc3\x84"  "\x8e"
    ä  "\xc3\xa4"  "\x84"
    Ö  "\xc3\x96"  "\x99"
    ö  "\xc3\xb6"  "\x94"
    Ü  "\xc3\x9c"  "\x9a"
    ü  "\xc3\xbc"  "\x81"
    ß  "\xc3\x9f"  "\xe1"

我把你的代码改成:

#include <iostream>

using namespace std;

int main()
{
    char lied[] = "ÄäÖöÜüß\r\n";  // this syntax must remain the same

    cout << lied << endl;

    int second = 0;

    char *q = lied;
    for (char* p = lied; *p != '\0'; ++p)
    {
        if (*p == '\xc3') {
            second = 1;
        }
        else if (second) {
            char c;
            second = 0;
            switch (*p)
            {
            case '\x84': c = '\x8e'; break;
            case '\xa4': c = '\x84'; break;
            case '\x96': c = '\x99'; break;
            case '\xb6': c = '\x94'; break;
            case '\x9c': c = '\x9a'; break;
            case '\xbc': c = '\x81'; break;
            case '\x9f': c = '\xe1'; break;
            default:
                c = *p;
                break;
            }
            *q++ = c;
        }
        else {
            *q++ = *p;
        }
    }
    *q = 0;

    cout << lied << endl;
    return 0;
}

在Windows系统上的CP 850控制台中,我得到了预期的结果:

├ä├ñ├û├Â├£├╝├ƒ

ÄäÖöÜüß
tyky79it

tyky79it2#

我猜,当你说“我想把变音转换成十六进制代码”时,你的意思是你想要一个C字符串表示的字符串,其中一些字符被编码为转义序列。
让我们这样做,并处理以下字符:

  • 基本转义序列:像tab(\t)这样的特殊字符被编码为反斜杠加一个字母。
  • 十六进制转义字符:所有其他不在有效ASCII范围(32到127)内的字符都被编码为类似\xc0的序列。

这些转义会使字符串更长,因此无法就地编码字符串。创建另一个字符串,该字符串的长度至少是原始字符串长度的四倍,加上空终止符的一倍。
现在迭代原始字符串并进行转换:

#include <stdio.h>

int main(void)
{
    char lied[] = "\"Fix Schwyz!\" quäkt Jürgen blöd vom Paß.\r\n";
    char encoded[4 * sizeof(lied)];
    
    const char *p = lied;
    char *q = encoded;
    
    while (*p) {
        unsigned char c = *p++;
        
        switch (c) {
        case '"':   *q++ = '\\'; *q++ = '"'; break;
        case '\r':  *q++ = '\\'; *q++ = 'r'; break;
        case '\n':  *q++ = '\\'; *q++ = 'n'; break;
        case '\t':  *q++ = '\\'; *q++ = 't'; break;
        case '\a':  *q++ = '\\'; *q++ = 'a'; break;
        case '\b':  *q++ = '\\'; *q++ = 'b'; break;
        
        default:    if (c < 32 || c > 127) {
                        static const char *hex = "0123456789abcdef";
        
                        *q++ = '\\';
                        *q++ = 'x';
                        *q++ = hex[c / 16];
                        *q++ = hex[c % 16];
                    } else {
                        *q++ = c;
                    }
        }
    }
    
    *q = '\0';
    
    puts(encoded);
    
    return 0;
}

在使用Latin 1(ISO-8859-1)编码的区域设置中,这将打印:

\"Fix Schwyz!\" qu\xe4kt J\xfcrgen bl\xf6d vom Pa\xdf.\r\n

在UTF-8语言环境中,您应该看到每个非ASCII字符有两个转义十六进制代码。
注意事项:

  • 对于这种解决方案,您不需要知道变音符号的确切代码,它们只是“非ASCII”,就像其他重音字符或外国字符一样。
  • 这个解决方案不关心编码,只要给它一个字符串。
  • 您的原始代码是C++,因此您可以创建一个std::string并追加到它,而不是自己进行繁琐的分配计算。

相关问题