上一章介绍的printf和scanf函数都属于IO函数。
这里我们介绍两个函数getchar()和putchar()用于字符的IO。
getchar()函数不带任何参数,如果缓冲区为空,则会等待缓冲区,当输入并回车后,将从输入队列中返回下一个字符。
putchar()函数打印输入的参数。
getchar()函数把每个字符解释称一个字符编码,而scanf()函数以同样的方式看待输入也是读取字符,但是他会把字符输入根据转换说明转成相应的数值。
比如:
#include <stdio.h>
int main(void)
{
char ch;
ch = getchar(); // read a character
putchar(ch); // print the newline
return 0;
}
如果我在键盘输入abcd agf
然后回车,那么打印将是a。
因为getchar()会读取我们输入的一行输入回车表示结束,空格不会结束。
然后他会读取下一个字符(也就是第一个)并赋值给ch
putchar()将ch打印出来。
再看下面程序:
int main(void)
{
char ch;
ch = getchar(); // read a character
while (ch != '\n') // while not end of line
{
putchar(ch);
ch = getchar(); // get next character
}
putchar(ch); // print the \n
return 0;
}
当我们输入ndn ang
然后回车,会打印ndn ang
。
分析一下:
ndn ang\n
表示输入一行完成。上面代码可以简写,将循环替换
int main(void)
{
char ch;
while ((ch = getchar()) != '\n') // while not end of line
{
putchar(ch);
}
return 0;
}
上面的示例中我们就可以读取一行输入的字符串并且可以带空格了。
我们也可以使用特定的字符作为结束
while ((ch = getchar()) != '#') // while not end of line
这样当我们输入
angn asdn#dng
就会得到
angn asdn
在上面的例子中我们发现,当我们输入一行字符串时
ndn ang
只有当我们敲下回车时,程序才会打印。如果不敲回车我们就可以一直输入。这种输入叫做缓冲输入。
那么输入的这些字符串放在哪里了呢。用户输入的字符被收集在了一个存储位置叫做缓冲区.
但是当我们打游戏的时候,我们按下某个键,则会有立即的相应,比如释放q技能。这个叫做无缓冲输入。所以有缓冲输入和无缓冲输入各有自己的应用场景。
ANSI C和后续的C标准都规定输入是有缓冲的,不过最初早的C标准中的输入是无缓冲的。
缓冲分为两类:完全缓冲IO和行缓冲IO。
上面的例子中,我们一个使用回车来结束,另一个是用‘#’符号来结束程序。
这些符号都是常用的,我们不应该用常用符号来结束程序。所以我们应该想个办法用一个比较唯一的东西来结束,C提供了这样的一个字符。
先简单介绍一下文件的概念,他是存储器中存储信息的区域。
程序会经常操作文件,比如打开,读取,关闭写入等。
C语言在会调用底层IO也就是操作系统函数来操作文件。比如linux系统函数write() open()等。
但是如果在windows上,直接调用write() open 就不行了,需要调用windows的系统函数。所以C语言将不同系统的文件处理函数封装成了C的标准IO包。他来处理不同系统的差异,暴露给用户统一的函数比如fopen(),fwrite()等。
不同的系统不仅暴露处理文件函数不同,他们各自处理文件的方式也不同。比如有些系统把文件内容存储在一处,文件相关信息存储在另一处。而有些系统会在每个文件中创建专门的文件描述。
不同的系统还会用不同的文件结尾。
C把键盘的输入和输出视为自动打开的文件。stdin表示键盘输入,stdout表示向屏幕输出。
也就是C用处理文件的方式来处理键盘输入。
例如,程序读文件要检测文件结尾才能知道何时停止。而键盘输入就是一个文件,你输入到什么字符时,程序会检测到并停止。
少部分系统使用Ctrl+Z。比如ngnag ^Z
,系统读到Ctrl+Z就结束。
还有一些系统会存储文件大小信息,如果文件有300字节,则程序读完300字节后就会停止。比如Unix系统。
getchar()检测到文件结尾时会返回一个EOF。他-1的宏定义,在stdio.h文件中。
#define EOF (-1)
因为getchar()本身返回的是读取的下一个字符,-1作为他读取到结束符。
int main(void)
{
int ch;
while ((ch = getchar()) != EOF) // while not end of line
{
putchar(ch);
}
return 0;
}
因为EOF是-1所以变量ch要改为int,而且getchar()实际返回类型也为int。
上述例子,我们输入一行,按回车后,会刷新缓冲区。程序getchar()就会依次读入输入的一行并打印。
当打印完成后继续等待输入。
在大多数Unix和Linux系统会使用Ctrl+D
作为输入结束符。
asdn aslkd
asdn aslkd
aghn
aghn
重定向是命令行概念,而不是C程序中的概念。
前面我们说过stdin是输入流,我们键盘的输入作为输入和stdin输入流相关联。
我们还可以使用文件内容作为stdin输入流,这样getchar()函数也可以使用。
程序并不关心输入的内容是来自键盘还是文件,他只知道这是要导入的字符流
我们可以使用程序读取文件1.txt
./echo_eof < 1.txt
int main(void)
{
int ch;
while ((ch = getchar()) != EOF) // while not end of line
{
putchar(ch);
}
return 0;
}
由于文件末尾会有结束符,所以程序可以读到结束符然后结束。
./echo_eof > 1.txt
他会把程序输出到1.txt文件中
比如我读入一个文件,进入程序,然后程序的输入到另一个文件
./echo_eof < in.txt > out.txt
./echo_eof > out.txt < in.txt
上面两句一样,因为重定向符号没有顺序。