标准 IO

Linux 分层(内核架构)

在这里插入图片描述
在这里插入图片描述

标准IO

标准IO只能操作普通文件。

文件类型:

b: 块设备文件
c: 字符设备文件
d: 目录文件
-: 普通文件
l: 链接文件
s: 套接字文件
p: 管道文件

概念

C库 中定义的一组用于 输入输出的函数。

特点

1、通过缓冲机制减少系统调用。
2、围绕流进行操作,流用 FILE * 表示。
3、标准IO 默认打开了3个流,stdin(标准输入)、stdout(标准输出)、stderr(标准错误)。

ctags 索引:

1)vi -t <要追踪的内容>,可以查找宏、数据类型等;
2)输入前面序号,回车;
3)继续追踪:将光标定位到要追踪的内容上,Ctrl + ]
4)回退:Ctrl + T
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

缓冲区

分类

1、全缓冲:跟文件相关

全缓冲区刷新条件:

① : 程序正常退出
② : 缓冲区满刷新
③ : 强制刷新 int fflush(FILE *stream);
2、行缓冲:跟终端相关

行缓冲区刷新条件:

① : \n
在这里插入图片描述
在这里插入图片描述

② : 程序正常退出
略。
③ : 缓冲区满刷新
见下面“写满缓冲区”。
④ : 强制刷新 int fflush(FILE *stream);
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

3、不缓冲:没有缓冲区,标准错误

测试行缓冲区大小:

1、写满缓冲区

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

缓冲区满则全部释放,故缓冲区大小 = 128 * 8bytes = 1024B = 1KB
2、stdout->_IO_buf_end 减去 stdout->_IO_buf_base
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

函数接口

打开文件(fopen)、perror

FILE *fopen(const char *path, const char *mode);
功能:打开文件
参数:
    path:打开的文件
    mode:打开的方式
        r/rb:	只读,当文件不存在时报错,文件流定位到文件开头
        r+/r+b:可读可写,当文件不存在时报错,文件流定位到文件开头
        w/wb:	只写,文件不存在创建,存在清空重写
        w+/w+b:可读可写,文件不存在创建,存在清空重写
        a/ab:	追加(在末尾写),文件不存在创建,存在追加,文件流定位到文件末尾
        a+/a+b:读和追加, 文件不存在创建,存在追加, 读文件流定位到文件开头,写文件流定位到文件末尾
        	注:当以 a 的方式打开文件时,写只能在末尾进行追加,
         		定位操作无法改变写的位置,但是可以改变读的位置
返回值:成功:文件流
       失败:NULL,并且会设置错误码
void perror(const char *s);
功能:根据errno值打印对应的错误信息
参数:
	 s:提示语句
返回值:空

在这里插入图片描述

关闭文件(fclose)

int fclose(FILE* stream);
功能:关闭文件
参数:stream:文件流

在这里插入图片描述

读写操作

每次读写一个字符(fgetc / fputc)
int  fgetc(FILE * stream); 
功能:从文件中读取一个字符
参数:stream:文件流
返回值:成功:读到的字符
      失败或读到文件末尾:EOF(-1)

在这里插入图片描述

int fputc(int c, FILE * stream); 
功能:向文件中写入一个字符
参数:c:要写的字符
   stream:文件流
返回值:成功:写的字符的ASCII
      失败:EOF

在这里插入图片描述
在这里插入图片描述

// 实现 cat 功能
#include <stdio.h>

int main(int argc, char const *argv[])
{
    FILE *p = fopen("./test.txt", "r");		// 若从终端读入路径,"./test.txt" --> argv[1]

    if (p == NULL){
        perror("Failed:");
        return -1;
    }

    char ch;
    while (1)				// while ((ch = fgetc(p)) != EOF) {fputc(ch, stdout);}		
    {
        ch = fgetc(p);
        if (feof(p))						// if (ch == EOF)
            break;
        else 								// 可以省略
            fputc(ch, stdout);
    }
    putchar(10);
    
    fclose(p);
    return 0;
}

若只允许从终端输入两个参数,则将下图的代码添加在main函数内最前面。
在这里插入图片描述

feof、ferror
int  feof(FILE * stream);
功能:判断文件有没有到结尾
返回:到达文件末尾,返回非零值

在这里插入图片描述
在这里插入图片描述

int ferror(FILE * stream);
功能:检测文件有没有出错
返回:文件出错,返回非零值

在这里插入图片描述
在这里插入图片描述

每次读写一串字符(fgets / fputs)
char * fgets(char *s,  int size,  FILE * stream);
功能:从文件中每次读取一行字符串
参数:s:存放字符串的地址
         size:一次读取的字符个数         
         stream:文件流
返回值:成功:s的地址
       失败或读到文件末尾:NULL
特性:每次实际读取的字符个数为size-1个,会在末尾自动添加\0
       每次读一行,遇到 \n 后不再继续读下一行

在这里插入图片描述

int fputs(const char *s, FILE *stream);

fputs()  writes  the  strings to stream, without its terminating null byte ('\0').
fputs() return a nonnegative number on success,  or  EOF  on error.
实现“wc -l 文件名”功能
// 若最后空行个数 n>1,只记录 n-1 行
#include <stdio.h>

int main(int argc, char const *argv[])
{
    if (argc != 2){
        printf("Please input %s <filename>.", argv[0]);
        return -1;
    }

    FILE *p = fopen(argv[1], "r");

    char buf[1024];			// 每次获取字符的长度必须足够大(容纳一整行)才可以,不建议此法
    char *q;										// 并不需要定义q
    int count = 0;
    while ((q = fgets(buf, 1024, p)) != NULL){	
        count++;                 // while (fgets(buf, 1024, p) != NULL) 即可
    }							 // while (fgets(buf, 1024, p)) 即可
    printf("%d\n", count);

    return 0;
}

在这里插入图片描述

(计算 ‘\n’ 的个数:)
在这里插入图片描述

实现“head -n 文件名”功能
#include <stdio.h>

int main(int argc, char const *argv[])
{
    if (argc != 2){
        printf("Please input %s <filename>.", argv[0]);
        return -1;
    }

    FILE *p = fopen(argv[1], "r");
    if (p == NULL){
        perror("Failed:");
        return -1;
    }

    char buf[1024];
    int n, count = 0;
    scanf("%d", &n);
    while (count < n){				// 不建议如此
        fgets(buf, 1024, p);		// 读取长度必须足够大,每次读完一整行才可以
        fputs(buf, stdout);
        count++;
    }

    fclose(p);
    return 0;
}

在这里插入图片描述
在这里插入图片描述

(依据 ‘\n’ 计算行数👆)
(因为要输入 -n,所以要指向 argv[1] 串的第二个字符) int atoi(const char *nptr);

二进制读写(fread / fwrite)
size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
功能:从文件流读取多个元素
参数:   ptr :用来存放读取元素
    	size :元素大小  sizeof(数据类型)
 		nmemb :读取元素的个数
    	stream :要读取的文件
返回值: 成功:	读取的元素的个数;
            	读到文件尾: 0
        失败: 	-1 
size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream);
功能:按对象写
参数:同上
返回值: 成功 :写的元素个数
        失败 :-1

在这里插入图片描述

实现 cp 功能

在这里插入图片描述

23 // while ((s = fgets(arr, 1024, p)) != NULL)
24 // fputs(arr, q);

定位操作

rewind(将文件位置指针定位到起始位置)
void rewind(FILE *stream);
功能:将文件位置指针定位到起始位置
fseek(SEEK_SET、SEEK_CUR、SEEK_END)

打开方式 “a”、“a+” 不支持 fseek函数。

int fseek(FILE *stream, long offset, int whence);
功能:文件的定位操作
参数:stream:文件流
     offset:偏移量:正数表示向后文件尾部偏移,负数表示向文件开头偏移
     whence:相对位置:
           SEEK_SET:相对于文件开头
           SEEK_CUR:相对于文件当前位置
           SEEK_END:相对于文件末尾
返回值:成功:0
        失败:-1   
注:当打开文件的方式为a或a+时,fseek不起作用  
ftell(获取当前的文件位置)
long ftell(FILE *stream);
功能:获取当前的文件位置
参数:要检测的文件流
返回值:成功:当前的文件位置,出错:-1

在这里插入图片描述

打开文件 2.0(freopen)

FILE * freopen(const char *pathname, const char *mode, FILE* fp); 
功能:将指定的文件流重定向到打开的文件中
参数:path:文件路径
mode:打开文件的方式(同fopen)
      fp:文件流指针
返回值:成功:返回文件流指针
      失败:NULL

在这里插入图片描述

diff <文件1> <文件2> :对比两个文件是否相同

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值