简体   繁体   English

将使用wscanf读取的宽字符串转换为C中的整数

[英]convert wide-character string read with wscanf to an integer in C

I am trying to convert a string read using wscanf to an integer using wcstol, both from header file wchar.h on Linux. 我试图将使用wscanf的字符串读取转换为使用wcstol的整数,两者都来自Linux上的头文件wchar.h。 While wcstol works on constant wide-char strings (eg L"23") it does not work on wscanf input, which puzzles me. 虽然wcstol在常量宽字符串(例如L“23”)上工作,但它对wscanf输入无效,这让我很困惑。 I always get 0, even if the input is actually numeric (eg 23). 我总是得到0,即使输入实际上是数字(例如23)。 Why? 为什么?

$ ./test 
23
s=23
0

Here is my test program: 这是我的测试程序:

#include <stdio.h>
#include <wchar.h>
int main() {
  wchar_t s[100];
  if (wscanf(L"%s", s) == 1) {
    wprintf(L"s=%s\n", s);
    wprintf(L"%ld\n", wcstol(s, NULL, 10));
  }
}

If instead of wcstol I use strtol, it works but I get this warning: 如果我使用strtol而不是wcstol,它可以工作,但我得到这个警告:

/usr/include/stdlib.h:183:17: note: expected 'const char * restrict' but argument is of type 'wchar_t * {aka int *}' /usr/include/stdlib.h:183:17:注意:预期'const char * restrict'但参数类型为'wchar_t * {aka int *}'

which I could silent using a type cast. 我可以使用类型演员沉默。 I thought wcstol was the right way to parse a wide-char string to an integer. 我认为wcstol是将宽字符串解析为整数的正确方法。 Since on my machine chars are actually ints, strtol happens to work, but that leaves me still unsure whether this is the right solution. 因为我的机器上的字符实际上是整数,所以strtol恰好起作用,但这让我仍然不确定这是否是正确的解决方案。 What's going on here? 这里发生了什么? Why wcstol does not do its job? 为什么wcstol没有做好自己的工作?

Your problem is with the wscanf() format. 你的问题是wscanf()格式。 A %s field descriptor designates a pointer to char , just like for scanf() . %s段描述符指定一个指向char的指针,就像scanf() These two functions differ a bit in how they convert the input, but they agree on the meaning of the field descriptors. 这两个函数在转换输入方面略有不同,但它们对字段描述符的含义达成一致。

For reading into an array of wchar_t , you want %ls . 要读入wchar_t数组,您需要%ls Moreover, whether you should use wscanf() of scanf() is primarily a function of how the input is encoded, not of the data type into which you want to scan its contents. 此外,是否应该使用scanf() wscanf()主要取决于输入的编码方式, 而不是您要扫描其内容的数据类型。

Your problem is the wscanf format. 你的问题是wscanf格式。

As described on MAN : MAN所述

s 小号

Matches a sequence of non white-space wide characters. 匹配一系列非空白宽字符。 [...] The application shall ensure that the corresponding argument is a pointer to a character array large enough to accept the sequence and the terminating null character, which shall be added automatically. [...]应用程序应确保相应的参数是一个指向大小足以接受序列和终止空字符的字符数组的指针,该字符应自动添加。

Simply "%s" must be used for non-wide-chars string, as usual in printf , scanf and so on 简单地说,“%s”必须用于非宽字符串,就像在printfscanf等中一样

MAN also says: MAN还说:

l (ell) l(ell)

Specifies that a following d, i, o, u, x, X, or n conversion specifier applies to an argument with type pointer to long or unsigned long; 指定以下d,i,o,u,x,X或n转换说明符适用于类型指针为long或unsigned long的参数; [...] that a following c, s, or [ conversion specifier applies to an argument with type pointer to wchar_t. [...]以下c,s或[转换说明符适用于具有指向wchar_t的类型指针的参数。

That means you must use "%ls" as format string to read a wide-char string. 这意味着您必须使用"%ls"作为格式字符串来读取宽字符串。

There is another non-standard ISO C solution if you are on POSIX or on .NET MSDN : format "%S" can be used. 如果您使用POSIX.NET MSDN,还有另一种非标准ISO C解决方案:可以使用格式"%S"

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM