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

vfwprintf函数


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

描述:

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

该函数将输出写入参数stream指向的流,参数format指向的宽字符串指定后续参数如何转换为输出。

格式序列由0至多个指令构成,函数调用时按顺序执行格式序列中的指令,执行到格式序列末尾时,函数将返回。

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

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


参数:
FILE * restrict stream

指向写入输出的流的指针。


const wchar_t * restrict format

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

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

普通宽字符不作任何改变写入输出流。


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

每个转换说明都会获取0至多个后续参数,并根据相应的转换说明符(如果适用)对其进行转换,然后将结果写入输出流。


转换说明遵循以下格式:

%标记符opt字段宽度符opt精度符opt长度修饰符opt转换说明符

其中带opt的都是可选的。


1、标记符及其意义

标记符 描述
-

转换结果在字段内左对齐。默认情况下是右对齐。

+

有符号的转换结果总是以+号或者-号开头。默认情况下正值前没有+号。

空格

如果一个有符号转换的首字符不是符号,或者一个有符号转换结果没有宽字符,将在结果前添加空格。如果在标记符中同时出现空格标记符和+标记符,空格标记符将被忽略。

#

对于o转换,当且仅在必要时,会增加精度以强制结果的第一位数字为0;如果值和精度均为0,则输出单个0。对于x(或者X)转换,将给非0结果前置0x(或者0X)。对于aAeEfFgG转换,结果将转换为带有小数点的浮点数,即使小数点后没有数字(通常小数点字符仅在其后有数字时才会出现在这些转换结果中。)。对于g(或者G)转换,尾随0会保留。对于其它形式转换,其行为是未定义的。

0

对于diouxXaAeEfFgG转换,前导0(跟在符号或者基数之后)将代替空格填充字段,转换无穷大或者非数值除外。如果在标记符中同时出现0标记符和-标记符,0标记符将被忽略。对于diouxX转换,如果指定了精度,0标记符将被忽略。对于其它形式转换,其行为是未定义的。

如果存在多个标记符,ISO/IEC 9899:2018标准并未指定标记符的先后顺序。


2、字段宽度符及其意义

字段宽度符 描述
数字

该数字为大于0的十进制整数,表示最小字段宽度。

*

该字符表示最小字段宽度,该字符并未直接指定字段宽度,需要在转换参数前有一个额外整值参数来指定字段宽度,例如:fwprintf(stdout, L"%*d", width, value);,其中参数width指定字段宽度。如果width是负整数,转换结果是左对齐的。

如果字段宽度为负值,就相当于使用其绝对值作为字段宽度,-字符作为标记符。

如果转换值含有的字符数小于字段宽度,默认情况下在转换值左边填充空格;如果转换值含有的字符数大于等于字段宽度,转换值正常输出。


3、精度符及其意义

精度符 描述
.数字

该数字为十进制整数。

.*

该字符未直接指定精度,需要在转换参数前有一个额外整值参数指定精度,例如:fwprintf(stdout, L"%.*f", precision, value);,其中参数precision指定精度。

对于diouxX转换,精度符表示出现的最小位数。对于aAeEfF转换,精度符表示小数点后出现的位数。对于gG转换,精度符表示最大有效位数。对于s转换,精度符表示写入的最大宽字符数。如果只指定.字符,精度值为0

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


4、长度修饰符及其意义

长度修饰符 描述
hh

对于diouxX转换说明符,该字符用于signed char或者unsigned char类型参数(参数会被整数提升,但在输出前参数值应转换为signed char或者unsigned char类型。)。对于n转换说明符,该字符用于signed char类型指针。

h

对于diouxX转换说明符,该字符用于short int或者unsigned short int类型参数(参数会被整数提升,但在输出前参数值应转换为short int或者unsigned short int类型。)。对于n转换说明符,该字符用于short int类型指针。

l

对于diouxX转换说明符,该字符用于long int或者unsigned long int类型参数。对于n转换说明符,该字符用于long int类型指针。对于c转换说明符,该字符用于wint_t类型参数。对于s转换说明符,该字符用于wchar_t类型指针。对于aAeEfFgG转换说明符,该字符不起作用。

ll

对于diouxX转换说明符,该字符用于long long int或者unsigned long long int类型参数。对于n转换说明符,该字符用于long long int类型指针。

j

对于diouxX转换说明符,该字符用于intmax_t或者uintmax_t类型参数。对于n转换说明符,该字符用于intmax_t类型指针。

z

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

t

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

L

对于aAeEfFgG转换说明符,该字符用于long double类型参数。

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


5、转换说明符及其意义

转换说明符 描述
d,i

int类型参数转换为有符号十进制整数。精度指定转换结果的最小位数。如果转换结果的位数小于精度值,将添加前导0。默认精度为1。精度为00值转换结果没有宽字符。(:转换说明符di对于格式化输出函数(例如:fwprintf函数)是没有区别的;对于格式化输入函数(例如:fwscanf函数)两者是有区别的。)

o,u,x,X

unsigned int类型参数转换为无符号的八进制整数(o)、十进制整数(u)或者十六进制整数(x或者X)。小写字母abcdef用作x转换;大写字母ABCDEF用作X转换。精度指定转换结果的最小位数。如果转换结果的位数小于精度值,将添加前导0。默认精度为1。精度为00值转换结果没有宽字符。

f,F

double类型参数转换为[-]ddd.ddd形式的十进制浮点数,其中小数点后位数等于精度值。如果没有指定精度,默认精度为6。如果精度为0,并且没有使用#标记符,将不会出现小数点。如果转换结果中出现小数点,小数点前至少有一位数。转换结果会被舍入到合适的位数。

如果double类型参数表示无穷大,是转换成[-]inf形式还是转换成[-]infinity形式将由实现定义。如果double类型参数表示非数值,是转换成[-]nan形式还是转换成[-]nan(n-wchar-sequence)形式,以及n-wchar-sequence的含义将由实现定义。f转换说明符对应infinfinity或者nanF转换说明符对应INFINFINITY或者NAN。(:当用于无穷大和非数值时,-+和空格标记符具有其通常的含义;但#0标记符没有影响。)

e,E

double类型参数转换为科学计数法形式([-]d.ddde±dd),其中小数点前有一位数,如果参数是非0值,该数也是非0值;小数点后位数等于精度值。如果没有指定精度,默认精度为6。如果精度为0,并且没有使用#标记符,将不会出现小数点。转换结果会被舍入到合适的位数。e转换说明符对应指数为eE转换说明符对应指数为E。指数位数至少为2位;并且仅包含表示指数所需的更多位数。如果参数值为0,指数为0

如果double类型参数表示无穷大,是转换成[-]inf形式还是转换成[-]infinity形式将由实现定义。如果double类型参数表示非数值,是转换成[-]nan形式还是转换成[-]nan(n-wchar-sequence)形式,以及n-wchar-sequence的含义将由实现定义。e转换说明符对应infinfinity或者nanE转换说明符对应INFINFINITY或者NAN。(:当用于无穷大和非数值时,-+和空格标记符具有其通常的含义;但#0标记符没有影响。)

g,G

double类型参数表示的浮点数是按e转换说明符还是按f转换说明符进行转换(对于G转换说明符,对应的是E转换说明符和F转换说明符。)取决于转换值和精度。声明一个变量P,如果精度值为非0值,P等于精度值;如果省略精度,P等于6;如果精度值为0P等于1。如果转换按E转换说明符进行转换,将有一个指数X

- 如果P>X≥-4,转换将按f(或者F)转换说明符进行转换,并且精度值为P-(X+1)

- 否则转换将按e(或者E)转换说明符进行转换,并且精度值为P-1

如果未使用#标记符,结果的小数部分将删除所有尾随0,并且如果不存在小数部分,将删除小数点。

如果double类型参数表示无穷大,是转换成[-]inf形式还是转换成[-]infinity形式将由实现定义。如果double类型参数表示非数值,是转换成[-]nan形式还是转换成[-]nan(n-wchar-sequence)形式,以及n-wchar-sequence的含义将由实现定义。g转换说明符对应infinfinity或者nanG转换说明符对应INFINFINITY或者NAN。(:当用于无穷大和非数值时,-+和空格标记符具有其通常的含义;但#0标记符没有影响。)

a,A

double类型参数表示的浮点数将转换成[-]0xh.hhhhp±d形式,其中小数点前有1位十六进制数(如果参数是规格化浮点数(normalized floating-point number),该十六进制数为非0值,否则其值是不确定的。);小数点后十六进制数的位数与精度值相同。如果没有指定精度并且FLT_RADIX2的幂,那么精度足以精确表示转换值。如果没有指定精度并且FLT_RADIX不是2的幂,那么精度足以区分double类型的值,但尾随0可能会被省略。如果精度为0,并且没有使用#标记符,将不会出现小数点。字母abcdef用于a转换;字母ABCDEF用于A转换。a转换的转换结果使用xpA转换的转换结果使用XP。指数位数至少为1位;并且仅包含表示2的十进制指数所需的更多位数。如果值为0,指数为0

如果double类型参数表示无穷大,是转换成[-]inf形式还是转换成[-]infinity形式将由实现定义。如果double类型参数表示非数值,是转换成[-]nan形式还是转换成[-]nan(n-wchar-sequence)形式,以及n-wchar-sequence的含义将由实现定义。a转换说明符对应infinfinity或者nanA转换说明符对应INFINFINITY或者NAN。(:当用于无穷大和非数值时,-+和空格标记符具有其通常的含义;但#0标记符没有影响。)

c

如果不存在l长度修饰符,int类型参数就像调用btowc函数一样转换为宽字符,并将结果宽字符写入输出流。

如果存在l长度修饰符,wint_t类型参数将转换为wchar_t类型,并写入输出流。

s

如果不存在l长度修饰符,参数应为指向字符数组初始元素的指针,该数组包含处于初始移位状态的多字节字符序列。数组中的字符就像反复调用mbrtowc函数一样转换为宽字符(第一个多字节字符转换前,描述转换状态的mbstate_t对象应初始化为0。),并将结果宽字符写入输出流直至终止空宽字符(但不包括终止空宽字符)。如果指定精度,写入的宽字符数不超过精度值。如果没有指定精度或者精度值大于转换后的数组长度,转换后的数组应包含一个空宽字符。

如果存在l长度修饰符,参数应为指向wchar_t类型数组初始元素的指针。数组中的宽字符将被写入输出流,直至终止空宽字符(但不包括终止空宽字符)。如果指定精度,写入的宽字符数不超过精度值。如果没有指定精度或者精度值大于数组长度,数组应包含一个空宽字符。

p

参数应为void类型指针。指针值转换为实现定义的打印宽字符序列。

n

参数应为一个指向有符号整数的指针,到目前为止通过调用vfwprintf函数写入到输出流的宽字符数将写入该整数。对于该转换说明符,没有参数被转换,但消耗一个参数。如果转换说明包含标记符、字段宽度符或者精度符,该转换说明符的行为是未定义的。

%

向输出流写入一个%宽字符。没有参数被转换。完整的转换说明为%%


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

d i u o x X a A e E f F g G c s p n
int unsigned int double int char * void * int *
hh signed char unsigned char signed char *
h short int unsigned short int short int *
l long int unsigned long int wint_t 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类型对应的无符号整数类型。


如果转换说明无效,函数行为是未定义的。如果参数不是转换说明所对应的类型,函数行为是未定义的。

任何情况下,不存在的或者较小的字段宽度都不会导致字段被截断;如果转换结果宽于字段宽度,字段会被扩展,以便包含转换结果。

对于a(或者A)转换,如果FLT_RADIX2的幂,转换值准确地舍入为具有指定精度的十六进制浮点数。


va_list arg

va_list类型对象。


返回值:

如果发生输出错误或者编码错误,函数返回一个负值;否则函数返回写入输出流的宽字符数。


范例:
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 
/*函数vfwprintf范例*/

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

static int count = 0;

void archives(const wchar_t *format, ...)
{
    wprintf(L"档案%d\n", ++count);

    va_list args;
    va_start(args, format);
    vfwprintf(stdout, format, args);
    va_end(args);

    putwchar('\n');
}

int main(void)
{
    setlocale(LC_ALL, "");
    
    archives(L"姓名: %ls\n", L"张三");
    archives(L"姓名: %ls\n性别:%lc\n", L"李四", L'');
    archives(L"姓名: %ls\n性别:%lc\n年龄:%d\n", L"王五", L'', 25);

    return 0;
}


输出:

档案1

姓名:张三

 

档案2

姓名:李四

性别:男

 

档案3

姓名:王五

性别:男

年龄:25


相关内容:
vwprintf 将输出写入标准输出流的函数。
vswprintf 将限定大小的输出写入数组的函数。