【八组输入输出你都了解多少】

2023-11-01

前言

在这里插入图片描述
大家好,我是熊猫,今天我们来了解了解C语言<stdio.h>头文件中的那些输入输出函数。
在开始之前,大家可以先回想回想自己了解到的输入输出函数都有哪些,
我想很多朋友第一反应为scanf和printf,
再之后可能会有putchar,getchar,以及puts和gets。
不过我们今天要讲解的是包含上面这部分以及从文件读取和写入的各种常用函数,下面我们进入正题。


一、总览

我们如果按照使用范围分类的话可以分为两大类:
1.只能从标准输入流(stdin)输入数据,只能往标准输出流(stdout)输出数据;
2.可以从任何流中读取和写入数据。
补充:这里我们要先理解:输入就是从流中读取数据,输出就是往流中写入数据。(输出到屏幕 == 写到屏幕上)


(一)只能从标准流(std)中输入和输出数据

scanf、printf;
getchar、putchar;
gets、puts。

(二)可以从所以流中读取和写入数据

fscanf、fprintf;
fgetc、fputc;
fputs、fgets;
fread、fwrite;

(三)只能从字符串中读取和写入数据

sscanf、sprintf;


二、详细描述

下面我们并不会按照上面的分类进行讲解,而是,
将同一种形式的函数放在一起分析,
通过这样的对比更有利于我们理解和记忆。


(一)scanf、fscanf、sscanf

函数原型:
int scanf (const char* const _Formet, …);
int fscanf (const FILE* const _Stream, const char* const _Formet, …);
int sscanf ( const char * s, const char * format, …);

1.scanf

int scanf (const char* const _Formet, …);

看到了我们平时使用的scanf会不会有一种既熟悉又陌生的感觉,
返回值我们应该都知道,是输入数据的个数,不过,
上面的参数列表里的是一个格式字符串,以及省略号。
哎~!我平时就是写上需要输入的数据,然后在后面写上变量的地址,
他怎么只要一个格式字符串呢?
其实,这个格式字符串就是我们平时所写的需要输入的数据的格式,后面的省略号表示随便你输入多少数据,具体是根据格式字符串来定的。

示例:

#include<stdio,h>

int main()
{
	int a = 0;
	float fl = 0.0f;
	char ch = 0;
	printf("请输入一个整形,浮点型和字符型数据:\n");
	int con = scanf("%d %f %c", &a, &fl, &ch);
	//前面的字符串是我们我们需要输入的数据的类型,后面是数据需要存放的地址

	//这里要注意scanf的返回值:输入数据的个数,
	//是输入数据的个数而不是输入字符的个数
	printf("scanf返回值:%d\n\n", con);

	char str[20] = {0};
	printf("请输入字符串:\n");
	con = scanf("%s", str);
	//这里只输入了一个数据:一个字符串
	printf("scanf返回值:%d\n", con);
	return 0;
}

运行实例:
在这里插入图片描述

补充:
1.scanf只能从标准输入流(stdin)–也就是键盘中读取数据。
2.这里如果输入格式出错,就会返回EOF(EOF是文件结束标志,在VS中的定义是 - 1),所以我们可以在输入的时候进行判断:
假设输入三个数据,如果返回值 == 3、或者返回值 != EOF,就说明我们输入正确了。


2.fscanf

int fscanf (const FILE* const _Stream, const char* const _Formet, …);

fscanf的返回值也是输入数据的个数,
与scanf的区别只是前面多了一个 流(stream),
我们平时描述数据的传输时会形象的描述说数据从发送方流向了接收方,就会说的流动就是数据流,
fscanf是从流里面读取数据,可以是标准输入流(stdin),亦可以是文件流(我们写入数据到文件流使用的是文件指针)

>示例:
int main()
{
	FILE* pf = fopen("test.txt", "r");
	//以只读的方式打开文件
	int a = 0;
	float fl = 0.0f;
	char ch = 0;
	printf("从文件test.txt中读取一个整形,浮点型和字符型数据:\n");
	fscanf(pf, "%d %f %c", &a, &fl, &ch);
	printf("输出:%d %f %c\n\n", a, fl, ch);

	char str[20] = { 0 };
	printf("从文件test.txt中读取一个字符串:\n");
	fscanf(pf, "%s", str);
	printf("输出:%s\n\n", str);

	fclose(pf);
	pf = NULL;
	//关闭文件

	printf("从stdin中读取一个字符串:\n");
	fscanf(stdin, "%s", str);
	printf("输出:%s\n", str);
	return 0;
}

注意:读取文件时文件必须存在。
此时文件中的内容:
在这里插入图片描述

运行实例:
在这里插入图片描述

补充:
1.从文件中读取数据时:因为数据已经存在,所以不需要进行输入,但是从stdin(键盘)中读取时需要我们进行输入
因此我们在屏幕上看到了两个“哈哈”。
2.fscanf读取字符时遇到空格就认为该数据读取结束,之后知道找到下一个非空字符时才开始读取下一个数据。


3.sscanf

int sscanf ( const char * s, const char * format, …);

sscanf和fscanf就很相似了,
不同之处在于:fscanf第一个参数为 流,而 sscanf为常量字符指针–也就是指向一个字符串常量

示例:

int main()
{
	char arrc[] = "10 3.14 a hello world";
	char* ps = arrc;
	int a = 0;
	float fl = 0.0f;
	char ch = 0;
	printf("从ps指向的字符串中读取一个整形,浮点型和字符型数据:\n");
	sscanf(ps, "%d %f %c", &a, &fl, &ch);
	//ps也可以换成数组名arrc
	printf("%d %f %c\n\n", a, fl, ch);

	char str[20] = { 0 };
	printf("从ps指向的字符串中读取一个字符串:\n");
	sscanf(ps, "%s", str);
	printf("%s\n", str);

	return 0;
}

运行实例:
在这里插入图片描述
补充:
为什么这里字符串读取到的是"10",而不是"hello" 呢“?
答:
从文件中读取数据,在关闭文件之前我们读取到哪里都可以保存下来,之后继续往后读取,
但是从字符串中读取数据时没有“关闭字符串”这个操作,所以在每次读取字符串时都会从最开始进行读取。


(二)printf、fprintf、sprintf

函数原型:
int printf(const char* const _Formet, …);
int fprintf(FILE* const _Stream, const char* const _Formet, …);
int sprintf ( char * str, const char * format, … );

1.printf

int printf(const char* const _Formet, …);

printf函数的参数列表里也是一个格式字符串和一串省略号,和scanf一样,按照格式字符串的形式进行输出。
并且,printf只能将数据写入到stdout(屏幕)上;
和scanf不同的是:虽然他们的返回值都是int类型,但是,scanf返回值为输入变量的个数,而,printf返回值却是输出字符的个数。

示例:

int main()
{
	int a = 1;
	float fl = 3.14f;
	char ch = 'a';
	int ret = printf("%d\n", a);
	printf("printf返回值:%d\n\n", ret);
	char str[] = "hello world";
	ret = printf("%s\n", str);
	printf("printf返回值:%d\n\n", ret);

	return 0;
}

运行实例:
在这里插入图片描述

补充:
第一个printf输出一个字符’1’,和’\n’,所以返回值为2;
第二个printf输出字符串"hello world"和’\n’,一共 11 + 1 = 12 个字符,所以返回值为12.


2.fprintf

int fprintf(FILE* const _Stream, const char* const _Formet, …);

fprintf和printf的区别是fprintf参数列表中多了一个参数:流,表示我们可以把数据写入任何数据流中,
这里可以类比fscanf和scanf的区别。

示例:

int main()
{
	int a = 1;
	float fl = 3.14f;
	char ch = 'a';
	printf("写入到stdout:\n");
	fprintf(stdout, "%d %f %ch\n", a, fl, ch);
	char str[] = "hello world";
	fprintf(stdout, "%s\n", str);

	FILE* pf = fopen("ppp.txt", "w");

	printf("\n写入ppp.txt文件\n");
	fprintf(pf, "%d %f %c\n", a, fl, ch);
	fprintf(pf, "%s\n", str);

	fclose(pf);
	pf = NULL;
	return 0;
}

运行实例:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述


3.sprintf

int sprintf ( char * str, const char * format, … );

sprintf和fprintf的区别就是第一个参数,sprintf是想字符串中写入数据。

示例:

int main()
{
	char buf[100] = { 0 };
	int a = 1;
	float fl = 3.14f;
	char ch = 'a';
	printf("写入到buf字符串\n\n");
	sprintf(buf, "%d %f %c\n", a, fl, ch);

	printf("输出buf字符串:\n");
	fprintf(stdout, "%s\n", buf);

	return 0;
}

运行实例:
在这里插入图片描述


(三)getchar、fgetc

函数原型:
int getchar(void);
int fgetc(FILE* _Stream);

1.getchar

int getchar(void);

getchar只可以从stdin中读取字符,读取成功就返回该字符,失败则返回EOF
这里返回值为 int类型是对 char类型进行了整形提升

示例:

int main()
{
	int ch = 0;
	/*while(scanf("%c",&ch)!=EOF)*/
	while ((ch = getchar()) != EOF)
	{
		getchar();//吸收后面的 空格字符(空格、换行、tab键)
		printf("%c\n\n", ch);
	}
	return 0;
}

运行实例:
在这里插入图片描述

补充:结束输入操作:Ctrl + z
有的时候需要输入三次才能退出。


2.fgetc

int fgetc(FILE* _Stream);

fgetc与getchar的区别在于fgetc可以从任何数据流中读取数据,类比scanf和fscanf

示例:

int main()
{
	int ch = 0;
	/*while(scanf("%c",&ch)!=EOF)*/
	while ((ch = fgetc(stdin)) != EOF)
	{	//	从stdin流中读取数据
		getchar();//吸收后面的 空格字符(空格、换行、tab键)
		printf("%c\n\n", ch);
	}
	return 0;
}

运行实例:
在这里插入图片描述


(四)putchar、fputc

int putchar( int character);
int fputc(int character, FILE* _Stream);

1.putchar

int putchar( int character);

putchar的参数为需要输出的字符,如果输入正确就返回一个非负数(不一定就是该字符),错误就返回EOF

示例:

int main()
{
	int ch = 0;
	/*while(scanf("%c",&ch)!=EOF)*/
	while ((ch = fgetc(stdin)) != EOF)
	{
		getchar();//吸收后面的 空格字符(空格、换行、tab键)
		putchar(ch);
		putchar('\n');
		putchar('\n');
		/*printf("%c\n\n", ch);*/
	}
	return 0;
}

运行实例:
在这里插入图片描述


2.fputc

int fputc(int character, FILE* _Stream);
示例:

int main()
{
	int a= 'b';
	fputc(a,stdout);
	putchar(a);
	//两者等同,都是向stdout中输出数据
	return 0;
}

运行实例:
在这里插入图片描述

之后的介绍将不会和之前那么详细(啰嗦),这里我们需要注意的就是流的位置和fscanf不同,是位于最后的

(五)gets、fgets、fread

char* gets(char* str);
char* fgets(char* str, int num, FILE* _Stream);
size_t fread(void* _Buffer, size_t size, int count, FILE* _Stream);

1.gets

char* gets(char* str);
从stdin中获取字符串,直到\n或者EOF时结束,读取成功后返回该字符串
注意:该函数在c和c++中已经不可使用(从c11开始)

2.fgets

char* fgets(char* str, int num, FILE* _Stream);
从文件流中读取数据放到字符串中,
遇到空格字符、文件结尾、或者读取了 num - 1 个字符就结束读取,
读取成功就返回字符串首地址,
如果是读取到文件末尾失败则返回NULL,并且设置eof指示器(feof),
如果是读取过程中出错也返回NULL,不过设置的是错误指示器(ferror)。
示例:

int main()
{
	char str[100];
	//从stdin流中读取(10 - 1)个字符放入str中
	while(fgets(str, 10, stdin)!=NULL)
	printf("%s\n\n", str);
	return 0;
}

运行实例:
在这里插入图片描述

补充:
1.fgets每次最多读取num-1个字符,最后一位会自动放入 ‘\0’
2.读取过程中 ‘\n’ 也会被当做正确字符读入字符串中


3.fread

size_t fread(void* _Buffer, size_t size, int count, FILE* _Stream);
以二进制形式从文件流中读取数据,
size为一个数据的大小,
count为数据的个数
它的返回值为读取的数据个数,如果不等于 count则表示读取出问题了。

放到后面与fwrite一起介绍

(六)puts、fputs、fwrite

int puts(char* str);
int fputs(char* str, FILE* _Stream);
size_t fwrite(void* _Buffer, size_t size, int count, FILE* _Stream);

1.puts

int puts(char* str);
向stdout写入字符串,成功就返回非负数,否则返回EOF

2.fputs

int fputs(char* str, FILE* _Stream);
向流中写入字符串,写入文件时只有遇到’\0’才停止,并且’\0’不会被写入文件中,
成功就返回非负数,否则返回EOF。

示例:

int main()
{
	char str[100] = { 0 };
	while (fgets(str, 20, stdin) != NULL)
	{
		fputs(str, stdout);
		//等同于:puts(str);
		putchar('\n');
	}
	return 0;
}

运行实例:
在这里插入图片描述

补充:puts、fputs会在输出结束时自动换行


3.fwrite

size_t fwrite(void* _Buffer, size_t size, int count, FILE* _Stream);
以二进制形式进行写入
示例:

int main()
{
	FILE* pf = fopen("ppp.txt", "wb");
	printf("以二进制形式将字符串信息写入ppp.txt文件\n\n");
	int arr[10] = { 1,2,3,4,5,6,7,8,9,0 };
	fwrite(arr, sizeof(int), 10, pf);
	fclose(pf);
	pf = NULL;
	
	int an[10] = { 0 };
	char str[100] = { 0 };
	pf = fopen("ppp.txt", "rb");
	printf("以二进制形式从ppp.txt文件中读取字符串信息\n\n");
	fread(an, 4, 10, pf);
	
	for(int i=0;i<10;i++)
	printf("输出:%d\n", an[i]);
	fclose(pf);
	pf = NULL;

	return 0;
}

运行实例:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述


总结

以上就是我们C语言常用输入输出函数的全部内容,如果有什么疑问或者建议都可以在评论区留言,感谢大家的支持,欢迎来评论区一起探讨,大家的鼓励是在这里插入图片描述继续更新的巨大动力。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

【八组输入输出你都了解多少】 的相关文章

随机推荐

  • SpringBoot项目使用Sigar获取系统参数:CPU,内存,硬盘,网络流量波动

    先下载sigar http sigar hyperic com 将sigar bin lib目录下文件放到classpath中 1 pom
  • 淘宝框架atlas基本使用说明

    转自 http blog csdn net wdd1324 article details 76855408 官网 文档 github 视频资料 如有错误请指正 简介 Atlas是伴随着手机淘宝的不断发展而衍生出来的一个运行于Android
  • SOA是什么

    面向服务的体系结构 service oriented architecture SOA 是一个组件模型 它将应用程序的不同功能单元 称为服务 通过这些服务之间定义良好的接口和契约联系起来 接口是采用中立的方式进行定义的 它应该独立于实现服务
  • Java使用Hibernate-Validator验证API接口参数

    一 相关依赖
  • 逻辑地址 虚拟地址 物理地址 总线地址的区别

    1 逻辑地址 逻辑地址是最为模糊的概念 understanding the Linux kernel 上的解释是与虚拟地址相关 基于硬件MMU与软件内存管理的一个概念 具体可以看UTLK的第二章内存寻址 有很详细的解释 但是工作中之前用到的
  • 【2021-CVPR-3D人体姿态估计】Graph Stacked Hourglass Networks for 3D Human Pose Estimation

    Graph Stacked Hourglass Networks for 3D Human Pose Estimation 题目 用于3D人体姿态的图堆叠沙漏网络 作者 来源 CVPR 2021 研究内容 单人 单视图 有监督 创新点 提出
  • 目标检测数据集

    参考 You Only Look Once Unified Real Time Object Detection 你只看一次 统一的实时对象检测 CVPR 2016 1 PASCAL VOC PASCAL VOC 数据集是目标检测领域最常用
  • 推荐图灵出版社的图书

    最近半年买了不少图灵出版社的图书 有java oracle Linux和TCP IP方面的书 每本都读了差不多一半 读后有一种很亲切的感觉 总结下来一句话 很适合受中国传统教育的大部分学生 在此并无讽刺之意 很多学生习惯了 填鸭式 的教育模
  • 使用conda创建Python的虚拟环境

    目录 一 查看已有环境 二 创建虚拟环境 2 1 添加镜像地址 2 2 创建虚拟环境 2 3 激活虚拟环境 2 4 退出虚拟环境 三 pycharm使用环境 四 删除虚拟环境 五 快速创建虚拟环境 一 查看已有环境 键入以下命令 conda
  • nosql

    公共基础 一 NoSQL概述 1 NoSQL NoSQL定义 非关系型 分布式 开放源码和具有横向扩展能力的下一代数据库 NOSQL Not Only SQL 2 数据库的分类 1 TRDB数据库 传统关系型数据库 基于单机集中管理数据理念
  • 机器学习实战——第三章(分类):决策树算法与实例(一)

    前言 今天看了会 机器学习实战 第三章 决策树 很迷 似懂非懂 专业术语太多了 而且有点混乱 对于一个大一概率论没学好的学渣来说 如今大三的我看到那些概率公式和一些概率论专业术语就头疼 马上就打了退堂鼓 早起看了半个小时没看明白果断又躺回了
  • 设置swiper轮播图的css样式无效?

    项目场景 在做vue项目的时候 使用到了vue awesome swiper三方库 当时小编想重写 覆盖轮播图的分页器小圆点的css样式 其次 小编做项目时 使用的css预编译器是SCSS 问题描述 当小编在重写分页器小圆点css样式时 发
  • Vim配置及使用总结

    Vim配置及使用总结 我的Vim配置 Vim安装及配置文件 Vim安装 Vim配置文件 我的Vim配置 Vim配置详解 Vim使用技巧 基本使用介绍 命令模式 输入模式 底线命令模式 技巧总结 二进制文件查看 下面是我在使用vim时的一些配
  • Sass -- 条件语句、循环语句、自定义函数

    文章目录 条件语句 循环语句 for while each 自定义函数 条件语句 在Sass中可以使用 if if else if else 来进行条件判断 用法和JS相同 循环语句 在Sass中可以使用 for while each 来进
  • 4. Hadoop伪分布式运行模式

    文章目录 Hadoop伪分布式运行模式 1 启动HDFS并运行MapReduce程序 1 1 配置集群 配置hadoop env sh 配置core site xml 配置hdfs site xml 1 2 启动集群 格式化NameNode
  • window.open()的所有参数列表(转)

    前言 经常上网的朋友可能会到过这样一些网站 一进入首页立刻会弹出一个窗口 或者按一个连接或按钮弹出 通常在这个窗口里会显示一些注意事项 版权信息 警告 欢迎光顾之类的话或者作者想要特别提示的信息 其实制作这样的页面效果非常的容易 只要往该页
  • Python-玩转数据-Scrapy框架介绍及安装

    一 Scrapy框架说明 1 Scrapy介绍 Scrapy框架官方网址 http doc scrapy org en latest Scrapy是用纯Python实现一个为了爬取网站数据 提取结构性数据而编写的应用框架 用途非常广泛 用户
  • 如果访问云服务器上的文件,如果访问云服务器上的文件

    如果访问云服务器上的文件 内容精选 换一换 WinSCP工具可以实现在本地与远程计算机之间安全地复制文件 与使用FTP上传代码相比 通过 WinSCP 可以直接使用服务器账户密码访问服务器 无需在服务器端做任何配置 通常本地Windows计
  • [Qt]不带标题栏(FramelessWindowHint)的窗体移动及调整大小

    Qt窗体若设置了 setWindowFlags Qt FramelessWindowHint 运行后该窗体是无法进行移动和调整大小的 那要如何才能让它和普通窗体一样进行移动和调整其大小的呢 方案如下 void QFramelessWindo
  • 【八组输入输出你都了解多少】

    目录 前言 一 总览 一 只能从标准流 std 中输入和输出数据 二 可以从所以流中读取和写入数据 三 只能从字符串中读取和写入数据 二 详细描述 一 scanf fscanf sscanf 1 scanf 2 fscanf 3 sscan