C语言从头学44——I/O 函数(一)

I/O函数就是负责与外部设备通信的函数。所谓外部设备,一般指键盘、显示器等负责输入输出的设备。这里的输入、输出都是相对于计算机内存而言的。严格地说,输入输出函数并不是直接与外部设备打交道,而是通过缓存进行中转通信。

一、缓存

以文件读写为例,文件一般都保存在硬盘中。计算机读写硬盘的速度比我们人类读写速度快很多,但和CPU的速度相比,读写硬盘就像是慢动作。所以,程序不会直接读写硬盘。在C语言中,只要打开一个文件,就在内存里面为这个文件设置一个缓存区。程序向文件写入数据时,程序先把数据放入缓存,等到缓存写满了,再把里面的数据一次性写入磁盘文件,然后清空缓存再写入,周而复始;程序从文件读取数据时,也是先把一部分文件数据放到缓存,然后程序从缓存获取数据,等到缓存读空了,再把新的数据放入缓存,也是周而复始。内存的读写速度比磁盘读写速度快很多,缓存的作用就是通过增加每次读写硬盘的量从而减少读写磁盘的次数,提高程序效率。

通过缓冲区间接读写的模式,对于程序来说,不是一次性读取或写入所有数据,而是持续不断类似流水的过程;缓存与硬盘间是批发,缓存与cpu间是零售,缓存相当于是中间商批发零售持续不断,这个过程称为字节流操作。

C语言的输入输出函数:输入函数负责从文件获取数据;输出函数负责向文件写入数据。显示器、键盘、鼠标、打印机等外部设备都可以想象成是一个文件,计算机与它们之间的交互过程和与文件之间的交互过程完全一样。

二、下面开始介绍I/O函数

(一)、printf()函数

这个函数前面已经介绍过,不再介绍,只是强调printf属于I/O函数,它负责输出到屏幕。

(二)、scanf()函数

1、执行到scanf函数,程序会停下来等待用户从键盘输入数据;该函数定义在头文件 stdio.h。

功能:scanf函数用于读取用户的键盘输入。

使用格式:scanf(参1,参2);

参1 占位符格式字符串(告诉计算机后续输入值的类型)

参2 接收变量地址

返回值:scanf读取成功返回接收变量个数;没有读取到数据或者匹配失败返回0;如果读取到的是"\0"或"\n"等,则返回-1。

说明:

a.由于scanf函数操作的是指针,所以参2不能直接写接收变量,需要对接收变量取址;

b.如输入的数据是字符串,接收字符串的变量本就是指针,所以接收字符串的变量名前不能再取址;

c.参1、参2既可以各自由一个占位字符串或单个变量地址组成,也可以由多个占位符字符串或多个变量地址组成,变量地址中间用","隔开。占位符与变量地址组形式、数量上都要匹配。实际使用时,输入的数据之间用与占位字符串之间相同的符号隔开,也可以每输入一个数据就打一次回车。但输入字符串还是建议调用一次scanf只输入一个字符串,或者干脆处理其它输入也是输入一个数据就调用一次scanf,既简单又不易出错。

d.在使用scanf函数时,经常报警该函数不够安全,建议使用改进的scanf_s,这种情况处理办法有二:一是听人劝改用scanf_s函数,scanf_s使用方法与scanf基本一样,只有输入字符串时(占位符%s)需要增加第三个参数字符串长度;二是在程序头部加上语句" #define _CRT_SECURE_NO_WARNINGS",不让它报警;如此虽不报警,但也需注意接收字符串数组长度与输入字符串最大长度的匹配,不要造成溢出。

e. scanf读取是顺序读取,比如读取int型数据,你输入了小数点,则读取到小数点就停了;小数点会赋给其它的变量,如果没有变量接收可能还会报错,所以使用scanf输入数据要做到准确无误,最好配合上输入提示。

2、与scanf函数相关的占位符

%c: 字符。

%d: 整数。

%f: float 类型浮点数。

%lf: double 类型浮点数。

%Lf: long double 类型浮点数。

%s: 字符串。

说明:

a.上面所有占位符之中,除了%c以外,都会自动忽略开头的空格;%c可以接受空格。如果希望%c也不接收空格,则需这样写scanf(" %c",&x),即在%前加上一个空格。

b.%s从当前第一个非空白字符开始读起,遇到空白字符(即空格、换行符、制表符等)停止。因此scanf不适合读取包含空格的字符串。按照字符串的定义, scanf处理%s时,都会在字符串末尾加一个"\0"结束符。

c.为防止输入字符串时造成溢出,可变通一下%s,写成%ns形式,n就是允许输入的最大长度,这样输入多了的部分会舍弃,不会造成溢出。

3、赋值忽略符

比如,输入日期有人习惯写成2024-8-7,也有人习惯写成2024/8/7,实际计算机需要的是2024、6、18 这三个数,三者之间的连接可以忽略。这种情况就用到了忽略符,"%*c"就表示可以忽略掉一个输入的字符,无需有对应的变量接收,把c换成d也可,但一般情况下忽略的多是字符。

4、关于scanf函数使用举一个小例子:

cpp 复制代码
#define _CRT_SECURE_NO_WARNINGS //禁止对scanf函数报警
#include<stdio.h>
int main(void)
{
//调用scanf函数输入并显示整型、浮点两个数据
	int a=0;
	float x=0;
	printf("请输入整型数 a 浮点数 x 两数中间用--隔开\n");
	int ret=scanf("%d--%f", &a,&x); //输入格式举例:15--3.14159回车
	if (ret == 0)
	{
		printf("输入错误,结束程序!");
		return 0;
	}
	printf("你输入数据a=%d  x=%f\n",a,x); //运行结果:你输入数据a=15  x=3.141590
//调用scanf函数输入并显示一个字符串
	char str[128];
	printf("请输入一个字符串(最长127字节)\n");
	scanf("%127s", str); //str结尾需有\0,故最多只能输入127个字符
						 //比如输入:天津市南开区
	printf("你输入的字符串是:%s\n", str); //运行结果:你输入的字符串是:天津市南开区
//调用scanf函数使用输入不同格式的日期并显示
	int year, month, day;
	printf("请输入日期\n");
	scanf("%d%*c%d%*c%d", &year, &month, &day); //无论输入2024-8-7、2024/8/7均可正常输入
	printf("%d年%d月%d日\n", year, month, day); //运行结果:2024年8月7日
	fflush(stdin);
	getchar();
	getchar();
	return 0;
}
相关推荐
嵌入式科普17 分钟前
十三、从0开始卷出一个新项目之瑞萨RZN2L串口DMA接收不定长
c语言·stm32·瑞萨·e2studio·rzn2l
小林熬夜学编程2 小时前
【Linux网络编程】第十四弹---构建功能丰富的HTTP服务器:从状态码处理到服务函数扩展
linux·运维·服务器·c语言·网络·c++·http
Jackey_Song_Odd2 小时前
C语言 单向链表反转问题
c语言·数据结构·算法·链表
A懿轩A3 小时前
C/C++ 数据结构与算法【数组】 数组详细解析【日常学习,考研必备】带图+详细代码
c语言·数据结构·c++·学习·考研·算法·数组
半盏茶香3 小时前
在21世纪的我用C语言探寻世界本质 ——编译和链接(编译环境和运行环境)
c语言·开发语言·c++·算法
字节高级特工4 小时前
【C++】深入剖析默认成员函数3:拷贝构造函数
c语言·c++
计算机学长大白5 小时前
C中设计不允许继承的类的实现方法是什么?
c语言·开发语言
XH华11 小时前
初识C语言之二维数组(下)
c语言·算法
Uu_05kkq14 小时前
【C语言1】C语言常见概念(总结复习篇)——库函数、ASCII码、转义字符
c语言·数据结构·算法
嵌入式科普16 小时前
十一、从0开始卷出一个新项目之瑞萨RA6M5串口DTC接收不定长
c语言·stm32·cubeide·e2studio·ra6m5·dma接收不定长