C语言学习(十一)之字符输入/输出


一、单字符I/O:getchar()和putchar()

getchar()和putchar()每次都处理一个字符。

getchar() 是从键盘中接收字符。而putchar则是将接收的字符打印出来。

#include <stdio.h>


int main(void){
    
    

	char ch;
	// 将接收的字符赋值给ch,如果ch不等于#,则继续输入。
	// 如果有#,则#后面的内容不会被打印出来。
	while ((ch = getchar()) != '#')
	{
    
    
		putchar(ch);
	}	
	return 0;
}

二、缓冲区

2.1 什么是缓冲区

用户输入的字符后立即重复打印该字符的是属于无缓冲(直接)输入,即正在等到的程序可立即使用输入的字符。

大部分系统在用户按下Enter键之前不会重复打印刚输入的字符,这种输入形式属于缓冲输入,用户输入的字符被收集并存储在一个被称为缓冲区的临时存储区,按下Enter键之后,程序才可使用用户输入的字符。


2.2 为什么需要缓冲区

当我们输入错误或打错字符时,可以通过键盘的删除键直接删除或回退,然后重新输入。当最后按下Enter键之后,输入的就是正确的字符。如果没有缓冲区,就没有办法修改。

虽然缓冲区有很多好处,但某些程序也需要无缓冲输入。所以,缓冲输入和无缓冲输入都需要。


2.3 缓冲区分类

缓冲分为两类:即完全缓冲I/O行缓冲I/O

2.3.1 完全缓冲I/O

完全缓冲输入指的是当缓冲区被填满时才刷新缓冲区(内容被发送至目的地),通常出现在文件输入中。缓冲区的大小取决于系统,常见的大小时512字节和4096字节。


2.3.2 行缓冲I/O

行缓冲I/O指的是在出现换行符时刷新缓冲区。键盘输入通常是行缓冲输入,所以按下Enter键后才刷新缓冲区。


三、结束键盘输入

在上述的程序中,只要输入的字符中不含#,程序就会一直打印出#前面的内容,直到读取到#后,程序就会停止打印输出。但有时我们就要用#号,所以这时就不能满足要求了。应该用一个文本中用不到的字符来标记输入完成,这样的字符不会无意间出现在输入的字符中。C提供了这样的字符,不过需要先了解C处理文件的方式。


3.1 文件、流和键盘输入

文件是存储器中存储信息的区域。通常,文件都保存在永久存储器中(例如:硬盘、U盘等)。毫无疑问,文件对于计算机系统相当重要。我们写的C程序就保存在文件当中。

C通过标准I/O包来处理文件。这涉及创建用于处理文件的标准模型和一套标准的I/O函数。

C程序处理的是流而不是直接处理文件。是一个实际输入或输出的映射的理想化数据流。这意味着不同属性的不同种类的输入,由属性更统一的流来表示。于是,打开文件的过程就是把流与文件相关联,而且读写都通过流来完成。


3.2 文件结尾

文件结尾就是要计算机操作系统要以某种方式判断文件的开始和结束。

一种方法是在文件末尾放置一个特殊的字符标记问价结尾(例如:CP/M、IBM-DOS和MS-DOS的文本文件曾经用过这种方法)。另一种方法是存储文件大小的信息。如果文件有3000字节,程序读到3000字节时便达到了文件的末尾。

在C语言中,用getchar()读取文件检测到文件结尾时将返回一个特殊的值,即EOF(end of file的缩写)。scanf()函数检测到文件结尾时也返回EOF。通常EOF定义在<stdio.h>文件中。

#define EOF    (-1)

上述代码中,将EOF定义为 -1 。为什么是-1呢?因为getchar()函数的返回值通常介于0~127,这些值对应标准字符集。但是,如果系统能识别扩展字符集,该函数的返回值可能在0~255。无论哪种情况,-1都不对应任何字符,所以该值可用于标记文件结尾。

如何使用EOF呢,还是以上面的代码为例:

#include <stdio.h>


int main(void){
    
    
	// ch的类型改为int类型,是因为char只能表示0~255之间的无符号整数,
	//而EOF的值为-1。getchar()函数实际返回的值类型是int,所以它可以读取EOF的值
	int ch;
	// EOF在头文件中已经定义,在这里可以直接使用,不需要再次定义
	// 
	while ((ch = getchar()) != EOF)
	{
    
    
		putchar(ch);
	}
	
	return 0;
}

四、重定向和文件

程序可以通过两种方式使用文件。一种是,显式使用特定的函数打开文件、关闭文件、读取文件、写入文件,诸如此类。另一种是设计能与键盘和屏幕交互的程序,通过不同的渠道重定向输入至文件和从文件输出。

重定向的一个主要问题是它与操作系统有关,与C无关。


4.1 重定向输入

假设我们已经编译了上述程序,并生成了一个名为test.exe的可执行文件。

在这里插入图片描述
打开终端命令行,输入test.exe,回车,运行该程序
在这里插入图片描述
这就是在终端执行编译过后的C语言程序文件。运行的结果和编译器运行的结果一样。

假设你要用程序处理名为words的文本文件。文本文件时内含文本的文件,其中存储的数据是我们可识别的字符。文件的内容可以是一篇文章或者C程序。内含机器语言指令的文件(如存储可执行程序的文件)不是文本文件。
在这里插入图片描述
由于该程序的操作对象是字符,所以要使用文本文件。只需下面的命令即可。

test.exe < words.txt

输出结果如下:
在这里插入图片描述
上述命令中的“ < ”符号是重定向运算符。该运算符使words文件与stdin流相关联,把文件中的内容作为输入到test.c的程序中,并打印在屏幕上。

4.2 重定向输出

假设要用test.c把键盘输入的内容发送到名为mywords文件中,就可以使用重定向输出符完成操作。

test.c > mywords

输出结果:
在这里插入图片描述

重定向输出符“ > ” ,创建一个名为mywords的新文件,然后把test.c的输出重定向至该文件中。重定向把stdout从显示设备(显示器)赋给mywords文件。如果该文件已经存在,则会擦除文件中的内容写入新的内容。

4.3 组合重定向

组合重定向就是将重定向输入和重定向输出结合起来。

例如:将mywords文件拷贝一份,就可以使用下面命令:

test.exe < words > savemywords

在这里插入图片描述

也可以这样写,因为命令与与重定向的顺序无关。

test.exe > savemywords < words

注意,拷贝副本的文件名不能和原文件名一样。

4.4 注意

1、重定向运算符连接一个可执行程序(包括标准操作系统指令)和一个数据文件,不能用于连接一个数据文件和另一个数据文件,也不能用于连接一个程序和另一个程序。
2、使用重定向运算符不能读取多个文件的输入,也不能把输出定向至多个文件
3、通常,文件名和运算符之间的空格不是必须的,除非偶尔在UNIX Shell、Linux Shell或Windoms命令行提示模式中使用的有特殊含义的字符。

猜你喜欢

转载自blog.csdn.net/qq_46292926/article/details/127568938