当前位置:网站首页>C primer plus学习笔记 —— 3、字符的IO(输入/输出)

C primer plus学习笔记 —— 3、字符的IO(输入/输出)

2022-06-26 19:43:00 Charles Ren

getchar()和putchar()

上一章介绍的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
分析一下:

  1. 当我们输入完字符串回车后,实际输入为ndn ang\n表示输入一行完成。
  2. ch这时读取输入的第一个字符
  3. 然后进行判断,不是换行符,就会打印,
  4. 打印后再次调用getchar()就表示读取刚才输入的一行队列中的下一个字符。
  5. 然后再进行判断是否是换行符,不是再打印,依次类推。

上面代码可以简写,将循环替换

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。

  1. 完全缓冲: 当缓冲区被填满的时候才刷新缓冲区(也就是将内容发送至目的地然后清空缓冲区)。通常出现在文件输入中,缓冲区大小通常取决于系统常见的512B或4K。
  2. 行缓冲:指当出现换行符就时刷新缓冲区(也就是将内容发送至目的地然后清空缓冲区)。键盘输入通常为行缓冲输入,在按下Enter键后才刷新缓冲区

键盘输入结束符

上面的例子中,我们一个使用回车来结束,另一个是用‘#’符号来结束程序。
这些符号都是常用的,我们不应该用常用符号来结束程序。所以我们应该想个办法用一个比较唯一的东西来结束,C提供了这样的一个字符。

文件

先简单介绍一下文件的概念,他是存储器中存储信息的区域。
程序会经常操作文件,比如打开,读取,关闭写入等。

为何用统一C标准IO

C语言在会调用底层IO也就是操作系统函数来操作文件。比如linux系统函数write() open()等。
但是如果在windows上,直接调用write() open 就不行了,需要调用windows的系统函数。所以C语言将不同系统的文件处理函数封装成了C的标准IO包。他来处理不同系统的差异,暴露给用户统一的函数比如fopen(),fwrite()等。

处理文件差异

不同的系统不仅暴露处理文件函数不同,他们各自处理文件的方式也不同。比如有些系统把文件内容存储在一处,文件相关信息存储在另一处。而有些系统会在每个文件中创建专门的文件描述。
不同的系统还会用不同的文件结尾。

C处理输入的方式

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
上面两句一样,因为重定向符号没有顺序。

原网站

版权声明
本文为[Charles Ren]所创,转载请带上原文链接,感谢
https://chongbin.blog.csdn.net/article/details/125359167