标准IO

目录

思维导图:

学习内容:

1. IO基础

2. 标准IO

2.1 标准IO提供的内容

2.2 FILE结构体

2.2.1 结构体解析

2.3 fopen 打开文件

2.4 fclose:关闭文件 

例如:

2.5 fgetc\fputc:单字符的输入输出 

 例如:

2.6 错误码 

 2.7 fputs\fgets:字符串输入输出

例如:

 2.8 缓冲区

课内练习:

1.使用fgetc完成,打开一个文件,统计该文件中的行数

2.使用fgetc和fputc完成,cp指令的功能,实现两个文件的拷贝,将src文件中的内容,拷贝到dest文件中 

课外作业:

1.使用fgets统计给定文件的行号

2.使用fgets、fputs完成两个文件的拷贝 


思维导图:


学习内容:

1. IO基础

        1> IO:(inout output) 所谓IO,就是程序与外部设备进行信息交换的过程

        2> IO的分类:标准IO和文件IO

        3> 标准IO:调用封装好的相关库函数,来实现数据的输入输出

        4> 文件IO:调用系统(内核)提供的相关函数,来实现数据的输入输出

        5> 标准IO和文件IO的区别:

                1、标准IO属于库函数,文件IO属于系统调用

                2、标准IO操作的是文件指针,文件IO操作的是文件描述符

                3、标准IO有缓冲器,文件IO没有缓冲区

        6> 目前所接触过的IO函数:

                printf、scanf、putchar、getchar、puts、gets

        7> 常用的IO接口函数

                标准IO:fprint、fscanf、fputc、fgetc、fputs、fgets、fread、 fwrite、fopen、fclose、            fseek、ftell、rewind。。。

                文件IO:open、close、read、write、seek。

2. 标准IO

2.1 标准IO提供的内容

        可以通过指令:man 7 stdio.h 可以查看该头文件提供的内容

1、标准的缓冲输入输出

2、提供的数据类型 FILE 文件结构体类型. off_t 偏移量类型 size_t 大小的类型,一般是一个long int类型

3、提供的偏移量的宏值 SEEK_SET:文件起始位置 SEEK_END:文件结束位置 SEEK_CUR:文件当前位置

4、提供文件结束标志:EOF (end of file)

5、默认提供的文件指针: stdin:标准输入指针 stdout:标准输出指针 stderr:标准出错指针

6、标准IO会提供三种缓冲区: 全缓存 行缓存 不缓存

2.2 FILE结构体

        查看该结构体 :vi -t FILE

2.2.1 结构体解析

struct _IO_FILE {char* _IO_buf_base;   /* 缓冲区开始地址 */char* _IO_buf_end;    /* 缓冲区结束地址 */int _fileno;         //用于系统调用的文件描述符};   

        当一个程序启动后,系统会自动打开三个文件指针:

                stdin:标准输入文件指针 ---> scanf、getchar、gets

                stdout:标准输出文件指针 ----> printf、putchar、puts

                stderr:标准出错文件指针 ---> perror

        以上三个文件指针,都是针对于终端文件操作而言的

2.3 fopen 打开文件

       #include <stdio.h>FILE *fopen(const char *pathname, const char *mode);
功能:打开给定路径的文件,以mode的形式打开
参数1: 要打开的文件的路径,是一个字符串
参数2:打开文件时的打开方式,是一个字符串r      以只读的形式打开一个文件,文件指针定位在开头Open text file for reading.  The stream is positioned at the beginning of the file.r+     以读写的形式打开一个文件,文件指针定位在开头Open for reading and writing.  The stream is positioned at the beginning of the file.w      以只写的形式打开文件,如果文件不存在则创建文件,如果文件存在则清空文件内容,文件指针定位在开头Truncate file to zero length or create text file for writing.  The stream is positioned at the beginning of the file.w+      以读写的形式打开文件,如果文件不存在则创建文件,如果文件存在则清空文件内容,文件指针定位在开头Open for reading and writing.  The file is created if it does not exist, otherwise it is truncated.  The stream is positionedat the beginning of the file.a      以追加的形式打开文件(结尾写),如果文件不存在则创建文件,如果存在则结尾写,文件指针定位在结尾Open  for appending (writing at end of file).  The file is created if it does not exist.  The stream is positioned at the endof the file.a+     以读或追加的形式打开文件,如果文件不存在,则创建文件,读指针定位在开头,写指针定位在结尾Open for reading and appending (writing at end of file).  The file is created if it does not exist.  The initial  file  posi‐tion for reading is at the beginning of the file, but output is always appended to the end of the file.
返回值:成功打开文件,返回该文件的地址,失败返回NULL,并置位错误码         

2.4 fclose:关闭文件 

       #include <stdio.h>int fclose(FILE *stream);功能:关闭给定的文件指针参数1:要关闭的文件指针返回值:成功返回0,失败返回EOF,并置位错误码

例如:

 

#include<myhead.h>int main(int argc, const char *argv[])
{//定义文件类型的结构体以便于接受打开的文件地址FILE * fp = NULL;//打开一个文件//fp = fopen("./text.txt", "r");           //以只读的形式打开一个当前路径下的文件fp = fopen("./text.txt", "w");           //以只写的形式打开一个当前路径下的文件if(NULL == fp){printf("fopen error\n");return -1;}printf("fopen success");   //关闭文件指针fclose(fp);return 0;
}

2.5 fgetc\fputc:单字符的输入输出 

      #include <stdio.h>int fputc(int c, FILE *stream);功能:将给定的字符,写入到文件指针stream指向的文件中去参数1:要写入的字符参数2:打开的文件指针返回值:成功返回写入字符的ascii值,失败返回EOF,并置位错误码#include <stdio.h>int fgetc(FILE *stream);功能:从指定文件中,读取一个字符参数:打开的文件指针返回值:从文件中读取的第一个字符的ascii值,失败返回EOF并置位错误码      

 例如:

#include<myhead.h>int main(int argc, const char *argv[])
{//定义文件类型的结构体以便于接受打开的文件地址FILE * fp = NULL;//打开一个文件//fp = fopen("./text.txt", "r");           //以只读的形式打开一个当前路径下的文件fp = fopen("./text.txt", "w+");           //以只写的形式打开一个当前路径下的文件if(NULL == fp){printf("fopen error\n");return -1;}printf("fopen success\n");//向文件中写入字符fputc('H', fp);fputc('e', fp);fputc('l', fp);fputc('l', fp);fputc('o', fp);fputc('\n', fp);//文件中存储的结果为 Hello  //说明每次写入数据时,光标会自动后移//关闭文件指针fclose(fp);//再次以只读的形式打开文件fp = fopen("./text.txt", "r");           //以只写的形式打开一个当前路径下的文件if(NULL == fp){printf("fopen error\n");return -1;}//定义变量用于读取数据char buf = 0;while(1){buf = fgetc(fp);       //从fp中读取数据if(EOF == buf)          //表示文件读取结束{break;}printf("%c\t", buf);   //将读取的数据显示到终端}//关闭文件指针fclose(fp);return 0;
}

2.6 错误码 

        1> 错误码是调用内核提供的函数时,如果调用出错,那么内核空间会向用户空间反馈一个错误信息

        2> 错误信息千奇百怪,并且是字符串内容,为了方便起见,给这些错误信息,进行编号

        3> 如果,内核空间函数调用出问题时,只需要反馈错误编号即可,这个错误编号就叫做错误码

        4> 常见错误码:可以通过指令 vi -t EIO 查看

  5 #define EPERM        1  /* Operation not permitted */6 #define ENOENT       2  /* No such file or directory */7 #define ESRCH        3  /* No such process */8 #define EINTR        4  /* Interrupted system call */9 #define EIO      5  /* I/O error */10 #define ENXIO        6  /* No such device or address */11 #define E2BIG        7  /* Argument list too long */12 #define ENOEXEC      8  /* Exec format error */13 #define EBADF        9  /* Bad file number */14 #define ECHILD      10  /* No child processes */15 #define EAGAIN      11  /* Try again */16 #define ENOMEM      12  /* Out of memory */17 #define EACCES      13  /* Permission denied */18 #define EFAULT      14  /* Bad address */19 #define ENOTBLK     15  /* Block device required */20 #define EBUSY       16  /* Device or resource busy */21 #define EEXIST      17  /* File exists */22 #define EXDEV       18  /* Cross-device link */23 #define ENODEV      19  /* No such device */                                                            24 #define ENOTDIR     20  /* Not a directory */25 #define EISDIR      21  /* Is a directory */26 #define EINVAL      22  /* Invalid argument */27 #define ENFILE      23  /* File table overflow */28 #define EMFILE      24  /* Too many open files */29 #define ENOTTY      25  /* Not a typewriter */30 #define ETXTBSY     26  /* Text file busy */31 #define EFBIG       27  /* File too large */32 #define ENOSPC      28  /* No space left on device */33 #define ESPIPE      29  /* Illegal seek */34 #define EROFS       30  /* Read-only file system */35 #define EMLINK      31  /* Too many links */36 #define EPIPE       32  /* Broken pipe */37 #define EDOM        33  /* Math argument out of domain of func */38 #define ERANGE      34  /* Math result not representable */

5> 错误码的相关函数 

1、strerror函数#include <string.h>char *strerror(int errnum);功能:将给定的错误码,转变成错误信息参数1:错误码返回值:错误码对应的错误信息的字符串错误码如何获得?答:需要加一个头文件:#include<errno.h>#include <errno.h>const char * const sys_errlist[];int sys_nerr;int  errno;        /*  Not  really  declared  this  way;  seeerrno(3) */2、perror函数#include <stdio.h>void perror(const char *s);功能:向标准出错缓冲区中,写入最新的错误码对应的信息参数:提示字符串,会自动提供一个冒号,并且输出结束后,会自动加一个换行返回值:无

 2.7 fputs\fgets:字符串输入输出

       #include <stdio.h>int fputs(const char *s, FILE *stream);功能:将给定的字符串,写入到文件中参数1:要写入的字符串起始地址参数2:打开的文件指针返回值:成功返回写入的字符个数(字符串长度),失败返回EOF#include <stdio.h>char *fgets(char *s, int size, FILE *stream);功能:从stream所指向的文件中,最多读取size-1的字符到s中,在读取过程中,如果遇到回车或者文件结束,会结束本次读取,并且会把回车也放入容器中。在后面自动加上'\0'参数1:存放数据的容器,一般是一个字符数组参数2:读取的大小参数3:文件指针返回值:成功返回容器的起始地址,失败返回NULL

例如:

#include<myhead.h>int main(int argc, const char *argv[])
{//定义文件指针FILE *fp = NULL;if((fp = fopen("./file.txt", "w")) == NULL){//strerror:将错误码转变成错误信息//printf("errno:%s\n", strerror(errno));perror("fopen error");return -1;}printf("open success\n");//向文件中写入字符串fputs("Hello world\n", fp);fputs("I love China\n", fp);fputs("good good study day day up\n", fp);//关闭文件fclose(fp);//以只读的形式重新打开文件if((fp = fopen("./file.txt", "r")) == NULL){perror("fopen error");return -1;}//循环读取数据char buf[128] = "";while(1){//清空容器bzero(buf,  sizeof(buf));if( fgets(buf, sizeof(buf), fp)  == NULL){break;    //说明文件读取结束}//输出读取的数据printf("%s", buf);   }printf("\n");//关闭文件fclose(fp);return 0;
}

 2.8 缓冲区

        1> 标准IO提供了三种缓冲区:行缓存、全缓存、不缓存

        2> 行缓存:有关标准输入、标准输出指针对应的缓冲区,其大小位1024字节

        3> 全缓存:有关普通文件指针对应的缓冲区,其大小位4096字节

        4> 不缓存:有关标准出错文件指针对应的缓冲区,其大小位 0

#include<myhead.h>int main(int argc, const char *argv[])
{printf("行缓存的大小为:%ld\n", stdout->_IO_buf_end - stdout->_IO_buf_base);//0printf("行缓存的大小为:%ld\n", stdout->_IO_buf_end - stdout->_IO_buf_base);//1024getchar();        //使用一次标准输入printf("行缓存的大小为:%ld\n", stdin->_IO_buf_end - stdin->_IO_buf_base);//1024perror("usage");      //使用一次标准出错printf("不缓存的大小为:%ld\n", stderr->_IO_buf_end - stderr->_IO_buf_base);//0//验证全缓冲FILE *fp = NULL;if((fp = fopen("./tt.c", "w+")) == NULL){perror("fopen error");return -1;}fgetc(fp);        //使用一次全缓冲printf("全缓存的大小为:%ld\n", fp->_IO_buf_end - fp->_IO_buf_base);//0//关闭fclose(fp);return 0;
}

        5> 行缓存的刷新时机 


课内练习:

1.使用fgetc完成,打开一个文件,统计该文件中的行数

解析:

#include<myhead.h>int main(int argc, const char *argv[])
{//判断传入的参数是否为2个if(argc != 2){printf("input file error!!!\n");printf("usage:./a.out fileName\n");return -1;}//表示传过来的有一个文件//定义文件指针FILE *fp = NULL;if((fp = fopen(argv[1], "r")) == NULL){printf("fopen error\n");return -1;}//说明文件已经打开char buf = 0;        //接受字符int count = 0;       //统计行数while(1){//从文件中读取一个字符buf = fgetc(fp);if(buf == EOF){break;}//判断是否读取到回车if(buf == '\n'){count ++;}}//输出行号printf("该文件一共有%d行\n", count);//关闭文件fclose(fp);return 0;
}

2.使用fgetc和fputc完成,cp指令的功能,实现两个文件的拷贝,将src文件中的内容,拷贝到dest文件中 

#include<myhead.h>int main(int argc, const char *argv[])
{//判断传入的是否为三个文件if(argc != 3){printf("input file error\n");printf("usage:./a.out srcfile destfile\n");return -1;}//以只读的形式打开源文件FILE *sfp = NULL;if((sfp = fopen(argv[1], "r")) == NULL){printf("open src file error\n");return -1;}//以只写的形式打开目标文件FILE *dfp = NULL;if((dfp = fopen(argv[2], "w")) == NULL){printf("open destfile error\n");return -1;}//定义搬运工char buf = 0;//循环从源文件中读取数据放入到目标文件中while(buf = fgetc(sfp) != EOF){//将读取的数据写入目标文件中fputc(buf, dfp);}//关闭文件fclose(sfp);fclose(dfp);printf("拷贝成功\n");return 0;
}

课外作业:

1.使用fgets统计给定文件的行号

解析:

#include<myhead.h>
int main(int argc, char const *argv[])
{FILE *fp = NULL;int count=0;char buf[50];if(argc != 2){printf("intput file error\n");printf("usage: ./a.out xxx\n");return -1;}if((fp = fopen(argv[1],"r")) == NULL){perror("fopen error");return -1;}while(fgets(buf,sizeof(buf),fp) != NULL){count++;}fclose(fp);printf("有%d行\n",count);return 0;
}

2.使用fgets、fputs完成两个文件的拷贝 

解析:

#include<myhead.h>
int main(int argc, char const *argv[])
{FILE *fp1 = NULL;FILE *fp2 = NULL;if(argc != 3){printf("intput file error\n");printf("usage: ./a.out xxx xxx\n");return -1;}if((fp1=fopen(argv[1],"r")) == NULL){perror("fopen error");return -1;}if((fp2=fopen(argv[2],"w")) == NULL){perror("fopen error");return -1;}char buf[50];while(fgets(buf,sizeof(buf),fp1) != NULL){fputs(buf,fp2);}fclose(fp1);fclose(fp2);return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://xiahunao.cn/news/3267359.html

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

概率论--最大似然估计

目录 概念 基本原理 应用领域 实际应用案例 优缺点 优点&#xff1a; 缺点&#xff1a; 延伸 最大似然估计在机器学习中的具体应用案例是什么&#xff1f; 如何解决最大似然估计在处理小样本数据时的偏差问题&#xff1f; 最大似然估计与其他参数估计方法&#xff08…

uniapp手写滚动选择器

文章目录 效果展示HTML/Template部分&#xff1a;JavaScript部分&#xff1a;CSS部分&#xff1a;完整代码 没有符合项目要求的选择器 就手写了一个 效果展示 实现一个时间选择器的功能&#xff0c;可以选择小时和分钟&#xff1a; HTML/Template部分&#xff1a; <picker…

【文件fd】文件描述符fd | 文件描述表

目录 1.文件描述符fd 2.系统调用的0/1/2 3.C语言的stdin/stdout/stderr 4.系统调用的0/1/2和C语言的stdin/stout/stderr二者的关系❓ 5.文件描述表 5.1 文件描述符概念 5.3 文件对象strcut file 5.4 进程和文件对应关系 5.5 文件描述符理解 5.6 源码查看 1.文件描述…

AI行业合适做必应bing推广吗?怎么开户呢?

快速发展的AI行业中&#xff0c;有效的市场获客渠道是关键&#xff0c;随着数字营销领域的不断演进&#xff0c;必应Bing以其独特的市场定位、庞大的用户基础和高效的广告系统&#xff0c;成为AI企业推广策略中的重要一环。特别是针对那些寻求精准触达、高效转化的AI企业而言&a…

C++初级学习:⼊⻔基础

本文内容&#xff1a; 1.C参考⽂档&#xff1a;2.C第一个程序3.命名空间3.1namespace的价值3.2namespace的定义3.3命名空间的使用 4.C输⼊&输出5.缺省参数6.函数重载 1.C参考⽂档&#xff1a; https://legacy.cplusplus.com/reference/ https://zh.cppreference.com/w/cp…

【React】JSX:从基础语法到高级用法的深入解析

文章目录 一、什么是 JSX&#xff1f;1. 基础语法2. 嵌入表达式3. 使用属性4. JSX 是表达式 二、JSX 的注意事项1. 必须包含在单个父元素内2. JSX 中的注释3. 避免注入攻击 三、JSX 的高级用法1. 条件渲染2. 列表渲染3. 内联样式4. 函数作为子组件 四、最佳实践 在 React 开发中…

【C++】19.红黑树模拟实现 set 和 map

我们想要实现STL中的set和map&#xff0c;那么第一步就需要看一下库函数是如何实现的&#xff1a; 通过查看源代码我们发现两个容器都包含了stl_tree.h&#xff0c;因此我们猜测此头文件实现的是红黑树。 但是set和map很显然不是使用同一棵树实现的&#xff0c;那么STL库是怎么…

C# Nmodbus,EasyModbusTCP读写操作

Nmodbus读写 两个Button控件分别为 读取和写入 分别使用控件的点击方法 ①引用第三方《NModbus4》2.1.0版本 全局 public SerialPort port new SerialPort("COM2", 9600, Parity.None, 8, (StopBits)1); ModbusSerialMaster master; public Form1() port.Open();…

Beam Search 原理详解

文章目录 1. 前言2. 原理3. 举例4. 参考 1. 前言 Beam Search 是一种启发式图搜索算法&#xff0c;用于在图或树的搜索过程中寻找最有可能的路径。它常用于自然语言处理&#xff08;NLP&#xff09;中的序列生成任务&#xff0c;如机器翻译、语音识别和文本生成等。与穷举搜索…

渲染技术如何帮助设计内容实现从平面到立体的转换

随着数字艺术和视觉特效的飞速发展&#xff0c;三维建模与渲染技术在影视、游戏、广告、工业设计、建筑可视化等多个领域展现出了其不可或缺的重要性。这一技术不仅实现了从平面到立体的跨越&#xff0c;还极大地丰富了视觉表达的层次感和真实感。 三维建模&#xff1a;构建虚…

一站式企业服务平台有哪些特点和优势!

随着我国经济的快速发展&#xff0c;各地方政府及产业园区为了能够吸引投资和优质企业入驻&#xff0c;纷纷在营商环境优化上大下功夫&#xff0c;这是因为当下企业已经不再满足于基础服务&#xff0c;而是更看重利于企业发展的软环境&#xff0c;随之建设“一站式企业服务平台…

flex/lex使用和学习

flex/lex用于生成解析配置文件的C代码&#xff0c;我们可以不用自己手动去做解析的工作&#xff0c;交由他们生成的代码去做。 假设&#xff0c;我有如下一个配置文件config.xml 配置文件中定义了三种channel,分别为SSIF, IPMB, NET&#xff0c;每一种channel都有4个int属性&a…

PyTorch基础(24)--torch.multinomial()方法

&#x1f449;torch.multinomial的源码见https://github.com/dongjinkun/PyTorch/tree/main/torch 一、前言 torch.multinomial()方法多出现在需要采样的场景中&#xff0c;如强化学习。具体讲&#xff0c;当使用强化学习解决旅行商问题时&#xff0c;针对某一个instance&…

项目实战——外挂开发(30小时精通C++和外挂实战)

项目实战——外挂开发&#xff08;30小时精通C和外挂实战&#xff09; 外挂开发1-监控游戏外挂开发2-秒杀僵尸外挂开发3-阳光地址分析外挂开发4-模拟阳光外挂开发5-无限阳光 外挂开发1-监控游戏 外挂的本质 有两种方式 1&#xff0c;修改内存中的数据 2&#xff0c;更改内存中…

外文文献去哪个网站查找下载又快又准

今天收到好多同学的文献求助&#xff0c;大部分都是外文文献。那么外文文献去哪里查找下载比较好呢&#xff1f;本文小编就讲解一下自己平时是在什么网站上查找获取文献的&#xff0c;下面就用几篇求助文献演示一下获取过程&#xff1a; 第一篇、OVID数据库&#xff1a;A Crit…

录音教程分享:电脑在线录音,7款录音软件免费版公开!

在我们的日常生活中&#xff0c;不可避免地会遇到需要在电脑上录制各种系统内音频的场景。无论是记录一次讲座、一段对话&#xff0c;或者录制某个重要网站上的音频&#xff0c;这种需求变得愈发重要且广泛。然而&#xff0c;对许多人来说&#xff0c;在电脑上在线录音可能是一…

菜鸟从0学微服务——MyBatis-Plus

关于“菜鸟从0学微服务” 针对有编程基础&#xff0c;开始学习微服务的同学&#xff0c;我们陆续推出从0学微服务的笔记分享。力求从各个中间件的使用来反思这些中间件的作用和优势。 会分享的比较快&#xff0c;会记录demo演算和中间件的使用过程&#xff0c;至于细节的理论…

Spark_Oracle_II_Spark高效处理Oracle时间数据:通过JDBC桥接大数据与数据库的分析之旅

接前文背景&#xff0c; 当需要从关系型数据库&#xff08;如Oracle&#xff09;中读取数据时&#xff0c;Spark提供了JDBC连接功能&#xff0c;允许我们轻松地将数据从Oracle等数据库导入到Spark DataFrame中。然而&#xff0c;在处理时间字段时&#xff0c;可能会遇到一些挑战…

计算机网络知识-面试点1

1. 三握四挥 定义&#xff1a; 在计算机网络中&#xff0c;特别是TCP/IP协议中&#xff0c;“三握”指的是三次握手&#xff08;Three-way Handshake&#xff09;&#xff0c;而“四挥”则指的是四次挥手&#xff08;Four-way Handshake&#xff09;。这两个过程分别用于TCP连接…

模式Hash和history

vuerouter有两种路由模式Hash和history。区别&#xff1a;Hash为默认模式&#xff0c;url中包含一个#符号的哈希部分。优势&#xff1a;兼容性好&#xff0c;不需要后端服务器的特殊配置。缺点&#xff1a;不够美观&#xff0c;搜索引擎优化较差。History模式使用的浏览器的His…