C语言专题——格式化I/O详解

C语言专题——格式化I/O详解

1 格式化I/O函数族

函数族 用途 可用于所有的流 只用于stdin和stdout 内存中的字符串
scanf 格式化输入 fscanf scanf sscanf
printf 格式化输出 fprintf printf sprintf

2 scanf函数族

int fscanf (FILE *stream, const char *format, ...);
int scanf (const char *format, ...);
int sscanf (const char *string, const char *format, ...);

当格式化字符串到达末尾或者读取的输入不再匹配格式字符串所指定的类型时,输入就停止。
被转换的输入值的个数作为返回值返回。
如果在任何输入值被转换之前,输入流就已到达尾部,函数就返回EOF。

scanf族中的format字符串参数可能包含下列内容:
空白字符——它们与输入中的零个或多个空白字符匹配,在处理过程中将被忽略。
格式代码——它们指定函数如何解释接下来的输入字符。
其他字符——当任何其他字符出现在格式字符串时,下一个输入字符必须与它匹配。
如果匹配,该输入字符随后就被丢弃。如果不匹配,函数就不再读取直接返回。

3 scanf格式代码

格式:%[*][宽度][限定符]格式码

其中,[]表示可选项。

1> *

星号表示将使转换后的值被丢弃而不是进行存储。

2> 宽度

宽度以一个非负的整数给出,它限制将被读取用于转换的输入字符的个数。
如果未给出宽度,函数就连续读入字符直到遇见输入中的下一个空白字符。

3> 限定符

限定符用于修改有些格式代码的含义:

格式码 h l L
d,i,n short long
o,u,x unsigned short unsigned long
e,f,g double long double

4> 格式码

格式码用于指定字符如何被解释:

代码 c
参数 char *
含义 读取和存储单个字符。前导空白字符并不跳过。如果给出宽度,就读取和存储这个数目的字符。字符后面不会添加一个NUL字节。参数必
须指向一个足够大的字符数组。

代码 i,d
参数 int *
含义 一个可选的有符号整数被转换。d把输入解释为十进制数;i根据它的第一个字符决定值的基数,就像整型字面值常量的表示形式一样。

代码 u,o,x
参数 unsigned *
含义 一个可选的有符号整数被转换,但它按照无符号数存储。如果使用u,值被解释为十进制数;如果使用o,值被解释为八进制数;如果使用
x,值被解释为十六进制数。X和x同义。

代码 e,f,g
参数 float *
含义 期待一个浮点值。它的形式必须像一个浮点型字面常量,但小数点并非必须。E和G分别与e和g同义。

代码 s
参数 char *
含义 读取一串非空白字符。参数必须指向一个足够大的字符数组。当发现空白时输入就停止,字符串后面会自动加上NUL终止符。

代码 [xxx]
参数 char *
含义 根据给定组合的字符从输入中读取一串字符。参数必须指向一个足够大的字符数组。当遇到第一个不在给定组合中出现的字符时,输入就
停止。字符串后面会自动加上NUL终止符。代码%[abc]表示字符组合包括a、b和c。如果列表以一个^字符开头,表示字符组合是所列字符的补集
,所以%[^abc]表示字符组合为a、b、c之外的所有字符。右方括号也可以出现在字符列表中,但它必须是列表的第一个字符。至于横杠是否用
于指定某个范围的字符(例如%[a-z]),则因编译器而异。

代码 p
参数 void *
含义 输入预期为一串字符,诸如那些由printf函数的%p格式代码所产生的输出。它的转换方式因编译器而异,但转换结果将和按照上面描述的
进行打印所产生的字符的值是相同的。

代码 n
参数 int *
含义 到目前为止通过这个scanf函数的调用从输入读取的字符数被返回。%n转换的字符并不计算在scanf函数的返回值之内。它本身并不消耗任
何输入。

代码 %
参数 (无)
含义 这个代码与输入中的一个%相匹配,该%符号被丢弃。

4 printf函数族

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

函数的返回值是实际打印或存储的字符数。

5 printf格式代码

格式:%[零个或多个标志][最小字段宽度][精度][修改符]格式码

1> 格式码

代码 c
参数 int
含义 参数被裁剪为unsigned char类型并作为字符进行打印。

代码 i,d
参数 int
含义 参数作为一个十进制整数打印。如果给出了精度而且值的位数小于精度位数,前面就用0填充。

代码 u,o,x,X
参数 unsigned int
含义 参数作为一个无符号值打印,u使用十进制,o使用八进制,x或X使用十六进制,两者的区别是x约定使用abcdef,而X约定使用ABCDEF。

代码 e,E
参数 double
含义 参数根据指数形式打印。例如,6.023000e23是使用代码e,6.023000E23是使用代码E。小数点后面的位数由精度字段决定,缺省值是6。

代码 f
参数 double
含义 参数按照的常规浮点格式打印。精度字段决定小数点后面的位数,缺省值是6。

代码 g,G
参数 double
含义 参数以%f或%e(如G则%E)的格式打印,取决于它的值。如果指数大于等于-4但小于精度字段就使用%f格式,否则使用指数格式。

代码 s
参数 char *
含义 打印一个字符串。

代码 p
参数 void *
含义 指针值被转换为一串因编译器而异的可打印字符。这个代码主要是和scanf中的%p代码组合使用。

代码 n
参数 int *
含义 这个代码是独特的,因为它并不产生任何输出。相反,到目前为止函数所产生的输出字符数目将被保存到对应的参数中。

代码 %
参数 (无)
含义 打印一个%字符。

2> 标志

标志 -
含义 值在字段中做对齐,缺省情况下是右对齐。

标志 0
含义 当数值为右对齐时,缺省情况下是使用空格填充值左边未使用的列。这个标志表示用零填充,它可用于d,i,u,o,x,X,e,E,f,g和G代码。
使用d,i,u,o,x和X代码时,如果给出了精度字段,零标志就被忽略。如果格式代码中出现了负号,零标志也没有效果。

标志 +
含义 当用于一个格式化某个有符号值代码时,如果值非负,正号标志就会给它加上一个正号。如果该值为负,就像往常一样显示一个负号。在
缺省情况下,正号并不会显示。

标志 空格
含义 只用于转换有符号值的代码。当值非负时,这个标志把一个空格添加到它开始的位置。注意这个标志和正号标志是相互排斥的,如果两个
同时给出,空格标志便被忽略。

标志 #
含义 选择某些代码的另一种转换形式:

用于... #标志...
o 保证产生的值以一个零开头
x,X 在非零值前面加0x前缀(%X则为0X)
e,E,f 确保结果始终包含一个小数点,即使它后面没有数字
g,G 和上面的e,E和f代码相同。另外,缀尾的0并不从小数中去除

3> 字段宽度

字段宽度是一个十进制整数,用于指定将出现在结果中的最小字符数。如果值的字符数少于字段宽度,就对它进行填充以增加长度。

4> 精度

精度以一个句点开头,后面跟一个可选的十进制数。如果未给出整数,精度的缺省值为零。

对于d,i,u,o,x和X类型的转换,精度字段指定将出现在结果中的最小的数字个数并覆盖零标志。如果转换后的值的位数小于宽度,就在它的前
面插入零。如果值为零且精度也为零,则转换结果就不会产生数字。

对于e,E和f类型的转换,精度决定将出现在小数点之后的数字位数。

对于g和G类型的转换,它指定将出现在结果中的最大有效位数。

当使用s类型的转换时,精度指定将被转换的最多的字符数。

如果用于表示字段宽度和/或精度的十进制整数由一个星号代替,那么printf的下一个参数(必须是个整数)就提供宽度和(或)精度。因此,
这些值可以通过计算获得而不必预先指定。

5> 修改符

修改符 用于...时 表示参数是...
h d,i,u,o,x,X 一个(可能是无符号)short型整数
h n 一个指向short型整数的指针
l d,i,u,o,x,X 一个(可能是无符号)long型整数
l n 一个指向long型整数的指针
L e,E,f,g,G 一个long double型值

6 代码举例

1> 使用扫描集,使scanf能够读取一整行:

#include

int main()
{
char string[50];
scanf("%[^/n]", string);
printf("%s/n", string);

return 0;
}

2> 使用*号,从参数表获取printf所需的字段宽度和精度参数:

#include
#include

int main()
{
double pi = acos(-1);
int width = 12;
int precision = 8;
printf("%*.*f/n", width, precision, pi);

return 0;
}
 

输入输出函数及控制流程语句

    本节主要介绍Turbo C2.0标准输入输出函数和文件的输入输出函数。通过本节的学习可以使读者掌握Turbo C2.0的屏幕输出、键盘输入输出以及磁盘文件的读写函数, 并能开始进行一些简单的程序的编写。
    控制流程语句主要包括: 条件语句、循环语句和开关语句。
 
 

    1.1  标准输入输出函数

    1.1.1 格式化输入输出函数
    Turbo C2.0 标准库提供了两个控制台格式化输入、 输出函数printf( ) 和scanf(), 这两个函数可以在标准输入输出设备上以各种不同的格式读写数据。printf()函数用来向标准输出设备(屏幕)写数据; scanf() 函数用来从标准输入设备(键盘)上读数据。下面详细介绍这两个函数的用法。
    一、printf()函数
    printf()函数是格式化输出函数, 一般用于向标准输出设备按规定格式输出信息。在编写程序时经常会用到此函数。printf()函数的调用格式为:
      printf("<格式化字符串>", <参量表>);
    其中格式化字符串包括两部分内容: 一部分是正常字符,  这些字符将按原样输出; 另一部分是格式化规定字符, 以"%"开始, 后跟一个或几个规定字符,用来确定输出内容格式。
    参量表是需要输出的一系列参数, 其个数必须与格式化字符串所说明的输出参数个数一样多, 各参数之间用","分开, 且顺序一一对应,  否则将会出现意想不到的错误。
    1. 格式化规定符
    Turbo C2.0提供的格式化规定符如下:
━━━━━━━━━━━━━━━━━━━━━━━━━━
   符号                  作用
──────────────────────────
    %d              十进制有符号整数
    %u              十进制无符号整数
    %f              浮点数
    %s              字符串
    %c              单个字符
    %p              指针的值
    %e              指数形式的浮点数
    %x, %X          无符号以十六进制表示的整数
    %0              无符号以八进制表示的整数
    %g              自动选择合适的表示法
━━━━━━━━━━━━━━━━━━━━━━━━━━
    说明:
    (1). 可以在"%"和字母之间插进数字表示最大场宽。
     例如:  %3d   表示输出3位整型数, 不够3位右对齐。
            %9.2f 表示输出场宽为9的浮点数, 其中小数位为2, 整数位为6,
                  小数点占一位, 不够9位右对齐。
            %8s   表示输出8个字符的字符串, 不够8个字符右对齐。
    如果字符串的长度、或整型数位数超过说明的场宽, 将按其实际长度输出。但对浮点数, 若整数部分位数超过了说明的整数位宽度, 将按实际整数位输出;若小数部分位数超过了说明的小数位宽度, 则按说明的宽度以四舍五入输出。
    另外, 若想在输出值前加一些0, 就应在场宽项前加个0。
    例如:   %04d  表示在输出一个小于4位的数值时, 将在前面补0使其总宽度为4位。
    如果用浮点数表示字符或整型量的输出格式, 小数点后的数字代表最大宽度,小数点前的数字代表最小宽度。
    例如: %6.9s 表示显示一个长度不小于6且不大于9的字符串。若大于9,  则第9个字符以后的内容将被删除。
    (2). 可以在"%"和字母之间加小写字母l, 表示输出的是长型数。
    例如:   %ld   表示输出long整数
            %lf   表示输出double浮点数
    (3). 可以控制输出左对齐或右对齐, 即在"%"和字母之间加入一个"-" 号可说明输出为左对齐, 否则为右对齐。
    例如:   %-7d  表示输出7位整数左对齐
            %-10s 表示输出10个字符左对齐
    2. 一些特殊规定字符
━━━━━━━━━━━━━━━━━━━━━━━━━━
    字符                           作用
──────────────────────────
     /n                   换行
     /f                   清屏并换页
     /r                   回车
     /t                   Tab符
     /xhh                 表示一个ASCII码用16进表示,
                          其中hh是1到2个16进制数
━━━━━━━━━━━━━━━━━━━━━━━━━━
    由本节所学的printf()函数, 并结合上一节学习的数据类型, 编制下面的程序, 以加深对Turbo C2.0数据类型的了解。
    例1
     #include
     #include
     int main()
     {
          char c, s[20], *p;
          int a=1234, *i;
          float f=3.141592653589;
          double x=0.12345678987654321;
          p="How do you do";
          strcpy(s, "Hello, Comrade");
          *i=12;
          c='/x41';
          printf("a=%d/n", a);     /*结果输出十进制整数a=1234*/
          printf("a=%6d/n", a);    /*结果输出6位十进制数a=  1234*/
          printf("a=%06d/n", a);   /*结果输出6位十进制数a=001234*/
          printf("a=%2d/n", a);    /*a超过2位, 按实际值输出a=1234*/
          printf("*i=%4d/n", *i);  /*输出4位十进制整数*i=  12*/
          printf("*i=%-4d/n", *i); /*输出左对齐4位十进制整数*i=12*/
          printf("i=%p/n", i);     /*输出地址i=06E4*/
          printf("f=%f/n", f);     /*输出浮点数f=3.141593*/
          printf("f=6.4f/n", f);   /*输出6位其中小数点后4位的浮点数
                                      f=3.1416*/
          printf("x=%lf/n", x);    /*输出长浮点数x=0.123457*/
          printf("x=%18.16lf/n", x);/*输出18位其中小数点后16位的长浮点
                                      数x=0.1234567898765432*/
          printf("c=%c/n", c);     /*输出字符c=A*/
          printf("c=%x/n", c);     /*输出字符的ASCII码值c=41*/
          printf("s[]=%s/n", s);   /*输出数组字符串s[]=Hello, Comrade*/
          printf("s[]=%6.9s/n", s);/*输出最多9个字符的字符串s[]=Hello,
                                     Co*/
          printf("s=%p/n", s);     /*输出数组字符串首字符地址s=FFBE*/
          printf("*p=%s/n", p);    /* 输出指针字符串p=How do you do*/
          printf("p=%p/n", p);     /*输出指针的值p=0194*/
          getch();
          retunr 0;
     }
    上面结果中的地址值在不同计算机上可能不同。
    例1.中第一条语句#include的含义是调用另一个文件stdio.h, 这是一个头文件, 其中包括全部标准输入输出库函数的数据类型定义和函数说明。Turbo C2.0对每个库函数便用的变量及函数类型都已作了定义与说明, 放在相应头文件"*.h"中, 用户用到这些函数时必须要用#include<*.h>或#include"*. h"
语句调用相应的头文件, 以供连接。若没有用此语句说明, 则连接时将会出现错误。
    二、scanf()函数
    scanf()函数是格式化输入函数, 它从标准输入设备(键盘) 读取输入的信息。其调用格式为:
      scanf("<格式化字符串>", <地址表>);
    格式化字符串包括以下三类不同的字符;
    1. 格式化说明符: 格式化说明符与printf()函数中的格式说明符基本相同。
    2. 空白字符: 空白字符会使scanf()函数在读操作中略去输入中的一个或多个空白字符。
    3. 非空白字符: 一个非空白字符会使scanf()函数在读入时剔除掉与这个非空白字符相同的字符。
    地址表是需要读入的所有变量的地址, 而不是变量本身。这与printf()函数完全不同, 要特别注意。各个变量的地址之间同","分开。
    例2:
     main()
     {
          int i, j;
          printf("i, j=?/n");
          scanf("%d, %d", &i, &j);
     }

    上例中的scanf()函数先读一个整型数, 然后把接着输入的逗号剔除掉,  最后读入另一个整型数。如果","这一特定字符没有找到, scanf()函数就终止。若参数之间的分隔符为空格, 则参数之间必须输入一个或多个空格。
    说明:
    (1). 对于字符串数组或字符串指针变量,  由于数组名和指针变量名本身就是地址, 因此使用scanf()函数时, 不需要在它们前面加上"&"操作符。
    例3
      mian()
     {
          char *p, str[20];
          scanf("%s", p);          /*从健盘输入字符串*/
          scanf("%s", str);
          printf("%s/n", p);       /*向屏幕输出字符串*/
          printf("%s/n", str);
     }

    (2). 可以在格式化字符串中的"%"各格式化规定符之间加入一个整数, 表示任何读操作中的最大位数。
    如例3中若规定只能输入10字符给字符串指针p, 则第一条scanf() 函数语句变为
          scanf("%10s", p);
    程序运行时一旦输入字符个数大于10,  p就不再继续读入, 而后面的一个读入函数即scanf("%s", str)就会从第11个字符开始读入。
    实际使用scanf()函数时存在一个问题, 下面举例进行说明:
    当使用多个scanf()函数连续给多个字符变量输入时, 例如:
     main()
     {
          char c1, c2;
          scanf("%c", &c1);
          scanf("%c", &c2);
          printf("c1 is %c, c2 is %c", c2/1, c2);
     }

你可能感兴趣的:(C/C++,c,语言,编译器,string,存储,math.h)