我正在用 C 语言制作一个字符转换器。
逻辑上非常简单:您键入一个字符,程序会检测到该字符并将其替换为新字符串中与其关联的其他字符。
在项目过程中,我现在遇到了两个问题:
void ReadString()
{
scanf("%s", inpString);
for(int i = 0; i <= strlen(inpString); i++)
{
ConvertChars(inpString);
}
PrintString();
}
void ConvertChars(char *convertedChars[])
{
if(strpbrk(convertedChars, "ཀ"))
{
strcpy(outString, "!");
}
if(strpbrk(convertedChars, "ཁ"))
{
strcpy(outString, "\"");
}
}
每当我输入
"ཀ"
或 "ཁ"
时,输出始终相同("
代表 "ཁ"
)。
由于某种原因,
for
循环似乎不起作用,因为它从不输出两个或多个转换后的字符,只输出一个(尽管在inpString
中输入了两个或多个字符)。
什么可能导致这些问题?
这个问题没有指定
ཀ
或 ཁ
的编码,因此计算机的含义是开放式的。但是,它可能是 UTF-8,用 U+0F40
表示 unicode 代码点 e0 bd 80
,用 U+0F41
表示 e0 bd 81
。即使您修复了逻辑错误,strpbrk
也会逐字节拆分,因此不适合多字节序列。
如果您需要从 UTF-8 转换某些字符,一种方法是使用状态机。
#include <stdlib.h>
#include <stdio.h>
int main(void) {
unsigned char buf[1024], out[sizeof buf];
size_t n;
enum { UTF_ONE_BYTE, UTF_TWO_BYTES, UTF_THREE_BYTES } state = UTF_ONE_BYTE;
do {
n = fread(buf, 1, sizeof buf, stdin);
size_t o = 0;
for(size_t i = 0; i < n; i++) {
const unsigned char cursor = buf[i];
switch(state) {
case UTF_ONE_BYTE:
switch(cursor) {
case 0xe0: state = UTF_TWO_BYTES; break; /* May be translated? */
default: out[o++] = cursor; break;
}
break;
case UTF_TWO_BYTES:
switch(cursor) {
case 0xbd: state = UTF_THREE_BYTES; break;
default: /* Nope, catch up. */
out[o++] = 0xe0; out[o++] = cursor; state = UTF_ONE_BYTE; break;
}
break;
case UTF_THREE_BYTES:
switch(cursor) {
case 0x80: out[o++] = '!'; break;
case 0x81: out[o++] = '\"'; break;
default: /* Not a translated character. */
out[o++] = 0xe0; out[o++] = 0xbd; out[o++] = cursor; break;
}
state = UTF_ONE_BYTE; break;
}
}
fwrite(out, 1, o, stdout);
} while(n == sizeof buf);
return ferror(stdin) ? (perror("stdin"), EXIT_FAILURE) : EXIT_SUCCESS;
}