打印
[ARM入门]

C 陷阱与缺陷学习 笔记 —— 其他 Printf 函数族

[复制链接]
797|0
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
千岁寒|  楼主 | 2018-10-25 12:06 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
#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个字符(前面补空格)

#define    NAMESIZE    14
char  name[NAMESIZE];
printf("%NAMESIZEs/n",name);
但是:上面的语法有错误,编译的时候会提示错误的类型 %N,因为宏由预编译来处理,而预编译不会进入到字符串内部!

相关帖子

发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

72

主题

244

帖子

4

粉丝