6

我正在编写一个 Excel 插件,需要wchar_t 为 Excel 生成输出(尽管在内部,我们是 100% char,实际上仅限char于纯 ASCII)。在某一时刻,我正在使用 swprintf进行转换:

static wchar_t buffer[ 32369 ];
buffer[0] = swprintf( buffer + 1, sizeof(buffer) - 1, L"#%s!", message );

Excel 显示某种 CJK 字符,尽管message (type char const*) 是一个以空字符结尾的字符串,在可打印的 ASCII 之外没有字符(十六进制值 0x20-0x7E)。

我在一个小型测试程序中尝试过这个,以十六进制转储生成的字符串,看起来 VC++ 将message 其视为一个wchar_t const*(尽管它似乎识别'\0'正确,尽管它在一个字节上);这导致wchar_t0x6568 (而不是0x0068, 0x0065我期望的)这样的值。

根据 C99 标准,对于"%s"说明符, swprintf应将字符从char const* “好像通过重复调用mbrtowc函数 [...]”转换。我看到的行为是 Visual C++ 库中的错误,还是我必须更改全局语言环境中的某些内容?

(FWIW:当我用 g++ 编译和运行我的小测试程序时,我得到了我期望的行为。但是,G++ 不是我们的 Excel 插件的选项,至少目前不是。)

4

2 回答 2

15

请注意,来自MSDN 的swprintf

swprintf 是 sprintf 的宽字符版本;swprintf 的指针参数是宽字符串。

然后在示例中:

wchar_t buf[100];
int len = swprintf( buf, 100, L"%s", L"Hello world" );

所以至少微软记录了这一点。

然后在格式说明符页面

s String 当与 printf 函数一起使用时,指定一个单字节字符串;当与 wprintf 函数一起使用时,指定一个宽字符串。字符被打印到第一个空字符或直到达到精度值。

进而

S String 当与 printf 函数一起使用时,指定一个宽字符串;当与 wprintf 函数一起使用时,指定一个单字节字符串。字符被打印到第一个空字符或直到达到精度值。

所以你想要的是大写%S

甚至看到这个类似的问题:visual studio swprintf 让我所有的 %s 格式化程序都想要 wchar_t * 而不是 char *他们建议使用的地方%ls(总是考虑参数wchar_t*)和%hs(总是考虑参数char*

于 2013-09-10T09:48:24.570 回答
2

调用swprintf说明符时, %s被解释为指向一个宽字符串,即 wchar_t 指针。而是使用%S(大写 S)格式说明符,因为这将正确使用char* message您传递的。

来自 Microsoft 关于 printf Type Field Characters 的文档:

  • s,字符串,与printf函数一起使用时,指定一个单字节字符串;当与wprintf函数一起使用时,指定一个宽字符串。字符被打印到第一个空字符或直到达到精度值。
  • S, String, When used with printf functions, specifies a wide-character string; when used with wprintf functions, specifies a single-byte–character string. Characters are printed up to the first null character or until the precision value is reached.
于 2013-09-10T09:50:56.237 回答