如何将 C 字符数组中的变音符号转换为十六进制代码?
How to convert umlauts in a C char array to hex codes?
我的任务是将包含多个变音符号的字符数组转换为具有相应 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 != '[=10=]'; ++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 风格的字符数组和指针来完成?
(除了 C++ input/output 流,我只被允许使用基本的 C)
我什至可以简单地覆盖变音符号,还是应该在循环时直接输出字符并在必要时替换它们? 我更喜欢先尝试第一种方法
我猜当你说“我想将变音符号转换成十六进制代码”时,你的意思是你想要字符串的 C 字符串表示,其中一些字符被编码为转义序列。
让我们这样做并处理以下字符:
- 基本转义序列:制表符(
\t
)等特殊字符编码为反斜杠加一个字母。
- hex escape characters: 所有其他不在 32 到 127 有效 ASCII 范围内的字符被编码为像
\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 = '[=10=]';
puts(encoded);
return 0;
}
在使用 Latin1 (ISO-8859-1) 编码的语言环境中,这将打印:
\"Fix Schwyz!\" qu\xe4kt J\xfcrgen bl\xf6d vom Pa\xdf.\r\n
在 UTF-8 区域设置中,您应该看到每个非 ASCII 字符都有 hwo 转义十六进制代码。
注意事项:
- 对于此解决方案,您不需要知道变音符号的确切代码,它们只是“非 ASCII”,就像其他重音字符或外来字符一样。
- 这个解决方案不关心编码,只要给定一串字符即可。
- 您的原始代码是 C++,因此您可以创建一个
std::string
并附加到它,而不是自己进行繁琐的分配计算。
你的问题不是很友好,因为它没有直接给出重要的东西。我可以从细节中猜到大部分:
您的 ASCII ANSI table 表明您需要 Window 代码页 850 编码以下字符 ÄäÖöÜüß
似乎每个变音符号由数组中的 2 个字符组成(均为负值):这意味着您的源文件当前是 UTF-8 编码的。
这是您需要的翻译table:
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 != '[=11=]'; ++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 系统上的 CP850 控制台中,我得到了预期的结果:
├ä├ñ├û├Â├£├╝├ƒ
ÄäÖöÜüß
我的任务是将包含多个变音符号的字符数组转换为具有相应 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 != '[=10=]'; ++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 风格的字符数组和指针来完成?
(除了 C++ input/output 流,我只被允许使用基本的 C)
我什至可以简单地覆盖变音符号,还是应该在循环时直接输出字符并在必要时替换它们? 我更喜欢先尝试第一种方法
我猜当你说“我想将变音符号转换成十六进制代码”时,你的意思是你想要字符串的 C 字符串表示,其中一些字符被编码为转义序列。
让我们这样做并处理以下字符:
- 基本转义序列:制表符(
\t
)等特殊字符编码为反斜杠加一个字母。 - hex escape characters: 所有其他不在 32 到 127 有效 ASCII 范围内的字符被编码为像
\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 = '[=10=]';
puts(encoded);
return 0;
}
在使用 Latin1 (ISO-8859-1) 编码的语言环境中,这将打印:
\"Fix Schwyz!\" qu\xe4kt J\xfcrgen bl\xf6d vom Pa\xdf.\r\n
在 UTF-8 区域设置中,您应该看到每个非 ASCII 字符都有 hwo 转义十六进制代码。
注意事项:
- 对于此解决方案,您不需要知道变音符号的确切代码,它们只是“非 ASCII”,就像其他重音字符或外来字符一样。
- 这个解决方案不关心编码,只要给定一串字符即可。
- 您的原始代码是 C++,因此您可以创建一个
std::string
并附加到它,而不是自己进行繁琐的分配计算。
你的问题不是很友好,因为它没有直接给出重要的东西。我可以从细节中猜到大部分:
您的 ASCII ANSI table 表明您需要 Window 代码页 850 编码以下字符 ÄäÖöÜüß
似乎每个变音符号由数组中的 2 个字符组成(均为负值):这意味着您的源文件当前是 UTF-8 编码的。
这是您需要的翻译table:
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 != '[=11=]'; ++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 系统上的 CP850 控制台中,我得到了预期的结果:
├ä├ñ├û├Â├£├╝├ƒ
ÄäÖöÜüß