导图社区 标准IO
这是一篇关于标准IO的思维导图,主要内容包括:标准IO流,标准文件IO相关函数,标准文件IO存在缓存区,文件IO。
编辑于2024-11-28 17:59:01这是一篇关于day5day6的思维导图,主要内容包括:消息队列:信息是带有类型的 可以过滤,IPC通信:共享内存 消息队列 信号灯集、ipcs命令 查看共享内存 消息队列 信号量、ipcs -s 查看信号量、ipcs -m 查看共享内存、ipcs -q 查看消息队列,共享内存,管道:在内核开辟的一块缓冲区,信号,进程间通信的方式。
这是一篇关于day4的思维导图,主要内容包括:设置线程属性,线程的同步,线程的互斥,线程。线程概念:为进一步减少处理器的空转时间,支持多处理器以及减少上下文切换开销,进程演化出线程,它是进程内独立的一条运行路线,是内核调度的最小单元。
这是一篇关于day3的思维导图,主要内容包括:守护进程,回收进程资源,孤儿进程和僵尸进程,exec族函数,结束进程,进程,Linux下的多任务机制。
社区模板帮助中心,点此进入>>
这是一篇关于day5day6的思维导图,主要内容包括:消息队列:信息是带有类型的 可以过滤,IPC通信:共享内存 消息队列 信号灯集、ipcs命令 查看共享内存 消息队列 信号量、ipcs -s 查看信号量、ipcs -m 查看共享内存、ipcs -q 查看消息队列,共享内存,管道:在内核开辟的一块缓冲区,信号,进程间通信的方式。
这是一篇关于day4的思维导图,主要内容包括:设置线程属性,线程的同步,线程的互斥,线程。线程概念:为进一步减少处理器的空转时间,支持多处理器以及减少上下文切换开销,进程演化出线程,它是进程内独立的一条运行路线,是内核调度的最小单元。
这是一篇关于day3的思维导图,主要内容包括:守护进程,回收进程资源,孤儿进程和僵尸进程,exec族函数,结束进程,进程,Linux下的多任务机制。
day1
标准IO流
有几个标准IO流
流 是标准IO核心的操作对象
一个程序开始执行后 会自动打开三个流
标准输入流 stdin默认从键盘输入
标准输出流 strout 默认终端输出
标准错误输出流 strerr 默认向终端输出
标准输出流和标准错误输出流区别
标准输出流尊在缓存区 标准错误输出流不存在缓存区
标准流面试题
已知标准输出流有缓存 请列举缓存区内容出现在终端上的可能情况 1)遇见'\n' 2)缓存区满 3)流关闭 4)fflush强制刷新
文件IO
什么是文件IO
针对于文件的输入输出相关操作 //打开文件 读取文件 写入文件 关闭文件 //I input O output
文件IO的分类
1、标准IO//标准C库里面针对于文件的相关操作 属于库函数 2、LinuxIO//Linux系统提供的针对于文件的相关操作 属于系统调用
1. 系统调用 (1) 用户空间进程访问内核的接口 (2) 把用户从底层的硬件编程中解放出来 (3) 极大的提高了系统的安全性 (4) 使用户程序具有可移植性 2. 库函数 (1) 库函数为了实现某个功能而封装起来的API集合 (2) 提供统一的编程接口,更加便于应用程序的移植
标准文件IO存在缓存区
全缓存
//标准IO存在缓冲区 //不加'\n'就是全缓存 等缓存区满了以后再统一给操作系统处理 统一打印 //缓存区默认大小1024个字节
行缓存(面向终端才有)
//加上\n 全缓存变成行缓存 输出内容不会在缓存区停留 遇见'\n'就交给操作系统处理 然后打印在终端上 //注意:只有当输出的对象是终端的时候 才会有行缓存的概念
标准文件IO相关函数
1、fopen函数
1、fopen的返回值 是一个结构体指针 FILE* 在内核空间开辟 保存的是打开文件的相关信息 2、打开方式 "r" //只读 "r+" //可读可写 "w" //文件存在 清空 再以只写方式打开 //文件不存在 先创建 再以只写方式打开 "w+" //文件存在 清空 再以可读可写方式打开 //文件不存在 先创建 再以可读可写方式打开 "a" //文件存在 直接以追尾巴方式打开 //文件不存在 创建 再以追尾巴方式打开 "a+" //文件存在 以可读 和 追尾巴方式打开 //文件不存在 创建 以可读 和 追尾巴方式打开
功能:打开文件
参数说明
头文件及函数原型 #include <stdio.h> FILE *fopen(const char *path, const char *mode); //指针函数 (3)参数说明 const char *path //打开文件的名字(可以用相对路径和绝对路径修饰) const char *mode //打开文件的方式 //调用参考 FILE *fp = fopen("./test.c","r");//打开当前目录下的test.c文件,以只读的方式打开文件 FILE *fp = fopen("/home/linux/test.c","r");//用绝对路径,以只读的方式打开test.c文件 "r" //以只读的方式打开文件 read "r+" //以可读可写的方式打开文件 "w" //注意打开文件之前分下面两种情况 write //1. 如果文件不存在,创建文件,再以只写的方式打开 //2. 如果文件存在,先清空原来文件里的内容,再以只写的方式打开文件 "w+" //注意打开文件之前分下面两种情况 //1. 如果文件不存在,创建文件,再以可读可写的方式打开 //2. 如果文件存在,先清空原来文件里的内容,再以可读可写的方式打开文件 "a" //注意打开文件之前分下面两种情况 append //1.如果文件不存在,创建文件,再以追尾巴写的方式打开 //2.如果文件存在,以追尾巴写的方式打开文件 "a+" //注意打开文件之前分下面两种情况 //1.如果文件不存在,创建文件,再以可读和追尾巴写的方式打开 //2.如果文件存在,可读和追尾巴写的方式打开文件
返回值 FILE* 指针,文件流指针,FILE是一个结构体,每打开一个文件,内核 就 会开辟出一块空间,用来保存打开这个文件得到相关信息 成功: 返回 FILE*(非空)//流 流是标准IO的核心对象 失败: 返回 NULL
2、fgetc函数
1、fgetc的返回值 是读取的字符对应的ascii值 2、读取到文件末尾 返回的是-1 也就是EOF 可以用来判断是否读取到文件末尾
功能:每次读取一个字符(咬文嚼字读)
参数说明
头文件及函数原型 #include <stdio.h> int fgetc(FILE *stream); (3)参数说明 FILE *stream //fopen函数的返回值 //调用参考 char ch; //char可以理解为特殊的整数,返回值是读取出的字符对应的ascii的值 FILE *fp = fopen("hello.c","r"); ch = fgetc(fp);//读取一个字符,保存到字符变量ch中
返回值 成功: 实际读取的字符对应的ascii值 失败: //当读取到文件的尾巴的时候,返回值是EOF 也就是-1 返回值是 -1 返回 EOF(-1) #define EOF -1
3、fputc函数
返回值 成功 写入的字符对应的ascii值 失败 -1
功能:向文件中写入一个字符
参数说明
头文件及函数原型 #include <stdio.h> int fputc(int c, FILE *stream); (3) 参数说明: int c //将要被写入文件的字符,对应的ascii的值 FILE *stream //fopen返回值,写入文件流指针指向的那个文件 //调用参考 char ch = 'A'; //将要被写入文件的字符 fputc(ch,fp); //将ch中的字符写入fp指向的打开的文件 fputc('A', fp);//将'A'写入fp指向的打开的文件 fputc(65, fp);//将65对应的字符写入fp指向的打开的文件
4、fclose函数
关闭文件的同时 会清空缓存区
功能:关闭文件,同时会刷新缓存区,将缓存区的内容清空
参数说明
头文件及函数原型 #include <stdio.h> int fclose(FILE *fp); (3)参数说明: FILE *fp //fopen的返回值 //调用参考 fclose(fp);
返回值 成功: 返回 0 失败: 返回 -1
返回值: 成功: 返回写入的字符 失败: 返回 -1
练习1
请写出标准main函数的格式,使用命令行传递参数 ./a.out a.c b.c a.c 命令行上传递的被拷贝的文件名字 b.c 命令行上传递的拷贝到的文件名字 利用fgetc和fputc实现内容拷贝,将a.c的内容,拷贝到b.c文件中 //程序本质实现了cp命令 但是不能拷贝目录文件 #include"my.h" int main(int argc, const char *argv[]) { //1.容错判断 if(argc != 3) { printf("忘记传递参数!\n"); return -1; } //2.打开文件 FILE *fpr = fopen(argv[1],"r");//以可读形式打开要拷贝的文件 FILE *fwr = fopen(argv[2],"a");//以追尾巴的方式打开拷贝到的文件 //容错判断 if(fpr == NULL || fwr == NULL) { printf("fopen filed!\n"); return -1; } //3.循环拷贝字符 //方式一 #if 0 while(1) { char ch = fgetc(fpr); if(ch == EOF)//判断是否读到文件的末尾 { break; } fputc(ch,fwr); } #endif //方式二 char ch;//保存读取的字符 while((ch = fgetc(fpr)) != EOF)//不要少加括号 { fputc(ch,fwr); } //4.关闭文件 fclose(fpr); fclose(fwr); return 0; }
5、perror函数
参数说明
头文件及函数原型 #include <stdio.h> void perror(const char *s); //调用参考 perror("fopen函数失败原因"); //方便改错 (3) 参数说明: char *s //打印错误原因前的提示字符串
返回值 无
6、strerror函数
//面试问题,errno变量的作用是什么??? errno是Linux系统的全局变量,保存的是错误原因的具体编号,有了错误原因的具体编号,就可以调用strerror函数将具体的错误信息打印出来,进而分析并解决问题。
功能:打印错误提示信息的函数 linux系统里有一个全局变量,errno用来保存错误信息编号,错误输出信 息的打印根据错误编号而来
参数说明
头文件及函数原型 #include <string.h> #include <errno.h>//函数在哪个头文件不用背 man 或者 百度 char *strerror(int errnum); (3) 参数说明: int errnum //错误信息的编号 //调用参考 printf("失败原因:%s\n",strerror(errno)); //参数errno是一个全局变量,包含头文件之后可以直接进行使用
返回值: char * 错误原因字符串的首地址 "No such file or directory"
7、fgets函数
1、如何判断是否读取到文件末尾?fgets返回值 == NULL 时 说明读取到了文件的末尾 2、当读取的size(最多一次能读取的字符数)小于一行的大小时,能读取size-1个字符 要给'\0'留空间
功能:每次读取一行 (\n换行符作为读取的终止符)
参数说明
头文件及函数原型 #include <stdio.h> char *fgets(char *s, int size, FILE *stream); //为什么不是const char* s? (3)参数说明: char *s //用来保存读取出的一行内容,存放的位置 int size //读取的最大字符数 FILE *stream //fopen函数的返回值 //调用参考 char buf[100]; //用来保存读取出的一行内容 未初始化 全是随机数 fgets(buf, 100, fp); //调用一次,就可以读取一行字符串保存到buf数组中 fgets(buf, sizeof(buf), fp); //调用一次,就可以读取一行字符串保存到buf数组中
返回值: 成功: char * //读取出的那行字符串的首地址 失败: 返回 NULL ,读取到文件尾返回NULL
8、fputs函数
功能:每次写入一个字符串
参数说明
头文件及函数原型 #include <stdio.h> int fputs(const char *s, FILE *stream); (3)参数说明: const char *s //用来保存即将写入文件的字符串的首地址 FILE *stream //fopen函数的返回值 //调用 char buf[100] = "hello world"; fputs("xixi",fp);//将xixi写入到文件中 fputs(buf,fp); //将buf数组中的字符串写入到文件中
返回值: 成功: >= 0 //非负数 失败: 返回 EOF
练习2
请写出标准main函数的格式, 用命令行传参./a.out a.c b.c,利用fgets和fputs实现内容拷贝,将a.c的内容,拷贝到b.c文件中 用循环,每读取出一个字符串,就立刻将这个字符串写入另一个文件中,读一个,写一个 argv[0] //char*类型 保存字符串"./a.out"首地址 argv[1] //char*类型 保存字符串"a.c"首地址 argv[2] //char*类型 保存字符串"b.c"首地址 //本质实现了cp命令的部分功能 cp命令也是命令行传参 不能拷贝文件夹 cp可以 #include"my.h" int main(int argc, const char *argv[]) { char buf[100] = {0}; //0.容错判断 if(argc != 3) { printf("忘记传递参数!\n"); return -1; } //1.打开命令行传入的文件 FILE *fpr = fopen(argv[1],"r");//以只读方式打开拷贝的文件 FILE *fwr = fopen(argv[2],"w");//以只写方式打开拷贝到的文件 if(fpr == NULL || fwr == NULL) { perror("fopen failed"); return -1; } //2.循环读取并写入 while(fgets(buf,sizeof(buf),fpr) != NULL) { //说明读取到内容 写入文件中 fputs(buf,fwr); } //程序执行到这 说明fgets返回值为NULL //3.关闭文件 fclose(fpr); fclose(fwr); return 0; }
9、fread函数
功能: 以指定大小读取内容 每次读取一段(注意一段以块数为单位)
参数说明
头文件及函数原型 #include <stdio.h> size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream); char buf[100]; (3)参数说明: void *ptr //用来读出的内容存放的位置 size_t size //一块的大小(一块是一个基本单位) 以字节为单位 size_t nmemb //一次最多读取的块数 FILE *stream //fopen的返回值 //调用参考 char buf[100]; fread(buf, 1, 100, fp);//1 1块的大小是1个字节, 100 一次最多读取100块 fread(buf, 100, 1, fp);//100 1块的大小是100个字节, 1, 一次最多读取1块 fread(buf, 2, 50, fp); // 2 1块的大小是2个字节, 50, 一次最多读取50块 int ret = fread(buf, 2, 50, fp); //假设返回值ret is 5 代表实际读取了5块,共 5*2 10个字节
返回值: 成功: 实际读取的块数 实际读取的记录数 实际读取的对象数 就不能说,代表实际读取的字节数 失败: 小于等于0
10、fwrite函数
1、返回值是实际读取的块数 对象数 记录数 和 实际写入的块数 对象数 记录数 不能说是实际的字节数 2、fread返回值 > 0 说明读取到数据 3、linux文件分两种 (1)文本文件 可以用记事本打开 是有效字符 .c .h (2)二进制文件 不可以用记事本打开 乱码 a.out .bmp .jpg fgetc fgets 只能读取文本文件 fread 既能读取文本文件 也能读取二进制文件
功能:按块写
参数说明
参数说明: const void *ptr //即将写入文件数据存放的位置 size_t size //一块的大小 size_t nmemb //实际想要写入的块数 FILE *stream //fopen函数的返回值 //调用参考 char buf[100] = "hello"; fwrite(buf, 1, strlen(buf), fp);//sizeof(buf) == 100
返回值: 成功: 实际写入的块数 失败: 小于0
11、sprintf、fprintf函数
sprintf
功能:将格式化后的字符串写入到字符数组中
参数
char *str //保存的是字符数组的首地址 const char *format //格式化字符串的首地址 int fprintf(FILE *stream, const char *format, ...); // ... 多个参数
fprintf
功能:将格式化后的字符串写入到stream对应打开的文件中
参数
FILE *stream //fopen函数返回值 const char *format //格式化字符串的首地址 //sprintf 和 fprintf 就当作printf的格式和作用来使用 只是输出的位置有不同 所以导致前面加了一个参数而已
printf sprintf fprintf区别
1、printf是将格式化好的字符串输出到终端 sprintf是将格式化好的字符串输出到字符数组 fprintf是将格式化好的字符串输出到文件设备 2、sprintf 和 fprintf 不可以重定向 printf 可以重定向
12、memset函数
注意 memset是以字节为单位重置的 int a[5] = {0}; memset(a,67,5); 是a[0]的4个字节和a[1]的第1个字节重置成67
功能:内存设置函数,memset是一个初始化函数, 作用是将某一块内存中的全部设置为指定的值。
参数说明
头文件及函数原型 #include <string.h> void *memset(void *s, int c, size_t n);//从s地址开始 往后n个字节 都设置成c (3)参数说明: void *s //被设置的内存空间的起始地址 int c //要被设置的值 size_t n //从起始位置开始的前n个字节,被设置值 //调用参考 char buf[100] = "hello"; memset(buf, 0, sizeof(buf));//将整个buf数组都清空,每个字节都存储0 memset(buf, '#', 2); //将buf数组的前两个字节,设置为'#'对应的ascii值
返回值:被设置的内存空间的起始地址
13、fseek函数
fseek(fp,-100,SEEK_SET);//不合逻辑 fseek(fp,100,SEEK_END);//不合逻辑
功能:文件指针是FILE结构中的一个成员变量 移动文件指针的位置
参数说明
头文件及函数原型 #include <stdio.h> int fseek(FILE *stream, long offset, int whence); (3)参数说明: FILE *stream //fopen的返回值 long offset //偏移量 int whence //基准值,相对位置 SEEK_SET //文件头 SEEK_END //文件尾巴 SEEK_CUR //当前文件指针位置 //调用参考 //偏移量:正数--->向后移动 负数---->向前移动 fseek(fp,100,SEEK_SET); //相对文件起始位置向后移动100个字符 fseek(fp,-100,SEEK_END); //相对于文件尾位置向前移动100个字符 fseek(fp,100,SEEK_CUR); //current相对于当前文件指针的位置向后移动100个字符 fseek(fp,-100,SEEK_CUR); //相对于当前文件指针的位置向前移动100个字符 fseek(fp, 0, SEEK_SET); //将文件指针移动的文件首 fseek(fp, 0, SEEK_END); //将文件指针移动到文件的尾巴
返回值: 成功: 0 失败: EOF -1
14、ftell函数
功能: 获取文件指针的位置 文件指针的位置下标是从0开始的
参数说明
头文件及函数原型 #include <stdio.h> long ftell(FILE *stream); (3)参数说明: FILE *stream//fopen的返回值 //调用参考 long post = ftell(fp); printf("post is %ld\n",post);
返回值 成功:返回当前文件指针的位置 失败:EOF