APUE学习笔记--标准I/O流(二)(fprintf、sprintf、snprintf、fscanf、sscanf、fseek、ftell、rewind、fseeko 、ftello、fflush)

  • 前言

    • 下面的函数,执行出错时,都会设置errno值。
  • fprintf

    • int fprintf(FILE *stream, const char *format, …);
      与printf很相似,只是printf默认输出流为stdout,fprintf可以指定输出流。
  • sprintf

    • int sprintf(char *str, const char *format, …);
      这不是输出到某个流,而是直接输出到某个内存中的字符数组中。
    • atoi把一个字符数组转换为int,sprintf可以把int转化为字符数组。
  • snprintf

    • int snprintf(char *str, size_t size, const char *format, …);
      sprintf没有指定str的大小,存在内存溢出可能。snprintf指定了接受数组的大小。
  • fscanf

    • int fscanf(FILE *stream, const char *format, …);
      scanf从标准输入流读取数据。sscanf可以指定输入流。
  • sscanf

    • int sscanf(const char *str, const char *format, …);
      不从某个流读取数据,而是从某个字符数组中读取数据。
  • 注意事项

    • scanf类和printf的这些函数,使用%s都比较危险,因为经常无法判断输入输出到底有多少。
    • 即使有snprintf这类限制了buf大小的函数,还是没有解决根本问题。即如果一行输入或者输出真的很大,超出了buf的size大小,那这行数据怎么读?
  • fseek、ftell、rewind

    • int fseek(FILE *stream, long offset, int whence);

      • 功能描述:使流指针指向相对于whence偏移量为offset的位置。
      • offset:相对于whence位置的偏移。可正可负。
      • whence:文件指针位置;
        • SEEK_SET:文件头
        • SEEK_CUR:当前位置
        • SEEK_END:文件尾
      • 返回值:执行成功,返回0;否则,返回-1。
    • long ftell(FILE *stream);

      • 函数描述:返回该流指针所在位置与该流起始位置相差的字节数。
      • 返回值: 成功,返回目前指针位置与流起始位置的偏移量;否则,返回-1。
    • void rewind(FILE *stream);

      • 使流指针指向流起始位置。
      • 等价于 (void) fseek(stream, 0L, SEEK_SET)
    • 使用fseek与ftell实现计算文件字节数。

#include <stdio.h>
#include <stdlib.h>


int main(int argc,char * argv[])
{
	if(argc != 2)
	{
		fprintf(stderr,"Usage---%s <source file>",argv[0]);
		exit(1);
	}

	FILE * fps;
	fps = fopen(argv[1],"r");
	if(fps == NULL)
	{
		perror("source file open failed !");
		exit(1);
	}

	int tmp = fseek(fps,0,SEEK_END);
	if(tmp == -1)
	{
		perror("fseek():");
		fclose(fps);
		exit(1);
	}
	fprintf(stdout,"%ld\n",ftell(fps));
	exit(0);
}

  • 注意事项

    • 注意ftell的返回值类型和fseek中的offset类型都为long。ftell的返回值的取值范围为【0,2的31次方 - 1】,而fseek中的offset可取正取负。也就是说ftell可访问的最大文件大小只能是fseek的一半。
  • fseeko 、ftello

为了处理如上问题,就有了如下两个函数:
int fseeko(FILE *stream, off_t offset, int whence);

off_t ftello(FILE *stream);

变化主要在于off_t。man手册对于off_t的解释如下:

    On many architectures both off_t and long  are  32-bit  types,  but
 compilation with
 
    #define _FILE_OFFSET_BITS 64
    
     will turn off_t into a 64-bit type.

所以需要64位的off_t时,需要gcc编译时输入-D _FILE_OFFSET_BITS=64
每次编译都这样,太麻烦,比较好的办法是编写makefile。(我暂时不懂makefile)

  • fflush

    • int fflush(FILE *stream);
      • 功能描述:强制把指定流中所有用户空间中的缓存数据送入输出流或者更新流中。
      • fflush(NULL):强制把所有用户空间中的缓存数据送入输出流或者更新流中。
      • 返回值:成功返回0;失败返回EOF。
      • fflush只能清空c标准库提供的用户数据缓冲空间,想要清空系统内核的缓冲区,得用其他函数。
  • linux中的缓冲区

    • 缓冲区作用:大多数时候是好事,合并系统调用。
    • 行缓冲:换行的时候刷新;满了的时候刷新;强制刷新(stdout是这样的,因为它是终端设备。)
    • 全缓冲:满了的时候刷新;强制刷新(默认如此,只要不是终端设备)
    • 无缓冲:如stderr,必须立即输出。
    • setvbuff可以设置某个缓冲区的类型。
    • 展示行缓冲的代码如下:
#include <stdio.h>
int main()
{
	printf("xxx");
	printf("ddd");
	while(1);
	exit(0);
}

执行后,xxxddd不会输出。因为stdout是行缓冲,stdout只能在满了或者换行或者强制刷新的时候,才会输出。
修改的办法:一:加\n。二:加fflush(stdout)或者fflush(NULL)。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值