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;
}
相关推荐
EricWang13582 小时前
[OS] 项目三-2-proc.c: exit(int status)
服务器·c语言·前端
我是谁??2 小时前
C/C++使用AddressSanitizer检测内存错误
c语言·c++
希言JY2 小时前
C字符串 | 字符串处理函数 | 使用 | 原理 | 实现
c语言·开发语言
午言若2 小时前
C语言比较两个字符串是否相同
c语言
TeYiToKu4 小时前
笔记整理—linux驱动开发部分(9)framebuffer驱动框架
linux·c语言·arm开发·驱动开发·笔记·嵌入式硬件·arm
互联网打工人no14 小时前
每日一题——第一百二十四题
c语言
爱吃生蚝的于勒4 小时前
深入学习指针(5)!!!!!!!!!!!!!!!
c语言·开发语言·数据结构·学习·计算机网络·算法
羊小猪~~4 小时前
数据结构C语言描述2(图文结合)--有头单链表,无头单链表(两种方法),链表反转、有序链表构建、排序等操作,考研可看
c语言·数据结构·c++·考研·算法·链表·visual studio
洋2405 小时前
C语言常用标准库函数
c语言·开发语言
徐嵌5 小时前
STM32项目---畜牧定位器
c语言·stm32·单片机·物联网·iot