本篇博文内容摘自《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\n", );

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

printf("%*d\n", , );

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

标准I/O库之格式化I/O的更多相关文章

  1. 标准I/O库之读和写流

    一旦打开了流,则可在三种不同类型的非格式化I/O中进行选择,对其进行读.写操作: (1)每次一个字符的I/O.一次读或写一个字符,如果流是带缓冲的,则标准I/O会处理所有缓冲. (2)每次一行的I/O ...

  2. UNIX环境高级编程---标准I/O库

    前言:我想大家学习C语言接触过的第一个函数应该是printf,但是我们真正理解它了吗?最近看Linux以及网络编程这块,我觉得I/O这块很难理解.以前从来没认识到Unix I/O和C标准库I/O函数压 ...

  3. UNIX环境高级编程——标准I/O库

    对一个进程预定义了三个流,并且这三个流可以自动的被进程使用,它们是:标准输入.标准输出.和标准错误. 标准I/O库提供缓冲的目的是尽可能减少使用read和write的次数. 标准I/O库提供了三种类型 ...

  4. APUE(5)---标准I/O库 (3)

    十.定位流 #include <stdio.h> long ftell(FILE *fp); //若成功,返回当前文件位置指示:若出错,返回-1L int fseek(FILE *fp, ...

  5. UNIX高级环境编程(7)标准IO函数库 - 二进制文件IO,流定位,创建临时文件和内存流

    1 二进制IO(Binary IO) 在前一篇我们了解了逐字符读写和逐行读写函数. 如果我们在读写二进制文件,希望以此读写整个文件内容,这两个函数虽然可以实现,但是明显会很麻烦且多次循环明显效率很低. ...

  6. Unix环境高级编程(三)标准I/O库

    标准I/O库是ISO C的标准,在很多操作系统上面都实现.Unix文件I/O函数都是针对文件描述符的,当打开一个文件的时候,返回该文件描述符用于后续的I/O操作.而对于标准I/O库,操作则是围绕流进行 ...

  7. 标准I/O库

    前言:我想大家学习C语言接触过的第一个函数应该是printf,但是我们真正理解它了吗?最近看Linux以及网络编程这块,我觉得I/O这块很难理解.以前从来没认识到Unix I/O和C标准库I/O函数压 ...

  8. APUE(5)---标准I/O库 (2)

    六.读和写流 一旦打开了流,则可在3种不同类型的非格式化I/O中进行选择,对其进行读.写操作:1)每次一个字符的I/O,一次读或写一个字符,如果刘时代缓冲的,则标准I/O函数处理所有缓冲:2)每次一行 ...

  9. UNIX系统高级编程——第五章-标准I/O库-总结

    基础: 标准I/O库在ANSI C中定义,可移植在不同的系统 文件指针(FILE):标准I/O库操作的不是文件描述符,而是流.FILE文件指针包含的是维护流所需的信息 通过函数fileno获取流的文件 ...

随机推荐

  1. 插入排序InsertionSort

    /** * * @author Administrator * 功能:插入排序法 */ package com.test1; import java.util.Calendar; public cla ...

  2. NGUI所见即所得之UIAtlasMaker , UIAtlas (2)

    本文的重点就是要将NGUI把多张图片打成一个图集(Atlas)的原理和过程研究下,学习下Unity提供的api和NGUI写的功能以及设计思想. (原文链接) 其它链接:NGUI所见即所得之UIRoot ...

  3. SPRING IN ACTION 第4版笔记-第四章ASPECT-ORIENTED SPRING-009-带参数的ADVICE2 配置文件为XML

    一. 1.配置文件为xml时则切面类不用写aop的anotation package com.springinaction.springidol; public class Magician impl ...

  4. 关于fastclick.js

    Fastclick fastclick.js解决了什么问题? 自己接触WebApp开发的前期, 总感觉WebApp上的按键操作不如NativeApp的灵敏, 好像有那么一小点延迟. 后来才知道, 这是 ...

  5. 关于标准库中的ptr_fun/binary_function/bind1st/bind2nd

    http://www.cnblogs.com/shootingstars/archive/2008/11/14/860042.html 以前使用bind1st以及bind2nd很少,后来发现这两个函数 ...

  6. webstrom使用记录

    很不方便的一点: 输入 $("#div p" 之后输入",就会变成$("#div p""" 这样,很不爽.

  7. ActionBar官方教程(4)给ActionBar添加操作项及它们的事件处理

    Adding Action Items The action bar provides users access to the most important action items relating ...

  8. android 利用数字证书对程序签名

    签名的必要性 1.  防止你已安装的应用被恶意的第三方覆盖或替换掉. 2.  开发者的身份标识,签名可以防止抵赖等事件的发生. 开发Android的人这么多,完全有可能大家都把类名,包名起成了一个同样 ...

  9. golang安装卸载 linux+windows+raspberryPI 平台

    参考  https://golang.org/doc/install 自ECUG2013洗脑回来,就渴望早点接触Go 听着许式伟和谢孟军的演讲 发现go的网络库的确很强大,高负载利器,语言的一些精简导 ...

  10. spring--DI--3

    3.1.1  依赖和依赖注入 传统应用程序设计中所说的依赖一般指“类之间的关系”,那先让我们复习一下类之间的关系: 泛化:表示类与类之间的继承关系.接口与接口之间的继承关系: 实现:表示类对接口的实现 ...