在C语言中,我们拥有一个很重要的概念叫做IO输入输出流,input和output,其主要是依靠printf与scanf,getchar(),putchar()等来实现
让我们一起来了解一下这些函数吧
在我们硬件角度来看,printf与putchar()是将数据从内存中显示到显示器中,scanf与getchar()是将键盘中的数据输入到内存中
程序运行前,默认会打开三个设备,分别为:键盘(标准输入),显示器(标准输出),显示器(标准错误)
所以我们可以认为scanf函数是从标准输入中读取数据,printf是从标准输出中读取数据
下面我们来观察一份代码
#include <stdio.h>
#include<Windows.h>
int main()
{
char ch = '\0';
while (ch = getchar()){
putchar(ch);
}
system("pause");
return 0;
}
上述即为这段代码的执行,我们不难发现,其完成了输入如并打印,但我们想一下,输入输出的是整型int的值吗?
事实上并不是的,他们都是字符,所以我们可以得出结论:
所有从终端输入显示到终端的内容都是字符
接下来让我们看下我们所熟知的scanf与printf
scanf("%d",&a);//123
a == 123;
printf("%d",1234);
当我们所使用scanf函数时,我们刚才已经得出,其输入的123一定是字符,但是我们在之前使用时却可以当整型来使用,这是为什么呢?
事实上,是因为%d这个符号(格式控制)起到了转换类型的作用,而相同的,如果要转乘其他类型比如字符浮点就需要将其变化为%s,%f等,所以上述代码中输入的123事实上是字符1,字符2,字符3;所需要占用的总空间为3个字节,而我们通过%d这个符号将其转化为整型,占用4个字节,所以我们才可以将其作为整形使用。那么我们的printf函数也就可以理解了,是将内存中的整型等变量转化为字符的形式打印到显示器中,所以我们作为使用者才可以看得到1234这四个连续的字符
而现在我们拥有了这些概念之后,我们来思考一下他们是如何实现的,这需要我们将视角拉回刚才的函数中:
char ch = '\0';
while (ch = getchar()){
putchar(ch);
我们这时候思考一下scanf与getchar,printf与putchar的关系,我们便可以发现,事实上是printf内部将所有的非格式化字符转化成格式化字符然后利用getchar一个一个连续的打出来的,而scanf内部则是利用putchar函数将字符输入而后转化为非格式化字符以供我们所使用
这时候就又有一个问题出现了,我们getchar与putchar函数不是操作的是单一字符吗?为什么显示到终端的时候是字符串呢?
这是因为我们存在while循环来将字符一个个连接起来的,利用回车来进行回显,那么如何去结束这个输入输出流呢?
char ch = '\0';
while ((ch = getchar())!=EOF){
putchar(ch);
因为C语言中所有的字符ASCI码都大于0,那么便无法退出这个while循环,这时候就需要一个C语言内置的宏EOF来结束,EOF在C语言中定义的为-1,通过在键盘中输入Ctrl+z来输入EOF便可以让getchar来读取EOF,从而结束这个输入输出。
这时候我们来举几个例子来练习下getchar与putchar的使用:
1.
#include<stdio.h>
#include<windows.h>
//屏蔽所有字母
int main()
{
char ch ='\0';
while((ch = getchar()) !=EOF){
if(ch >='0' && ch <='9'){
putchar(ch);
}
}
return 0;
}
这时候我们便可以观察到程序自动将字母字符屏蔽,仅输出数字字符。
2.
#include <stdio.h>
#include<Windows.h>
int main()
//将小写转大写
{
char ch = '\0';
while ((ch = getchar()) != EOF){
if (ch >= 'a' && ch <= 'z'){
putchar(ch-('a'-'A'));
}
}
system("pause");
return 0;
}
不难发现,确实通过ASCI码层面上完成了对于大小写的转换。
3.剖析scanf函数:
int a = 0;
scanf("%d", &a);
//*************************
char ch = '\0';
int n = 0;
while ((ch = getchar()) != EOF){
if (ch >= '0' && ch <= '9'){
n = n * 10 + (ch - '0');
printf("%d", n);
}
}
事实上,scanf函数的实现,就是底下不断地从标准输入读入字符,然后按照相对应的类型进行转化而实现的;而printf函数也同样,是将数据一个一个拆出,利用putchar转化成字符的形式打印出来。
这些接口都被称之为IO接口,总的来说,我们在显示器上看到的都是字符,而格式化输入输出就是利用%d,%s等将数据转化成需要的格式来进行操作,从显示层面上看到的都是字符,从操作层面上才转成对应的类型。