返回首页 C 高阶教程

输出

fputs

用fputs()把一个字符串写入到文件中
int fputs (char string, FILE fp) ;
功能:把字符串string写入到文件fp中
若fp为stdout,则为向屏幕输出。

printf

int printf ( char const format, …… ) ;
int fprintf ( FILE
fp, char const format, …… ) ;
int sprintf ( char const
string, char const *format, ……) ;
//以上函数的输出字符规则都相同,不同的是它们写入的流不同,一个是向屏幕写入、一个向文件流写入、一个向字符串写入。

带域宽和精度的打印

printf函数允许你为欲打印的数据指定精度。对于不同类型的数据而言,精度的含义是不一样的。

精度与整型转换说明符%d一起使用时,表示要打印的数据的最少数字位数。如果将要打印的数据所包含的数字的位数小于指定的精度,同时精度值前面带有一个0或者一个小数点,则加填充0。

精度与浮点型转换说明符%f一起使用时,表示将要打印的最大有效数字位数

精度与字符串转换说明符%s一起使用时,表示将要从一个字符串中打印出来的最大字符个数。(可用于控制打出的字符的个数) 表示精度的方法是:在百分号和转换说明符之间,插入一个表示精度的整数,并在整数的前面加上一个小数点。

域宽和精度可以放在一起使用,方法是:在百分号和转换说明符之间,先写上域宽,然后加上一个小数点,后面再写上精度。

例:
printf(“%9.3f”, 123.456789) ;
的输出结果是123.456

还可以用变量来控制域宽和精度(可用于关于精度的舍入)
在格式控制字符串中表示域宽或精度的位置上写上一个星号 * ,然后程序将会计算实参列表中相对应的整型实参值,并用其替换星号。

例:
printf(“% . f”, 7, 2, 98.736) ; 将以7为域宽,2为精度,输出右对齐的98.74
表示域宽的值可以是正数,也可以是负数(将导致输出结果在域宽内左对齐)

使用标记

printf函数还提供了一些标记来增加它的输出格式控制功能,在格式控制字符串中可以使用的标记有:

  • -(减号) 在域宽内左对齐显示输出结果
  • +(加号) 在正数前面显示一个加号,在负数前面显示一个减号
  • 空格 在不带加号标记的正数前面打印一个空格
  • #(井号) 当使用的是八进制转换说明符o时,在输出数据前面加上前缀0 ; 当使用的是十六进制转换说明符x或X时,在输出数据前面加上前缀0x或0X
  • 0(零) 在打印的数据前面加上前导0

逆向打印参数(POSIX扩展语法)

printf("%4$d %3$d %2$d %1$d", 1, 2, 3, 9); //将会打印9 3 2 1

返回值

printf 返回值是输出的字符个数

#include <stdio.h>
int main()
{
    int i=43;
    printf("%d\n",printf("%d",printf("%d",i)));
    return 0;
}//程序会输出4321

IO缓冲问题

在进行输入/输出时,程序并不是马上从输入/输出设备处理数据,而是先把数据放到缓存中,当缓存满时才进行输入/输出操作(或是遇到刷新操作,比如遇到换行或 fflush )。

C 实现通常允许程序员设置流的缓存大小

void setbuf (FILE steam, char buf) ;
参数 buf 必须指向一个长度为 BUFSIZ (定义在 stdio.h 头文件中)的缓冲区。

例:
setbuf (stdout, buf) ;
将告诉 I/O 库写入到 stdout 中的输出要以 buf 作为一个输出缓冲,并且等到 buf 满了或程序员直接调用 fflush() 再实际写出。

将buf参数设置为NULL,可关闭缓冲。

注意缓存的生命期问题

例:
下面的程序解释了通过使用 setbuf() 来把标准输入复制到标准输出:

#include <stdio.h>  
int  main()  
{      
    int c;    
    char buf[BUFSIZ];       
    setbuf(stdout, buf);    
    while((c = getchar()) != EOF)          
         putchar(c);   
    return 0 ;  
}    

这段程序隐藏着一个细微的Bug:
缓冲区最后一次刷新是在主程序完成之后,库将控制交回到操作系统之前所执行的清理的一部分。在这一时刻,缓冲区已经被释放了!(即main函数栈清空之后)

有两种方法可以避免这一问题:

  1. 使用静态缓冲区,或者将其显式地声明为静态
    static char buf[BUFSIZ];
    或者将整个声明移到主函数之外。

  2. 动态地分配缓冲区并且从不释放它
    setbuf (stdout, malloc(BUFSIZ));
    注意在后一种情况中,不必检查malloc()的返回值,因为如果它失败了,会返回一个空指针。而setbuf()可以接受一个空指针作为其第二个参数,这将使得stdout变成非缓冲的。这会运行得很慢,但它是可以运行的。
上一篇: 输入 下一篇: 一些不安全的库函...