读书笔记之C Primer Plus 6

为什么阅读《C Primer Plus》第六版

准备好好研究下redis源码,但是很久没用c语言写代码了,平时工作主要用java和js。
所以准备重新阅读学习下c语言经典书籍:C Primer Plus。
更好地阅读redis源码。


第13章 文件输入/输出

文件是当今计算机系统不可或缺的部分。文件用于存储程序、文档、数据、书信、表格、图形、照片、视频和许多其他种类的信息。

什么是文件

文件通常是在磁盘或固体硬盘上的一段已命名的存储区。
C提供两种文件模式:文本模式和二进制模式。

文本模式和二进制模式

所有文件的内容都以二进制形式存储。

  • 文本模式:如果文件最初使用二进制编码的字符(ASCII或Unicode)表示文本,该文件就是文本文件。
  • 二进制模式:如果文件中的二进制值代表机器语言代码或数值数据或图片或音乐编码,该文件就是二进制文件。
  • 在二进制模式中,程序可以访问文件的每个字节。
  • 在文本模式中,程序所见的内容和文件的实际内容不同。
  • 程序以文本模式读取文件时,把本地环境表示的行末尾或文件结尾映射为C模式。(比如\r转换成\n)
  • 除了以文本模式读写文本文件,还能以二进制模式读写文本文件

I/O的级别

  • 底层I/O(low-level I/O)使用操作系统提供的基本I/O服务
  • 标准高级I/O(standard high-level I/O)使用C库的标准包和stdio.h头文件定义
  • 标准高级I/Os比底层I/O容易跨平台移植。标准io使用缓冲区,底层io需要自己处理缓存。

标准文件

C程序会自动打开3个文件,它们被称为标准输入(standard input)、标准输出(standard output)和标准错误输出(standard error output)。
在默认情况下,标准输入是系统的普通输入设备,通常为键盘;标准输出和标准错误输出是系统的普通输出设备,通常为显示屏。

标准I/O

/* count.c -- 使用标准 I/O */
#include <stdio.h>
#include <stdlib.h>    // 提供 exit()的原型

int main(int argc, char *argv [])
{
     int ch;          // 读取文件时,存储每个字符的地方
     FILE *fp;        // “文件指针”
     unsigned long count = 0;
     if (argc != 2)
     {
          printf("Usage: %s filename\n", argv[0]);
          exit(EXIT_FAILURE);
     }
     if ((fp = fopen(argv[1], "r")) == NULL)
     {
          printf("Can't open %s\n", argv[1]);
          exit(EXIT_FAILURE);
     }
     while ((ch = getc(fp)) != EOF)
     {
          putc(ch, stdout);    // 与 putchar(ch); 相同
          count++;
     }
     fclose(fp);
     printf("File %s has %lu characters\n", argv[1], count);
     return 0;
}
  • return 0 和 exit 区别。

fopen函数

  • 函数声明在stdio.h中
  • 第一个参数:打开文件的包含该文件名的字符串地址。
  • 第二个参数:打开文件的模式,r=读模式,w=写模式
  • x模式:x模式的独占特性使得其他程序或线程无法访问正在被打开的文件
  • 成功打开文件后,fopen()将返回文件指针。
  • 文件指针不指向实际的文件,它指向一个包含文件信息的数据对象,其中有缓冲区信息。

getc和putc

  • ch = getchar(); 从标准输入中获取一个字符;
  • ch = getc(fp); 从fp指向的文件中获取一个字符;
  • putc(ch,fpout); 把字符ch放入FILE指针fpout指定的文件中;
  • 都定义在stdio.h中

文件结尾

返回一个特殊值EOF代表文件末尾

int ch;
FILE * fp;
fp = fopen("wacky.txt", "r");
while (( ch = getc(fp)) != EOF)
{
     putchar(ch);    //处理输入
}

fclose函数

  • 成功返回0
  • 失败返回EOF
  • 磁盘已满、移动磁盘移除或出现io错误,都会失败
if (fclose(fp) != 0)
     printf("Error in closing file %s\n", argv[1]);

指向标准文件的指针

stdio.h头文件把3个文件指针与3个标准文件相关联,C程序会自动打开这3个标准文件。

  • 标准输入 stdin
  • 标准输出 stdout
  • 标准错误 stderr

fprintf和fscanf

文件I/O函数fprintf()和fscanf()函数的工作方式与printf()和scanf()类似,区别在于前者需要用第1个参数指定待处理的文件。
都把FILE指针作为第一个参数,而不是最后一个参数。

fprintf(fp,"%s\n",words);
fscanf(fp,"%s",words);

fgets和fputs

  • fgets第一个参数表示存储输入位置的地址(char* 类型);
  • fgets第二个参数事一个整数,待输入字符串的大小;
  • fgets第三个参数是文件指针;
  • fgets(buf,STLEN,fp);
  • fgets读取输入直到第一个换行符的后面,或读到文件结尾,或者读取STLEN-1个字符;
  • 然后fgets在末尾添加一个空字符使之成为一个字符串;
  • fputs第一个参数是字符串的地址;
  • fputs第二个参数事文件指针;
  • 由于fgets保留了换行符,fputs就不会再添加换行符;

随机访问fseek和ftell

  • fseek第一个参数是FILE指针,fopen返回的文件指针
  • fseek第二个参数是编移量,必须是long类型的值,正(前移),负(后移)或0(保持不动)
  • fseek第三个参数事模式,该参数确定起始点,
  • stdio.h常量-> SEEK_SET文件开始处、SEEK_CUR当前闻之、SEEK_END文件末尾,旧的实现对应0L、1L、2L
  • ftell函数返回类型long,返回指向文件的当前位置距文件开始处的字节数;
  • last = ftell(fp);
fseek(fp,0L,SEEK_SET); //定位至文件开始处
fseek(fp,10L,SEEK_SET);//定位至文件中的第10个字符
fssek(fp,2L,SEEK_CUR);//从文件当前位置前移2个字节
fseek(fp,0L,SEEK_END);//定位至文件结尾
fseek(fp,-10L,SEEK_END);//从文件结尾处回退10个字节;

fgetpos和fsetpos

  • 不使用long类型,使用新类型:fpos_t文件定位类型
//调用该函数时,它把fpos_t类型的值放在pos指向的位置上,该值描述了文件中的当前位置距文件开头的字节数。如果成功,fgetpos()函数返回0;如果失败,返回非0。
int fgetpos(FILE * restrict stream,fpos_t * restrict pos);
//调用该函数时,使用pos指向位置上的fpos_t类型值来设置文件指针指向偏移该值后指定的位置。如果成功,fsetpos()函数返回0;如果失败,则返回非0。fpos_t类型的值应通过之前调用fgetpos()获得。
int fsetpos(FILE *stream,const fpos_t *pos);

int ungetc(int c, FILE *fp)函数

int ungetc()函数把c指定的字符放回输入流中。

int fflush()函数

int fflush()函数

调用fflush()函数引起输出缓冲区中所有的未写入数据被发送到fp指定的输出文件。这个过程称为刷新缓冲区。

int setvbuf()函数

int setvbuf(FILE * restrict fp, char * restrict buf, int mode, size_t size);

setvbuf()函数创建了一个供标准I/O函数替换使用的缓冲区。在打开文件后且未对流进行其他操作之前,调用该函数。指针fp识别待处理的流,buf指向待使用的存储区。

fwrite和fread

  • fwrite把二进制数据写入文件
  • fwrite返回size_t类型
  • fread()函数接受的参数和fwrite()函数相同。
  • 在fread()函数中,ptr是待读取文件数据在内存中的地址,fp指定待读取的文件。
size_t fwrite(const void * restrict ptr, size_t size, size_t nmemb,FILE * restrict fp);
size_t fread(void * restrict ptr, size_t size, size_t nmemb,FILE * restrict fp);

读书总结

这章仔仔细细看了两遍,对c的标准I/O有了清晰的认识,不像java的IO这么多。java的io虽然灵活,但略显繁琐。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

余很多之很多

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值