I/O:标准IO(二)

一、标准IO操作函数

1.fgets、fputs

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

功能描述:将字符串s写入stream指向的文件中

返回数:成功写入文件中数据的字节数

int puts(const char* s)

功能描述:将字符串s写入终端;

返回值:成功写入终端的数据的字节数

char *fgets(char *s, int size, FILE *stream);

功能:从stream指向的文件中,吸收最多size个字节的数据,写入s指向的字符数组中去

返回值:成功吸收返回s,失败返回NULL

吸收最多size个字节,size中包含了1个字节的结束符,所以,最多能吸收的有效字节数为:size-1

使用fgets代替scanf

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>

//从终端吸入size-1个有效数据
//使用fgets代替scanf

char *getstr(char *buf,int size){
	char *res=fgets(buf,size,stdin);
	int len=strlen(buf); //获取buf的长度,结束符在len下标上,所以回车就在len-1下标上
	if(buf[len-1]=='\n')//这两句不写的话,就会有两个换行符号
		buf[len-1]='\0';
	return res;
}
int main(int argc, const char *argv[])
{
	char buf[32]="0";
	printf("%s\n",getstr(buf,32));
	return 0;
}

2.fwrite、fread

fwrite和fread是数据流

文件流:任意数据,都会以字符串,然后再以字符串二进制的形式,写入文件中

数据流:所有数据,都以二进制的形式写入文件中

size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream);

功能描述:将ptr指向的内存空间上,总共 size * nmemb 个字节的数据,写入stream指向的文件中

注意:将普通数据写入后,文件中呈现二进制状态

 size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);

功能描述:读取stream指向的文件,总共读取nmemb个数据,每个数据大小为size,将这些数据写入 ptr指向的内存中

注意:fwrite、fread会强制读写 size*nmemb字节的数据,无论是否有那么多数据,成为模块化读写

int feof(FILE *stream);

功能描述:测试stream指向的文件,是否读写到了结束符,如果到了结束符,则返回非0(实际上是1),没到结束符返回0

注意:

1.因为在读取最后一个模块的时候,如果最后一个模块大小,没有我们设定的读取模块那么大的话,就会将文件结束符一起读取到模块里面去,然后通过feof判定文件读取结束,最后个模块就没有通过fwrite写出去

2.如果使用fwrite、fread配合feof去实现文件拷贝功能(一起其他类似的功能)的时候,如果模块大小没有计算精确的话,容易导致最后一个模块出问题

#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
int main(int argc, const char *argv[])
{
    FILE* rfp = fopen(argv[1],"r");
    FILE* wfp = fopen(argv[2],"w");
    if(rfp==NULL || wfp==NULL){return 1;}

    char buf[100] = {0};
    while(1){
        fread(buf,100,1,rfp);
        if(feof(rfp)==1){break;}
        fwrite(buf,100,1,wfp);
    }


    fclose(rfp);
    fclose(wfp);
    return 0;
}

3.文件光标偏移函数fseek

int fseek(FILE *stream, long offset, int whence);

功能:将stream指向的文件光标进行偏移,偏移量为offset个字节,offset为正表示从左往右偏,为负表示从右往左偏。whence决定偏移的起点

SEEK_SET:从文件开头开始偏移

SEEK_CUR:从文件当前光标位置开始偏移

SEEK_END:从文件末尾开始偏移

使用函数,修改图片

#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
int main(int argc, const char *argv[])
{
    FILE* fp = fopen("rising_freedom.bmp","r");

    fseek(fp,2,SEEK_SET);
    int bmp_size = 0;
    fread(&bmp_size,4,1,fp);
    printf("文件大小为 %d 字节\n",bmp_size);

    int w = 0,h = 0;
    fseek(fp,18,SEEK_SET);
    fread(&w,4,1,fp);
    fread(&h,4,1,fp);
    printf("图像尺寸为:%d * %d\n",w,h);

    fclose(fp);

    fp = fopen("rising_freedom.bmp","r+");

    fseek(fp,54,SEEK_SET);
    // bmp 图片默认像素格式是 bgr的
    unsigned char pix[3] = {0,0,255};
    for(int i=0;i<w;i++){
        for(int j=0;j<h;j++){
            fwrite(pix,3,1,fp);
        
        }
    }


    fclose(fp);
    return 0;
}

4.标准IO的缓存区

printf函数,缓存刷新机制

1:遇到回车自动刷新

2:缓存区满自动刷新 

3:程序结束自动刷新

4:IO切换缓存刷新

5:描述符关闭缓存刷新

6:使用 fflush函数强制刷新特定缓存区

4.1缓存区的分类

1:行缓存:printf就是行缓存

2:全缓存:FILE*指向的非终端文件,都是全缓存,全缓存刷新机制就比行缓存缺一个回车

3:无缓存:没有缓存,stderr,标准错误流是无缓存

4.2scanf的缓存区 

从键盘输入的所有数据,都会在缓存区,敲击回车,表示输入结束,这个回车也在缓存区

scanf吸收成功,就会将数据从缓存区中取走

        吸收失败则会一直留在缓存区

所以,我们要通过语句 while(getchar()!='\n') 来清理所有缓存

int a=0;
scanf("%d",&a);
while(getchar()!='\n');//用于吸收垃圾字符

4.3缓存区大小的计算

FILE 结构体里面,有2个指针

_IO_buf_base:缓存区起始地址

_IO_buf_end:缓存区尾地址

所以,只要拿缓存区尾地址 - 缓存区起始地址 = 缓存区大小了

注意:如果想要计算缓存区的大小的话,我们必须先激活一下使用这个缓存区的文件流,也就是做一下IO操作

行缓存:1024字节

全缓存:4096字节

无缓存:0字节

#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
int main(int argc, const char *argv[])
{
	printf("hello\n");//先激活缓存区的文件流
	printf("行缓存大小为:%ld\n",stdout->_IO_buf_end - stdout->_IO_buf_base);
	
	FILE* fp = fopen("./demo11.txt","w");
	
	fputc('x',fp);
	printf("全缓存大小为:%ld\n",fp->_IO_buf_end - fp->_IO_buf_base);

	fclose(fp);

	perror("123");
	printf("无缓存大小为:%ld\n",stderr->_IO_buf_end - stderr->_IO_buf_base);
	return 0;
}

二、作业

1.使用fwrite、fread将一张随意的bmp图片,修改成德国的国旗

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
int main(int argc, const char *argv[])
{
	FILE *fp=fopen("1.bmp","r");
	int w=0,h=0;
	fseek(fp,18,SEEK_SET);
	fread(&w,4,1,fp);
	fread(&h,4,1,fp);
	printf("图像尺寸为:%d * %d\n",w,h);
	fclose(fp);

	fp=fopen("1.bmp","r+");
	fseek(fp,54,SEEK_SET);
	unsigned char pix1[3]={0,0,0};
	unsigned char pix2[3]={0,0,255};
	unsigned char pix3[3]={128,255,255};
	int i=0,j=0;
	for(i=0;i<w/3;i++){
		for(j=0;j<h;j++){
			fwrite(pix3,3,1,fp);
		}
	}
	for(i=w/3;i<w/3*2;i++){
		for(j=0;j<h;j++){
			fwrite(pix2,3,1,fp);
		}
	}
	for(i=w/3*2;i<w;i++){
		for(j=0;j<h;j++){
			fwrite(pix1,3,1,fp);
		}
	}
	fclose(fp);
	return 0;
}

2.使用提供的getch函数,编写一个专门用来输入密码的函数,要求输入密码的时候,显示 * 号,输入回车的时候,密码输入结束

#include <termios.h>
#include <unistd.h>
#include <sys/types.h>
#include <stdio.h>
#include <assert.h>
#include <string.h>

int getch(){
	int c=0;
	struct termios org_opts, new_opts;
	int res=0;
	res=tcgetattr(STDIN_FILENO, &org_opts);
	assert(res==0);

	new_opts = org_opts;

	new_opts.c_lflag &= ~(ICANON | ECHO | ECHOE | ECHOK | ECHONL | ECHOPRT | ECHOKE | ICRNL);
	tcsetattr(STDIN_FILENO, TCSANOW, &new_opts);

	c=getchar();

	res=tcsetattr(STDIN_FILENO, TCSANOW, &org_opts);
	assert(res==0);
	return c;
}
int main(){
	char a[32]="0";
	int i;
	for(i=0;a[i]!='\n';i++){
		a[i]=getch();
		if(a[i]=='\n')
			break;
		printf("*");	
	}
	printf("%s",a);
	putchar(10);
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

kitex 入门和基于grpc的使用

&#x1f4d5;作者简介&#xff1a; 过去日记&#xff0c;致力于Java、GoLang,Rust等多种编程语言&#xff0c;热爱技术&#xff0c;喜欢游戏的博主。 &#x1f4d7;本文收录于kitex系列&#xff0c;大家有兴趣的可以看一看 &#x1f4d8;相关专栏Rust初阶教程、go语言基础系…

动态规划--(算法竞赛、蓝桥杯)--二维费用背包

1、B站视频链接&#xff1a;E15 背包DP 二维费用背包_哔哩哔哩_bilibili #include <bits/stdc.h> using namespace std; int f[101][101]; //f[j][k]第i件物品&#xff0c;体积<j,重量<k的最大价值int main(){int n,V,W;//物品、容量、承重int v,w,val;//体积、重…

redis实现分布式全局唯一id

目录 一、前言二、如何通过Redis设计一个分布式全局唯一ID生成工具2.1 使用 Redis 计数器实现2.2 使用 Redis Hash结构实现 三、通过代码实现分布式全局唯一ID工具3.1 导入依赖配置3.2 配置yml文件3.3 序列化配置3.4 编写获取工具3.5 测试获取工具 四、运行结果 一、前言 在很…

施耐德M340和M200 Modbus 通讯实现

Unity平台下M340和M200通过Modbus TCP通讯 两者通过RJ45连接&#xff0c;M340内IO scanning配置&#xff1a; IP address是各个M200的地址&#xff0c;通过这个配置&#xff0c;可以将各server的指定数据区映射到M340的内部数据区。 相比于M200作Modbus TCP Client&#xff0…

Java SE 1.基础常识

1.计算机语言 1.机器语言&#xff1a; 二进制的0和1组成的编码2.汇编语言&#xff1a; 英文标识符组成的编码3.高级语言&#xff1a; 接近自然语言 2.Java技术平台 1.JAVA SE 1.Java Platform Standard Edition&#xff0c;Java标准版 1.JDK 1.Java开发工具集&#xff1a;包括J…

Python实现双向链表:从基础到应用

一、引言 双向链表是一种比单向链表更复杂的数据结构&#xff0c;每个节点除了包含数据和指向下一个节点的指针外&#xff0c;还包含一个指向前一个节点的指针。这种结构使得我们可以从链表的任何节点开始&#xff0c;向前或向后遍历链表。 目录 一、引言 二、节点定义 三、…

黑猫的牌面

解法&#xff1a; 桶 #include <iostream> #include <vector> #include <algorithm> using namespace std; #define endl \nint main() {ios::sync_with_stdio(false);cin.tie(0); cout.tie(0);vector<int> tong(1001);int t 4;int k, pai;long lon…

vue3+ts+vite使用mock数据

安装以下命令 npm i vite-plugin-mock --save-dev npm i mockjs --save-dev 在根路径下创建mock文件夹 mock\user.ts const menuList [{path: /system,component: Layout,name: system,meta: {title: 系统管理,icon: Setting,roles: [sys:manage]},children: [{path: /depar…

leetcode--接雨水(双指针法,动态规划,单调栈)

目录 方法一&#xff1a;双指针法 方法二&#xff1a;动态规划 方法三&#xff1a;单调栈 42. 接雨水 - 力扣&#xff08;LeetCode&#xff09; 黑色的是柱子&#xff0c;蓝色的是雨水&#xff0c;我们先来观察一下雨水的分布情况: 雨水落在凹槽之间&#xff0c;在一个凹槽的…

前端Vue3项目如何打包成Docker镜像运行

将前端Vue3项目打包成Docker镜像并运行包括几个主要步骤&#xff1a;项目打包、编写Dockerfile、构建镜像和运行容器。下面是一个基本的流程&#xff1a; 1. 项目打包 首先&#xff0c;确保你的Vue3项目可以正常运行和打包。在项目根目录下执行以下命令来打包你的Vue3项目&am…

《PyTorch深度学习实践》第十三讲RNN进阶

一、 双向循环神经网络&#xff08;Bidirectional Recurrent Neural Network&#xff0c;BiRNN&#xff09;是一种常见的循环神经网络结构。与传统的循环神经网络只考虑历史时刻的信息不同&#xff0c;双向循环神经网络不仅考虑历史时刻的信息&#xff0c;还考虑未来时刻的信息…

14:00面试,14:07就出来了,问的问题过于变态了。。。

我从一家小公司转投到另一家公司&#xff0c;期待着新的工作环境和机会。然而&#xff0c;新公司的加班文化让我有些始料未及。虽然薪资相对较高&#xff0c;但长时间的工作和缺乏休息使我身心俱疲。 就在我逐渐适应这种高强度的工作节奏时&#xff0c;公司突然宣布了一则令人…

Leetcode : 数组拆分 I

给定长度为 2n 的整数数组 nums &#xff0c;你的任务是将这些数分成 n 对, 例如 (a1, b1), (a2, b2), ..., (an, bn) &#xff0c;使得从 1 到 n 的 min(ai, bi) 总和最大。返回该 最大总和 。 思路&#xff1a;2n长度数组&#xff0c;共有n对&#xff0c;原有思路暴力破解法…

centos7安装jdk8、maven3.9

jdk8安装 下载安装包 下载安装包地址 下载的时候需要注册oracle账号&#xff0c;没有的可以使用现成的 账号&#xff1a;2028056560qq.com 密码&#xff1a;Oracle1234 放到指定的目录 解压 tar -xvzf jdk-8u401-linux-i586.tar.gz 配置环境变量 添加JAVA_HOME变量 vim…

Linux之gcc和makefile的使用详细解析

个人主页&#xff1a;点我进入主页 专栏分类&#xff1a;C语言初阶 C语言进阶 数据结构初阶 Linux C初阶 算法 欢迎大家点赞&#xff0c;评论&#xff0c;收藏。 一起努力&#xff0c;一起奔赴大厂 目录 一.gcc/g安装 二.gcc运行代码 三.gcc是如何完成的 3.1预处…

【Leetcode每日一刷】贪心算法|122.买卖股票的最佳时机 II、55. 跳跃游戏

一、122.买卖股票的最佳时机 II 力扣题目链接 &#x1f984;解题思路&#xff1a; 首先需要明确的几个点&#xff1a; 当前只能有最大一支股票每一天操作只能3选1&#xff1a;买or卖or休息 此外&#xff0c;对于贪心&#xff0c;总有像下面图示的一种直觉&#xff1a;如果…

11.盛最多水的容器

题目&#xff1a;给定一个长度为 n 的整数数组 height 。有 n 条垂线&#xff0c;第 i 条线的两个端点是 (i, 0) 和 (i, height[i]) 。 找出其中的两条线&#xff0c;使得它们与 x 轴共同构成的容器可以容纳最多的水。 返回容器可以储存的最大水量。 解题思路&#xff1a;可以…

算法打卡day5|哈希表篇01|Leetcode 242.有效的字母异位词 、19.删除链表的倒数第N个节点、202. 快乐数、1. 两数之和

哈希表基础知识 哈希表 哈希表关键码就是数组的索引下标&#xff0c;然后通过下标直接访问数组中的元素&#xff1b;数组就是哈希表的一种 一般哈希表都是用来快速判断一个元素是否出现集合里。例如要查询一个名字是否在班级里&#xff1a; 要枚举的话时间复杂度是O(n)&…

【开源】JAVA+Vue.js实现天沐瑜伽馆管理系统

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 数据中心模块2.2 瑜伽课程模块2.3 课程预约模块2.4 系统公告模块2.5 课程评价模块2.6 瑜伽器械模块 三、系统设计3.1 实体类设计3.1.1 瑜伽课程3.1.2 瑜伽课程预约3.1.3 系统公告3.1.4 瑜伽课程评价 3.2 数据库设计3.2.…

【C语言】动态内存管理常用函数

前言 我们在之前学习的数组开辟的空间是固定不变的&#xff0c;有时候我们需要的空间⼤⼩在程序运⾏的时候才能知道~ c语言中的动态内存开辟&#xff0c;让程序员⾃⼰可以根据实际需求申请和释放相应空间&#xff0c;这使得空间的开辟变得灵活了许多。 欢迎关注个人主页&#x…
最新文章