C语言的缺陷与陷阱 札记 - 八 其他

21 篇文章 0 订阅

printf 函数族  

       参考同目录下 《 printf, fprintf, sprintf, snprintf, vprintf, vfprintf, vsprintf, vsnprintf 函数族》

#include <stdio.h>

int printf(const char *format, ...);

int fprintf(FILE *stream, const char *format, ...);

int sprintf(char *str, const char *format, ...);

int snprintf(char *str, size_t size, const char *format, ...);

#include <stdarg.h>

int vprintf(const char *format, va_list ap);

int vfprintf(FILE *stream, const char *format, va_list ap);

int vsprintf(char *str, const char *format, va_list ap);

int vsnprintf(char *str, size_t size, const char *format, va_list ap);

printf 系列函数 根据  format 参数 生成 输出内容:

  • printf 和 vprintf 函数 把 输出内容 写到 stdout, 即 标准输出流; 

  • fprintf 和 vfprintf 函数 把 输出内容 写到 给定的 stream 流; 

  • sprintf, snprintf, vsprintf 和 vsnprintf 函数 把 输出内容 存放到 字符串 str 中.

TIP:

  • 格式字符串 format 参数控制输出内容, 它指出怎么样把后面的参数 (或 通过stdarg) 的变长参数机制访问的参数) 转换成输出内容;

这些 函数 返回 打印的 字符 数量 (不包括 字符串 结尾用的 `\0');

  •  snprintf 和 vsnprintf 的 输出 不会 超过 size 字节 (包括了 结尾的 `\0'), 如果因为这个限制导致 输出内容被截断, 则函数返回 -1;

  • 格式字符串 (format 参数) 由 零到多个 指令 组成: 普通字符 (除 % 外)被原封不动的送到输出流;

  • 每个格式转换说明都会从后面提取零到多个参数. 格式转换说明 由%字符引导开始. 参数必须正确的 对应到格式转换符 (conversion specifier) 上;

 

printf :

const char * format   -----   用于包含变参的格式数据

...                                -----   定位随后紧邻变参在调用栈上的存储位置

[用于告知编译器将format之后的其它参数依次压入调用栈;两者使用时必须依序先后紧邻。]

vprintf:

 va_list ap                 -----     一个后续会指向调用栈传递过来的变参的指针

                                        va_start(ap, format) 使用format来定位ap的指向,即传入的变参序列的首地址

----------------------------------------------------------------------------------------------------------------------------------------------

int vpf(char*fmt,...)

{

    va_list argptr;

    int cnt;

    va_start(argptr,fmt); //第一个参数为指向可变参数字符指针的变量,第二个参数是可变参数的第一个参数,通常用于指定可变

                          //参数列表中参数的个数

    cnt=vprintf(fmt,argptr);

    va_end(argptr);      //将存放可变参数字符串的变量清空

    return(cnt);

}

----------------------------------------------------------------------------------------------------------------------------------------------

fprintf:

vfprintf:

成功则输出字符数,出错为负值。

----------------------------------------------------------------------------------------------------------------------------------------------

 

void log(FILE *file, const char* format, ... )

{

    va_list args;

    va_start (args, format);

    fprintf(file, "%s: ", getTimestamp());

    vfprintf (file, format, args);        // 在这个地方用vfprintf函数就很合适,因为

                                          // 第三个参数可以直接得到

    va_end (args);

}

 

vfprintf适合参数可变列表传递。

----------------------------------------------------------------------------------------------------------------------------------------------

 

sprintf: 第一个参数是字符串缓冲区,后面是一个格式字串。sprintf不是将格式化结果标准输出,而是将其存入szBuffer。该函数返回该字符串的长度。

vsprintf:vsprintf 是sprintf 的一个变形,它有三个参数。vsprintf 用于执行有不定数量参数的函数。vsprintf的前两个参数与sprintf相同:一个用于保存结果的字符串缓冲区和一个格式化字符串。第三个参数是指向格式化参数队列的指针。实际上,该指针指向在堆栈中供函数调用的变量。va_list、va_start和va_end宏(在STDARG.H中定义)帮助我们处理堆栈指针.

----------------------------------------------------------------------------------------------------------------------------------------------

int sprintf (char * szBuffer, const char * szFormat, ...)

{

    int     iReturn ;

    va_list pArgs ;

    va_start (pArgs, szFormat) ;

    iReturn = vsprintf (szBuffer, szFormat, pArgs) ;

    va_end (pArgs) ;

    return iReturn ;

}

va_start宏将pArg设置为指向一个堆栈变量,该变量位址在堆栈参数szFormat的上面。

----------------------------------------------------------------------------------------------------------------------------------------------

 

snprintf:

vsnprintf:

将n字节写入str所指向的内存,n的大小包含'\0';

如果要写入的字符串的长度大于或者等于n,则源字符串被截断,并且不会向目的内存写入'\0';

函数的返回值为实际写入字节数的大小,所以如果函数返回值大于或者等于n,则证明源字符串被截断.

----------------------------------------------------------------------------------------------------------------------------------------------

 

int snprintf(char *s, int size, const char *fmt, ...) 

{

    va_list ap;

    int n=0;

    va_start(ap, fmt);              //获得可变参数列表

    n=vsnprintf (s, size, fmt, ap); //写入字符串s

    va_end(ap);                     //释放资源

    return n;                       //返回写入的字符个数

}

----------------------------------------------------------------------------------------------------------------------------------------------

..................................................................................................................................................................................................
其他:

关于 % 格式的介绍:

基本格式    含义

%d            整型十进制

%u            无符号整型(对于八进制,十六进制来说没有符号区别)

%o            八进制

%x/%X     小写/大写的十六进制

%c            字符

%s            字符串

%f            浮点数,不使用科学表示法

%g/%G    六位有效数字表示法,当太大或太小时自动使用科学表示法

%e/%E     科学表示法,六位有效数字

 

标志            含义

‘-’                左对齐

‘+’                输出正负号,当然是对于十进制数来说的

‘ ’                和‘+’类似,但是正数

 

可变域宽和精度

    当想要打印出指定宽度的数字或字符串时,就可以指定域宽,使用宽度和精度修饰符“*”。

printf("%*.*s/n",14,14,name);  //打印14个字符

printf("%*.*s/n",14,5,name);    //只打印出5个字符(前面补空格)

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值