C++ 从UTF-8到ANSI wcstombs的转换在一个特定字符处失败

C++ 从UTF-8到ANSI wcstombs的转换在一个特定字符处失败,c++,utf-8,wchar-t,wchar,C++,Utf 8,Wchar T,Wchar,我想将wchar\u t*更改为char*。 不应进行WideChartMultiByte中的转换 我找到了wcstombs函数,它看起来工作得很好,但是有一个字符没有得到正确的更改 它是“œ”,具有ANSI编号156,但在UTF-8中是编号339。 当然,ASCII没有那么多数字,但为什么它会得到错误的数字呢 这里是我源代码的一部分,我添加了一个循环和一个if,这样它就可以工作了: wchar_t *wc; // source string char *cc;

我想将wchar\u t*更改为char*。 不应进行WideChartMultiByte中的转换

我找到了wcstombs函数,它看起来工作得很好,但是有一个字符没有得到正确的更改


它是“œ”,具有ANSI编号156,但在UTF-8中是编号339。 当然,ASCII没有那么多数字,但为什么它会得到错误的数字呢

这里是我源代码的一部分,我添加了一个循环和一个if,这样它就可以工作了:

    wchar_t *wc;    // source string
    char *cc;       // destination string
    int len = 0;    // length of the strings

    ...

    for(int i = 0; i < len; i++) {
            if(wc[i] != 339) {
                    cc[i] = wc[i];
            }else{
                    cc[i] = 156;
            }
    }   
wchar\u t*wc;//源字符串
char*cc;//目标字符串
int len=0;//弦长
...
对于(int i=0;i
这段代码正在运行,但说真的,这是解决这个问题的最佳方法吗


非常感谢

请容忍我对c/c++的完全无知,但您可以使用自定义查找表 或者一些预制函数

这里是一个256个整数的数组,其中索引
i
包含Windows-1252的unicode码点 代码点
i

例如,索引
156
,包含
0x0153
,它是十进制的
339

int[] windows1252ToUnicodeCodePoints = {
         0x0000,0x0001,0x0002,0x0003,0x0004,0x0005,0x0006,0x0007,0x0008,0x0009,0x000A,0x000B,0x000C,0x000D,0x000E,0x000F
        ,0x0010,0x0011,0x0012,0x0013,0x0014,0x0015,0x0016,0x0017,0x0018,0x0019,0x001A,0x001B,0x001C,0x001D,0x001E,0x001F
        ,0x0020,0x0021,0x0022,0x0023,0x0024,0x0025,0x0026,0x0027,0x0028,0x0029,0x002A,0x002B,0x002C,0x002D,0x002E,0x002F
        ,0x0030,0x0031,0x0032,0x0033,0x0034,0x0035,0x0036,0x0037,0x0038,0x0039,0x003A,0x003B,0x003C,0x003D,0x003E,0x003F
        ,0x0040,0x0041,0x0042,0x0043,0x0044,0x0045,0x0046,0x0047,0x0048,0x0049,0x004A,0x004B,0x004C,0x004D,0x004E,0x004F
        ,0x0050,0x0051,0x0052,0x0053,0x0054,0x0055,0x0056,0x0057,0x0058,0x0059,0x005A,0x005B,0x005C,0x005D,0x005E,0x005F
        ,0x0060,0x0061,0x0062,0x0063,0x0064,0x0065,0x0066,0x0067,0x0068,0x0069,0x006A,0x006B,0x006C,0x006D,0x006E,0x006F
        ,0x0070,0x0071,0x0072,0x0073,0x0074,0x0075,0x0076,0x0077,0x0078,0x0079,0x007A,0x007B,0x007C,0x007D,0x007E,0x007F
        ,0x20AC,0xFFFD,0x201A,0x0192,0x201E,0x2026,0x2020,0x2021,0x02C6,0x2030,0x0160,0x2039,0x0152,0xFFFD,0x017D,0xFFFD
        ,0xFFFD,0x2018,0x2019,0x201C,0x201D,0x2022,0x2013,0x2014,0x02DC,0x2122,0x0161,0x203A,0x0153,0xFFFD,0x017E,0x0178
        ,0x00A0,0x00A1,0x00A2,0x00A3,0x00A4,0x00A5,0x00A6,0x00A7,0x00A8,0x00A9,0x00AA,0x00AB,0x00AC,0x00AD,0x00AE,0x00AF
        ,0x00B0,0x00B1,0x00B2,0x00B3,0x00B4,0x00B5,0x00B6,0x00B7,0x00B8,0x00B9,0x00BA,0x00BB,0x00BC,0x00BD,0x00BE,0x00BF
        ,0x00C0,0x00C1,0x00C2,0x00C3,0x00C4,0x00C5,0x00C6,0x00C7,0x00C8,0x00C9,0x00CA,0x00CB,0x00CC,0x00CD,0x00CE,0x00CF
        ,0x00D0,0x00D1,0x00D2,0x00D3,0x00D4,0x00D5,0x00D6,0x00D7,0x00D8,0x00D9,0x00DA,0x00DB,0x00DC,0x00DD,0x00DE,0x00DF
        ,0x00E0,0x00E1,0x00E2,0x00E3,0x00E4,0x00E5,0x00E6,0x00E7,0x00E8,0x00E9,0x00EA,0x00EB,0x00EC,0x00ED,0x00EE,0x00EF
        ,0x00F0,0x00F1,0x00F2,0x00F3,0x00F4,0x00F5,0x00F6,0x00F7,0x00F8,0x00F9,0x00FA,0x00FB,0x00FC,0x00FD,0x00FE,0x00FF
};
您需要的是这个表的反转(或者每次进行线性扫描),在任何其他语言中,我都会使用类似于
Map
的构造

我想将wchar\u t*更改为char*

好的,您要将
wchar\u t
字符串转换为
char
字符串

不应进行WideChartMultiByte中的转换

什么?我想你不是说“不应该做任何转换”,但仅举一个例子,我无法说明你想要避免什么。只是
widecharttomultibyte
或者还有其他功能吗

我找到了wcstombs函数,它看起来工作得很好

wcstombs
对我来说似乎是
WideCharToMultibyte
,但我想它在某些方面是不同的,这对你很重要?如果您能描述一下是什么使得
wcstombs
可以接受,以及
WideCharToMultibyte
不能接受,那就太好了

但是有一个字符不能正确地更改

听起来好像不是很完美


它是“œ”,具有ANSI编号156,但在UTF-8中是编号339。当然,ASCII没有那么多数字,但为什么它会得到错误的数字呢

您可能的意思是,在CP1252中,“œ”被编码为十进制的156或十六进制的0x9C,并且该字符具有十进制的Unicode代码点339,或者更传统的U+0153。我根本不知道UTF-8是怎么回事

这里是我源代码的一部分,我添加了一个循环和一个if,这样它就可以工作了:

    wchar_t *wc;    // source string
    char *cc;       // destination string
    int len = 0;    // length of the strings

    ...

    for(int i = 0; i < len; i++) {
            if(wc[i] != 339) {
                    cc[i] = wc[i];
            }else{
                    cc[i] = 156;
            }
    }   
至于为什么没有得到预期的结果,可能是因为没有正确使用
wcstombs()
。很难说,因为您没有展示如何使用
wcstombs()
进行转换

wcstombs()
使用程序当前C语言环境指定的编码在
wchar\u t
char
之间进行转换。如果您已将区域设置设置为对
wchar\u t
使用Unicode编码,并对char使用CP1252,那么它应该会达到您的预期效果

这段代码正在运行,但说真的,这是解决这个问题的最佳方法吗


否。

您确定应该使用
字符而不是
无符号字符吗?当您为
char
分配一个高于其值的值,或者您正在询问
wcstombs
为什么可以生成无效的ascii值时,您期望得到什么?“但在UTF-8中,它是数字339。”这是错误的。您正在使用术语UTF-8来表示其他内容(UTF-16?Unicode?UTF-32?)。339是
œ
的Unicode码点(十进制)。UTF-8是一种编码,其中该字符将被编码为
0xC5 0x93
ANSI
在这种情况下,最有可能意味着代码页1252或Windows-1252您要求不使用WideChartMultiByte(),而是使用完全不可用的替代方法。您只发现了一个错误的转换,还有更多。不,这不是最好的方法。“ANSI”实际上是一个不正确的名字。