IO进程线程day2(2023.7.26)

news/2025/3/20 11:52:49/

一、Xmind整理:

二、课上练习:

练习1:全缓冲

//由于编译器优化,只打开不操作,此时不会真正申请缓冲区。
fputc('a', fp);
printf("%ld\n", fp->_IO_buf_end - fp->_IO_buf_base );

刷新条件:
1.缓冲区满 (要多写一个后才能刷新前4096个
2.fflush函数,强制刷新输出流缓冲区
   #include <stdio.h>
   int fflush(FILE *stream);

3.关闭流指针   fclose
4.主函数调用return
5.调用exit函数退出程序

6.输入输出转换

7.……

功能:目前只要理解能退出程序即可
原型:

#include <stdlib.h>
void exit(int status);

参数:

int status:目前随便填一个int类型整数即可,例如 1 2 0
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main(int argc, const char *argv[])
{FILE* fp=fopen("./fullbuf.txt","w");if(NULL==fp){perror("fopen");return -1;}/*由于编译器优化,只打开不操作,此时不会真正申请缓冲区。fputc('a',fp);printf("%ld\n",fp->_IO_buf_end - fp->_IO_buf_base);*/int i=0;while(i<4096+1){fputc('a',fp);//先放到缓存区中i++;}while(1){}fclose(fp);return 0;
}

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main(int argc, const char *argv[])
{FILE* fp=fopen("./fullbuf.txt","w");if(NULL==fp){perror("fopen");return -1;}/*由于编译器优化,只打开不操作,此时不会真正申请缓冲区。fputc('a',fp);printf("%ld\n",fp->_IO_buf_end - fp->_IO_buf_base);*//*int i=0;while(i<4096+1){fputc('a',fp);//先放到缓存区中i++;}fputc('b',fp);fflush(fp);fputc('c',fp);fflush(fp);fputc('d',fp);fflush(fp);*/fputc('e',fp);exit(0);while(1){}fclose(fp);return 0;
}

练习2:行缓冲

printf("size=%ld\n", stdout->_IO_buf_end - stdout->_IO_buf_base);

刷新条件:
1.缓冲区满 (要多写一个后才能刷新前4096个
2.fflush函数,强制刷新输出流缓冲区
   #include <stdio.h>
   int fflush(FILE *stream);

3.关闭流指针   fclose
4.主函数调用return
5.调用exit函数退出程序

6.遇到\n字符

7.输入输出转换

功能:目前只要理解能退出程序即可
原型:

#include <stdlib.h>
void exit(int status);

参数:

int status:目前随便填一个int类型整数即可,例如 1 2 0
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main(int argc, const char *argv[])
{char s1[20]="";scanf("%s",s1);//从终端获取字符串,默认使用的就是stdin流指针printf("s1=%s\n",s1);//将数据打印到终端,默认使用的就是stdout流指针char s2[20]="";fscanf(stdin,"%s",s2);//stdin代表从终端获取数据,此时与scanf完全等价fprintf(stdout,"s2=%s\n",s2);//stdout代表将数据输出到终端,此时与printf完全等价return 0;
}

练习3:无缓冲

无刷新条件

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main(int argc, const char *argv[])
{/*fputc('b',stderr);printf("size=%ld\n",stderr->_IO_buf_end - stderr->_IO_buf_base);*/fputc('d',stderr);perror("aaaa");while(1);return 0;
}


练习4:fputs

功能:将字符串输出到指定的文件中; fputs不会自动补充\n
原型:

#include <stdio.h>
int fputs(const char *s, FILE *stream);
int puts(const char *s);     
char str[20] = "hello";  
puts(str);

参数:

char *s:指定要输出的字符串的首地址;       
FILE *stream:流指针;

返回值:

成功,返回非负数>=0;
失败,返回EOF;

练习5:fgets

功能:从指定文件中获取字符串

1.最多获取size-1个字节,因为fgets函数在停止读取后,会在有效字符的最后一个字节补\0

2.会获取空格;会获取\n字符

3.遇到\n字符后停止读取,且会获取\n字符

原型:

#include <stdio.h>
char *fgets(char *s, int size, FILE *stream);

参数:

char *s:存储获取到的字符串;
int size:size-1
FILE *stream:流指针;

返回值:

成功,返回存储数据空间的首地址;
失败,返回NULL;
当读取到文件结尾,且没有任何数据被读取出来,返回NULL;

在文件中有如下数据:123456789, char str[9];                 会出现什么情况:A D

                                    fgets(str, 10, fp);

                                    printf("str=%s", str);

A. 123456789              B.123456789乱码               C.12345678               D.段错误

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main(int argc, const char *argv[])
{//打开文件,以读的方式打开文件FILE* fp=fopen("./fputs.txt","r");if(NULL==fp){perror("fopen");return -1;}char buf[20]="";fgets(buf,20,fp);printf("buf=%s\n",buf);fgets(buf,20,fp);printf("buf=%s\n",buf);fclose(fp);return 0;
}

1.使用fgets和fputs实现文件拷贝

2.使用fgets实现计算一个文件的大小

第一题:
#include <stdio.h>
#include <head.h>
int main(int argc, const char *argv[])
{FILE* fp_r = fopen("./01_fopen.c", "r");if(NULL == fp_r){ERR_MSG("fopen");return -1;}FILE* fp_w = fopen("./copy.c", "w");if(NULL == fp_w){ERR_MSG("fopen");return -1;}//读一次,写一次,直到文件读取完毕                  char buf[128] = "";while(1){if(fgets(buf, sizeof(buf), fp_r) == NULL)break;fputs(buf, fp_w);}printf("拷贝完毕\n");if(fclose(fp_r) < 0){ERR_MSG("fclose");return -1;}fclose(fp_w);return 0;
}
第二题:
#include <stdio.h>
#include <head.h>
int main(int argc, const char *argv[])
{FILE* fp_r = fopen("./01_fopen.c", "r");                          if(NULL == fp_r){ERR_MSG("fopen");return -1;}//循环读取,统计字节数char str[20] = "";int count = 0;while(1){if(fgets(str, sizeof(str), fp_r) == NULL)break;count+=strlen(str);     //fgets停止读取后会自动在结尾补充\0}printf("count = %d\n", count);if(fclose(fp_r) < 0){ERR_MSG("fclose");return -1;}return 0;
}

练习6:fwrite

功能:将数据的二进制形式写入到指定的文件中;
          二进制形式--> 将数据拆分成一个一个的字节并转换成字符形式写入文件中

原型:

#include <stdio.h>
char *fgets(char *s, int size, FILE *stream);

参数:

 void *ptr:指定要输出的数据的首地址,是void*类型,代表任意类型,所以可以输出任意类型数据;例如字符串char*  整型数组int*  构造类型size_t size:每个数据所占的字节数大小;例如:要输出的数据为int类型,则size==4要输出的数据为short类型,则size==2要输出的数据为char类型,则size==1要输出的数据为构造类型,则size==sizeof(struct 结构体名);size_t nmemb:指定要输出的数据个数,注意是个数,不是字节数总大小为size*nmemb; 具体以什么作为整体无所谓,只要输出的结果总大小相同即可;FILE *stream:流指针;

返回值:

成功,返回成功输出的数据个数,即nmemb;
失败, =0或者<nmemb

注意:

总大小为size*nmemb; 具体以什么作为整体无所谓,只要输出的结果总大小相同即可;

1.将整个数据作为整体,输出/输入一个数据 -->size = sizeof(数据), nmemb=1;

2.将一个字节作为整体,输出/输入sizeof个数据 -->size =1, nmemb = sizeof(数据)

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main(int argc, const char *argv[])
{FILE* fp=fopen("./fwrite.txt","w");if(NULL==fp){perror("fopen");return -1;}printf("fopen success\n");int arr[3]={48,49,50};//fprintf(fp,"%d",a);size_t res=0;res=fwrite(arr,4,3,fp);printf("res=%ld\n",res);fclose(fp);return 0;
}

 

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <head.h>
typedef struct a
{char name[18];int score;
}_A;
int main(int argc, const char *argv[])
{FILE* fp=fopen("fwrite.txt","w");if(NULL==fp){perror("fopen");return -1;}printf("fopen success\n");_A t;strcpy(t.name,"zhangsan");t.score=48;size_t res=fwrite(&t,sizeof(_A),1,fp);printf("res=%ld\n",res);_A brr[2]={{"zahngsan",65},{"wangwu",66}};//将数组中的单个元素作为整体,共输出两个数据,每个数据大小为sizeof(_A)res=fwrite(brr,sizeof(_A),2,fp);printf("res=%ld\n",res);/*//将brr当做整体,输出一个数据,每个数据的大小为sizeof(brr)res=fwrite(brr,sizeof(brr),1,fp);printf("res=%ld\n",res);*//*int arr[3]={48,49,50};//fprintf(fp."%d",a);size_t res=0;res=fwrite(arr,4,3,fp);printf("res=%ld\n",res);*/ fclose(fp);return 0;
}

练习7:fread

功能:将数据的二进制形式从指定文件中读取出来,转换成对应的数据

原型:

#include <stdio.h>
size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);

参数:

void *ptr:指定要将数据存储到什么位置,填对应位置的首地址。void*类型;
size_t size:每个数据所占的字节数大小;例如:
要输出的数据为int类型,则size==4
要输出的数据为short类型,则size==2
要输出的数据为char类型,则size==1
要输出的数据为构造类型,则size==sizeof(struct 结构体名);
size_t nmemb:指定要读取的数据个数,注意是个数,不是字节数
总大小为size*nmemb; 具体以什么作为整体无所谓,只要输出的结果总大小相同即可;
FILE *stream:流指针;

返回值:

成功,返回成功读取的数据个数,即nmemb;
失败或者读取到文件结尾的时候, =0或者<nmemb

练习8:fseek

功能:修改文件偏移量,到指定位置

原型:

#include <stdio.h>
int fseek(FILE *stream, long offset, int whence);

参数:

FILE *stream:指定要修改哪个文件的偏移量;
long offset: 距离whence参数指定的偏移量。往前偏移填负数, 往后偏移填正数
int whence:SEEK_SET,  文件开头位置SEEK_CUR,  文件当前位置SEEK_END   文件结尾位置

返回值:

 成功,返回0;失败,返回-1,更新errno;//修改偏移量到文件开头int res = fseek(fp, 0, SEEK_SET);   将文件偏移量修改到开头:void rewind(FILE *stream); --->等价于 fseek(fp, 0, SEEK_SET);   

注意:

任务1:若偏移量在文件开头,能否继续往前偏移 ---> 不行

任务2:若偏移量在文件结尾,能否继续往后偏移 ---> 可以

①若是以w w+ r+的方式打开,往结尾后偏移10个字节后写入,则会从第10个字节写入数据,且前面空余部分会自动补充^@

2.若是以a a+方式打开,往后偏移10个字节后写入,从文件结尾的最后一个有效字符的后面写入。

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main(int argc, const char *argv[])
{FILE* fp=fopen("./fseek.txt","w+");if(NULL==fp){perror("fopen");return -1;}fputc('a',fp);fputc('b',fp);fputc('c',fp);int res=fseek(fp,0,SEEK_SET);printf("res=%d\n",res);int c=0;c=fgetc(fp);printf("c=%c %d\n",c,c);return 0;
}

练习9:ftell

功能:获取文件当前位置距离文件开头的偏移量

原型:

#include <stdio.h>
long ftell(FILE *stream);

返回值:

成功,返回文件当前位置距离文件开头的偏移量;
失败,返回-1,更新errno;将文件偏移量修改到结尾,获取文件偏移量的值,就是文件大小。    
fseek(fp, 0, SEEK_END);
long size = ftell(fp); 

三、课后作业:

1. 使用fgets实现计算一个文件有几行

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main(int argc, const char *argv[])
{FILE* fp=fopen("./fgets.txt","r");if(NULL==fp){perror("fopen");return -1;}fseek(fp, 0, SEEK_END);if(ftell(fp) == 0)return 0;fseek(fp, 0, SEEK_SET);char buf[32] = "";int count = 0;while(1){if(fgets(buf, sizeof(buf), fp) == NULL){break;}if('\n' == buf[strlen(buf)-1])count++;}if(buf[strlen(buf)-1] != '\n')count++;printf("文件共有%d行\n",count);return 0;
}


2. 用fread和fwrite实现文件拷贝 

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main(int argc, const char *argv[])
{FILE *fp = fopen("copy1.txt","r");if(NULL == fp){fprintf(stderr,"__%d__",__LINE__);perror("fopen");return -1;}   FILE *fp_w = fopen("copy2.txt","w");if(NULL == fp_w){   fprintf(stderr,"__%d__",__LINE__);perror("fopen");return -1;}   char str[10];while(1){memset(str,0,sizeof(str));if(fread(str,1,1,fp) == 0)break;fwrite(str,1,1,fp_w);}fclose(fp);fclose(fp_w);return 0;
}


http://www.ppmy.cn/news/980968.html

相关文章

VRRP技术和浮动路由(第二十六课)

VRRP技术和浮动路由(第二十六课) 一、浮动路由 1、浮动路由概述 1&#xff09;浮动路由是什么 -浮动路由又称为路由备份&#xff0c;由两条或多条链路组成浮动路由 -浮动路由指配置两条静态路由&#xff0c;这两条静态路由的目的地址相同&#xff0c;但是下一跳地址不同两…

学习笔记--TCP/IP协议

TCP/IP协议 TCP (Transmission Control Protocol)传输控制协议&#xff0c;传输层协议。 一、协议的分层 ISO网络层分为7层 二、分层的作用 具体通信情况&#xff1a; 三、报文传输 三次握手连接&#xff0c;四次挥手释放 参考链接&#xff1a; https://zhuanlan.zhih…

Java 强制类型转换原理(父类转子类、子类转父类)

在Java中&#xff0c;对象的强制转换&#xff08;也称为类型转换&#xff09;是将一个对象的引用转换为另一个类的引用&#xff0c;前提是这两个类之间存在继承或实现关系。强制转换可能会导致运行时异常&#xff0c;因为在转换的过程中&#xff0c;如果对象的实际类型与转换的…

图为科技T501赋能工业机器人 革新传统工业流程

工业机器人已成为一个国家制造技术与科技水平的重要衡量标准&#xff0c;在2019年&#xff0c;中国工业机器人的组装量与产量均位居了全球首位。 当前&#xff0c;工业机器人被广泛用于电子、物流、化工等多个领域之中&#xff0c;是一种通过电子科技和机械关节制作出来的智能机…

Kubernetes ConfigMap - Secret - 使用ConfigMap来配置 Redis

目录 ConfigMap &#xff1a; 参考文档&#xff1a;k8s -- ConfigMap - 简书 (jianshu.com) K8S ConfigMap使用 - 知乎 (zhihu.com) ConfigMap的作用类型&#xff1a; 可以作为卷的数据来源&#xff1a;使用 ConfigMap 来配置 Redis | Kubernetes 可以基于文件创建 Conf…

Qt : day2

1. #include "widget.h"Widget::Widget(QWidget *parent): QWidget(parent) {qDebug() << this->size(); //获取当前页面尺寸this->setFixedSize(500, 600); //设置固定尺寸this->setWindowTitle("聊天框"); //设置窗口标题thi…

【Matlab】基于长短期记忆网络的数据分类预测(Excel可直接替换数据)

【Matlab】基于长短期记忆网络的数据分类预测(Excel可直接替换数据) 1.模型原理2.数学公式3.文件结构4.Excel数据5.分块代码6.完整代码7.运行结果1.模型原理 “基于长短期记忆网络的数据分类预测”是一种利用长短期记忆网络(Long Short-Term Memory, LSTM)进行数据分类任务…

16_LinuxINPUT子系统

目录 input子系统简 input驱动编写流程 注册input_dev 上报输入事件 input_event结构体 按键input驱动程序编写 编写测试APP 运行测试 input子系统简 按键、鼠标、键盘、触摸屏等都属于输入(input)设备,Linux内核为此专门做了一个叫做input子系统的框架来处理输入事件。…