• 标准I/O库之格式化I/O


    本篇博文内容摘自《UNIX环境高级编程》(第二版),仅作个人学习记录所用。关于本书可参考:http://www.apuebook.com/

    一、格式化输出

    执行格式化输出处理的是4个printf函数。

    #include <stdio.h>
    
    int printf( const char *restrict format, ... );
    int fpritnf( FILE *restrict fp, const char *restrict fromat, ... );
    两个函数的返回值:若成功则返回输出字符数,若输出出错则返回负值
    
    int sprintf( char *restrict buf, const char *restrict format, ... );
    int snprintf( char *restrict buf, size_t n, const char *restrict format, ... );
    两个函数返回值:若此成功则返回存入数组的字符数,若编码出错则返回负值

    printf将格式化数据写到标准输出,fprintf写至指定的流,sprintf将格式化的字符送入数组buf中。sprintf在该数组的尾端自动加一个null字节,但该字节不包括在返回值中

    注意,sprintf函数可能会造成由buf指向的缓冲区的溢出。调用者有责任确保该缓冲区足够大。为了解决这种缓冲区溢出的问题,引入了snprintf函数。在该函数中,缓冲区长度是一个显示参数,超过缓冲区尾端写的任何字符都会被丢弃。如果缓冲区足够大,snprintf函数就会返回写入缓冲区的字符数。与sprintf相同,该返回值不包括结尾的null字节。若snprintf函数返回小于缓冲区长度n的正值,那么没有截短输出。若发生了一个编码错误,snprintf则返回负值。

    格式说明控制其余参数如果编写,以后又如何显示。每个参数按照转换说明编写,转换说明以字符%开始,除转换说明外,格式字符串中的其他字符将按原样,不经任何修改地被复制输出。一个转换说明有4个可选部分,下面将它们都示于方括号中:

    %[flags] [fldwidth] [precision] [lenmodifier] convtype

    表5-5 转换说明中的标志部分

    标志 说明
    - 在字段内左对齐输出
    + 总是显示带符号转换的符号
    (空格) 如果第一个字符不是符号,则在其前面加上一个空格
    # 指定另一种转换形式(例如,对于十六进制格式,加0x前缀
    0 添加前导0(而非空格)进行填充

    fldwidth说明转换的最小字段宽度。如果转换得到的字符较少,则用空格填充它。字段宽度是一个非负十进制数,或是一个星号(*)。

    precision说明整型转换后最少输出数字位数、浮点数转换后小数点后的最少位数、字符串转换后的最大字符数。精度是一个句点(.),后接一个可选的非负十进制整数或一个星号(*)。

    宽度和精度字段两者皆可为*。此时,一个整型参数指定宽度或精度的值。该整型参数正好位于被转换的参数之前。(注意对这句话的理解)。我们还是用一个实例来说明比较容易接受:

    我们可以直接在fldwidth位置用一个整数10指定输出宽度:

    printf("%10d
    ", 123);

    也可以在fldwidth位置用*,而把指定宽度参数10放在转换说明后面,被转换的参数之前:

    printf("%*d
    ", 10, 123);

    lenmodifier说明参数长度。其可能的取值示于表5-6中。

    表5-6 转换说明中的长度修饰符

    长度修饰符 说明
    hh 有符号或无符号的char
    h 有符号或无符号的short
    l 有符号或无符号的long或者宽字符
    ll 有符号或无符号的long long
    j intmax_t或uintmax_t
    z size_t
    t ptrdiff_t
    L long double

    convtype不是可选的。它控制如何解释参数。表5-7中列出了各种转换类型。

    表5-7 转换说明中的转换类型部分

    转换类型 说明
    d、i 有符号十进制
    o 无符号八进制
    u 无符号十进制
    x、X 无符号十六进制
    f、F double精度浮点数
    e、E 指数格式的double精度浮点数
    g、G 解释为f、F、e或E,取决于被转换的值
    a、A 十六进制指数格式的double精度浮点数
    c 字符(若带长度修饰符l,则为宽字符)
    s 字符串(若带长度修饰符l,则为宽字符串)
    p 指向void的指针
    n 将到目前为止,所写的字符数写入到指针所指向的无符号整型中
    % %字符
    C 宽字符(XSI扩展,等效于lc)
    S 宽字符串(XSI扩展,等效于ls)

    下列4中printf族的变体类似于上面的4种,但是可变参数表(...)代换成了arg。

    #include <stdarg.h>
    #include <stdio.h>
    
    int vprintf( const char *restrict format, va_list arg );
    int vfprintf( FILE *restrict fp, const char *restrict format, va_list arg );
    两个函数返回值:若成功则返回输出字符数,若输出出错则返回负值
    
    int vsprintf( char *restrict buf, const char *restrict format, va_list arg );
    int vsnprintf( char *restrict buf, size_t n, const char *restrict format, va_list arg );
    两个函数返回值:若成功则返回存入数组的字符数,若编码出错则返回负值

    关于可变参数列表可参考《C和指针》7.6:Variable Argument Lists。

    二、格式化输入

    执行格式化输入处理的是三个scanf函数。

    #include <stdio.h>
    
    int scanf( const char *restrict format, ... );
    int fscanf( FILE *restrict fp, const char *restrict format, ... );
    int sscanf( const char *restrict buf, const char *restrict format, ... );
    三个函数返回值:若成功则返回指定的输入项数;若输入出错或在任意变换前已到达文件结尾则返回EOF

    scanf族用于分析输入字符串,并将字符序列转换成指定类型的变量。格式之后的各参数包含了变量的地址,以用转换结果初始化这些变量。

    格式说明控制如何转换参数,以便对它们赋值。转换说明以%字符开始。除转换说明和空白字符外,格式字符串中的其他字符必须与输入匹配。若有一个字符不匹配,则停止后续处理,不再读输入的其余部分。

    一个转换说明有三个可选部分,下面将它们都示于方括号中:

    %[*] [fldwidth] [lenmodifier] convtype

    可选的前导星号(*)用于抑制转换。按照转换说明的其余部分对输入进行转换,但转换结果并不存放在参数中。

    fldwidth说明最大宽度(即最大字符数)。

    lenmodifier说明要用转换结果初始化的参数大小。由printf函数族支持的长度修饰符同样得到scanf函数族的支持(见表5-6中的长度修饰符列表)。

    convtype字段类似于printf族的转换类型字段,但两者之间还有些差别。一个差别是,存储在无符号类型中的结果可在输入时带上符号。例如,-1可被转换成4 294 967 295赋予无符号整型变量。表5-8列出了scanf函数族支持的转换类型。

    表5-8 转换说明中的转换类型

    转换类型 说明
    d 有符号十进制,基数为10
    i 有符号十进制,基数由输入格式决定
    o 无符号八进制(输入可选地有符号)
    u 无符号十进制,基数为10(输入可选地有符号)
    x 无符号十六进制(输入可选地有符号)
    a、A、e、E、f、F、g、G 浮点数
    c 字符(若带长度修饰符l,则为宽字符)
    s 字符串(若带长度修饰符l,则为宽字符串)
    [ 匹配列出的字符序列,以]终止
    [^ 匹配除列出字符以外的所有字符,以]终止
    p 指向void的指针
    n 将到目前为止读取的字符数写入到指针所指向的无符号整型中
    % %字符
    C 宽字符(XSI扩展,等效于lc)
    S 宽字符串(XSI扩展,等效于ls)

    与printf族一样,scanf族也支持函数使用由<stdarg.h>说明的可变参数表。

    #include <stdarg.h>
    #include <stdio.h>
    
    int vscanf( const char *restrict format, va_list arg );
    int vfscanf( FILE *restrict fp, const char *restrict format, va_list arg );
    int vsscanf( const char *restrict buf, const char *restrict format, va_list arg );
    三个函数返回值:指定的输入项数,若输入出错或在任一变换前已到达文件结尾则返回EOF
  • 相关阅读:
    实例图解SQL SERVER2000使用AWE进行内存优化
    使用Power Designer正反向数据库及生成设计报告
    使用SVN+CruiseControl+ANT实现持续集成之二环境搭建和配置介绍
    使用SVN+CruiseControl+ANT实现持续集成之三构建操作及监视
    【排序】排序算法之分配排序
    [Cocoa]自定义TableViewCell实现圆角/渐变色TableView
    [Cocoa]XCode 3.2 常用快捷键
    [Cocoa]实现了一套自定义动画库
    Vim 使用入门快捷键
    [Cocoa] iPhone/iPad 时区转换
  • 原文地址:https://www.cnblogs.com/nufangrensheng/p/3506083.html
Copyright © 2020-2023  润新知