当前位置: C语言 -- 标准库 -- <wchar.h> -- vwscanf

vwscanf函数


概要:
#include <stdarg.h>
#include <wchar.h>
int vwscanf(const wchar_t * restrict format, 
      va_list arg);

描述:

vwscanf函数等价于wscanf函数,区别在于vwscanf函数使用va_list类型参数arg替换可变参数列表。参数arg应已经使用宏va_start初始化(以及后续可能调用宏va_arg。);但vwscanf函数不会调用va_end宏。

该函数从标准输入流中读取输入,参数format指向的宽字符串用于指定允许的输入序列以及如何转换输入序列用于赋值。

格式序列由0至多个指令构成,函数调用时按顺序执行格式序列中的指令。当所有指令执行完或者某个指令执行失败,函数将返回。函数调用失败分为两种情况:输入失败(input failures)和匹配失败(matching failures)。输入失败是由于发生编码错误或者输入字符不可用引起的;匹配失败是由于输入不当引起的。

如果格式序列对应的参数数量不足,函数行为是未定义的;如果参数数量过多,多余参数会被评估,否则将被忽略。

ISO/IEC 9899:2018标准定义了该函数的安全版本vwscanf_s函数。


参数:
const wchar_t * restrict format

指向格式字符串的指针。格式字符串应为宽字符序列;构成格式序列的指令分为以下三种情况:

- 由空格宽字符(white-space wide character)构成的指令。

执行该指令时,函数从标准输入流中读取宽字符直至第一个非空格宽字符(第一个非空格宽字符不会被读取。),或者直至没有宽字符可以读取。空格宽字符可以使用iswspace函数验证。单个空格宽字符能够匹配从标准输入流中读取的一个或者多个空格宽字符。该指令永远不会失败。

:空格宽字符通常包括宽空格符(L' ')、宽换页符(L'\f')、宽换行符(L'\n')、宽回车符(L'\r')、宽水平制表符(L'\t')和宽垂直制表符(L'\v')。


- 由普通宽字符(宽字符%和空格宽字符除外)构成的指令。

执行该指令时,函数从标准输入流中读取宽字符,如果读取的宽字符与构成指令的宽字符不同,指令执行失败;不同宽字符以及其后字符保持未读取状态。如果到达文件末尾、发生编码错误或者读取错误导致无法读取字符,指令执行失败。


- 由转换说明构成的指令。

该指令定义了匹配的输入序列。该指令将按以下步骤执行:

除非转换说明包含[c或者n转换说明符,否则将跳过输入的空格宽字符。跳过的空格宽字符不计算在字段宽度内。

如果转换说明不包含转换说明符n,函数将从标准输入流中读取输入项(input item)。输入项是匹配的最长输入宽字符序列;在指定字段宽度的情况下,其长度不超过字段宽度。输入项后的第一个宽字符(如果存在的话。)保持未读取状态。如果输入项长度为0,指令执行失败。如果到达文件末尾、发生编码错误或者读取错误导致不能从流中读取输入,这类失败属于输入失败;否则将属于匹配失败。

除转换说明符为%的情况外,输入项将转换为与转换说明相对应类型。如果输入项不是匹配序列,指令执行失败;这种失败属于匹配失败。在未使用赋值屏蔽符*的情况下,转换结果将存储到format参数后、尚未接收转换结果的第一个参数指向的对象中。如果该对象不具备合适的类型,或者转换结果无法使用该对象表示,函数行为是未定义的。


转换说明遵循以下格式:

%赋值屏蔽符opt字段宽度符opt长度修饰符opt转换说明符

其中带opt的都是可选的。


1、赋值屏蔽符及其意义

赋值屏蔽符 描述
*

从标准输入流中读取数据,但该数据会被忽略;也就是说读取的数据不会被保存,例如:wscanf( L"%d%*lc%d", &one, &two);,假设输入是123a456,结果one的值为123two的值为456


2、字段宽度符及其意义

字段宽度符 描述
数字

该数字为大于0的十进制整数,用以指定最大字段宽度(宽字符形式)。


3、长度修饰符及其意义

长度修饰符 描述
hh

对于diouxXn转换说明符,该字符用于指向signed char或者unsigned char类型对象的指针参数。

h

对于diouxXn转换说明符,该字符用于指向short int或者unsigned short int类型对象的指针参数。

l

对于diouxXn转换说明符,该字符用于指向long int或者unsigned long int类型对象的指针参数。对于aAeEfFgG转换说明符,该字符用于指向double类型对象的指针参数。对于cs[转换说明符,该字符用于指向wchar_t类型对象的指针参数。

ll

对于diouxXn转换说明符,该字符用于指向long long int或者unsigned long long int类型对象的指针参数。

j

对于diouxXn转换说明符,该字符用于指向intmax_t或者uintmax_t类型对象的指针参数。

z

对于diouxXn转换说明符,该字符用于指向size_t或者对应的有符号整数类型对象的指针参数。

t

对于diouxXn转换说明符,该字符用于指向ptrdiff_t或者对应的无符号整数类型对象的指针参数。

L

对于aAeEfFgG转换说明符,该字符用于指向long double类型对象的指针参数。

如果长度修饰符与除上面指定的转换说明符一起使用,其行为是未定义的。


4、转换说明符及其意义

转换说明符 描述
d

匹配符号可选的十进制整数,其格式与基数为10wcstol函数主题序列的预期格式相同。对应参数应为指向有符号整数的指针。

i

匹配符号可选的八进制、十进制或者十六进制整数,其格式与基数为0wcstol函数主题序列的预期格式相同。对应参数应为指向有符号整数的指针。

o

匹配符号可选的八进制整数,其格式与基数为8wcstoul函数主题序列的预期格式相同。对应参数应为指向无符号整数的指针。

u

匹配符号可选的十进制整数,其格式与基数为10wcstoul函数主题序列的预期格式相同。对应参数应为指向无符号整数的指针。

x

匹配符号可选的十六进制整数,其格式与基数为16wcstoul函数主题序列的预期格式相同。对应参数应为指向无符号整数的指针。

a、e、f、g

匹配符号可选的浮点数、无穷大或者非数值,其格式与wcstod函数主题序列的预期格式相同。对应参数应为指向浮点数的指针。

c

匹配由字段宽度指定长度的宽字符序列;如果不存在字段宽度符,字段宽度为1

如果不存在l长度修饰符,输入字符就像反复调用wcrtomb函数一样被转换,第一个宽字符转换前,将mbstate_t对象描述的转换状态初始化为0。对应参数应为一个指向字符数组初始元素的指针,并且指向的字符数组足以容纳生成的字符序列,不会在数组末尾添加空字符。

如果存在l长度修饰符,对应参数应为一个指向wchar_t类型数组初始元素的指针,并且指向的数组足以容纳宽字符序列,不会在数组末尾添加空宽字符。

s

匹配非空格宽字符序列。

如果不存在l长度修饰符,输入字符就像反复调用wcrtomb函数一样被转换,第一个宽字符转换前,将mbstate_t对象描述的转换状态初始化为0。对应参数应为一个指向字符数组初始元素的指针,并且指向的字符数组足以容纳生成的字符序列和终止空字符(终止空字符会被自动添加。)。

如果存在l长度修饰符,对应参数应为一个指向wchar_t类型数组初始元素的指针,并且指向的数组足以容纳宽字符序列和终止空宽字符(终止空宽字符会被自动添加。)。

[

匹配非空宽字符序列,该序列中的宽字符均来源于指定字符集合(扫描集)。

如果不存在l长度修饰符,输入字符就像反复调用wcrtomb函数一样被转换,第一个宽字符转换前,将mbstate_t对象描述的转换状态初始化为0。对应参数应为一个指向字符数组初始元素的指针,并且指向的字符数组足以容纳生成的字符序列和终止空字符(终止空字符会被自动添加。)。

如果存在l长度修饰符,对应参数应为一个指向wchar_t类型数组初始元素的指针,并且指向的数组足以容纳宽字符序列和终止空宽字符(终止空宽字符会被自动添加。)。

该转换说明符包括format字符串中的所有后续宽字符,直至并包括匹配的右括号]。括号间的宽字符([]之间的宽字符)构成指定字符集合(扫描集)。如果左括号([)后是^符号,指定字符集合(扫描集)包括除^]之间字符以外的所有宽字符。如果转换说明符以[]或者[^]开头,右括号(])将包含在指定字符集合(扫描集)中,下一个右括号(])则是结束转换说明符的右括号(]);否则第一个右括号(])则是结束转换说明符的右括号(])。对于宽字符-,如果不属于[-[^--]这些情况,其行为将由实现定义。

p

匹配实现定义的序列集,该序列集与vwprintf函数%p转换说明生成的序列集相同。对应参数应为void *类型指针。输入项以实现定义的方式转换为指针值。如果输入项是同一程序执行期间较早的转换值,则结果指针应等于该值;否则%p转换说明行为是未定义的。

n

没有输入被消耗。对应参数应为一个指向有符号整数的指针,通过调用此函数从标准输入流中读取的宽字符数将写入该整数。对于该转换说明符,没有参数被转换,但消耗一个参数。执行%n指令不会增加函数执行完成时返回的赋值总数。如果转换说明包含字段宽度符或者赋值屏蔽符,其行为是未定义的。

%

匹配单个%宽字符;不会发生转换或者赋值。完整转换说明应为%%


长度修饰符、转换说明符和对应的参数类型如下表所示:

d i u o x a e f g c s [] [^] p n
int * unsigned int * float * char * void ** int *
hh signed char * unsigned char * signed char *
h short int * unsigned short int * short int *
l long int * unsigned long int * double * wchar_t * long int *
ll long long int * unsigned long long int * long long int *
j intmax_t * uintmax_t * intmax_t *
z size_t * size_t * size_t *
t ptrdiff_t * ptrdiff_t * ptrdiff_t *
L long double *

该处类型为指向与size_t类型对应的有符号整数的指针类型。

该处类型为指向与size_t类型对应的有符号整数的指针类型。

该处类型为指向与ptrdiff_t类型对应的无符号整数的指针类型。


如果转换说明无效,函数行为是未定义的。

字符AEFGX都是有效的转换说明符,其行为与对应的aefgx转换说明符相同。

除非与指令匹配,否则尾随空格(包括换行符)将保持未读取状态。文字匹配和赋值屏蔽是否成功只能通过%n指令来确定。


va_list arg

va_list类型对象。


返回值:

如果第一次转换(如果存在。)完成前发生输入失败,函数返回宏EOF;否则函数返回赋值的输入项数目。如果发生匹配失败,赋值的输入项数目可能会小于提供的输入项数目,甚至为0


范例:
1 
2 
3 
4 
5 
6 
7 
8 
9 
10 
11 
12 
13 
14 
15 
16 
17 
18 
19 
20 
21 
22 
23 
24 
25 
26 
27 
28 
29 
30 
31 
32 
33 
34 
35 
36 
37 
/*函数vwscanf范例*/

#include <locale.h>
#include <stdarg.h>
#include <wchar.h>

#define LENGTH 256

int getCharacter(const wchar_t *format, ...)
{
    va_list args;
    va_start(args, format);
    vwscanf(format, args);
    va_end(args);

    return 0;
}

int main(void)
{
    setlocale(LC_ALL, "");

    wchar_t character[LENGTH];
    int count = 0;

    wprintf(L"输入一段文字:");
    do
    {
        getCharacter(L"%lc", (character + count));
    }while(character[count++] != L'\n');

    for(int i=0; i<(count - 1); ++i)
        wprintf(L"character[%d]: %lc\n", i, character[i]);

    return 0;
}


结果:

假设键盘输入为:

中秋节

将输出:

character[0]:中

character[1]:秋

character[2]:节

:使用Visual Studio编译。


相关内容:
vfwscanf 从流中读取输入的函数。
vswscanf 从数组中读取输入的函数。