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


    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;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    如果我在键盘输入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;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    当我们输入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;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    上面的示例中我们就可以读取一行输入的字符串并且可以带空格了。

    我们也可以使用特定的字符作为结束

    while ((ch = getchar()) != '#')        // while not end of line   
    
    • 1

    这样当我们输入
    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;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    因为EOF是-1所以变量ch要改为int,而且getchar()实际返回类型也为int。
    上述例子,我们输入一行,按回车后,会刷新缓冲区。程序getchar()就会依次读入输入的一行并打印。
    当打印完成后继续等待输入。
    在大多数Unix和Linux系统会使用Ctrl+D作为输入结束符。

    asdn aslkd
    asdn aslkd
    aghn
    aghn
    
    • 1
    • 2
    • 3
    • 4

    重定向

    重定向是命令行概念,而不是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;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    由于文件末尾会有结束符,所以程序可以读到结束符然后结束。

    重定向输出

    ./echo_eof > 1.txt他会把程序输出到1.txt文件中

    组合重定向

    比如我读入一个文件,进入程序,然后程序的输入到另一个文件
    ./echo_eof < in.txt > out.txt
    ./echo_eof > out.txt < in.txt
    上面两句一样,因为重定向符号没有顺序。

  • 相关阅读:
    LeetCode --- 1491. Average Salary Excluding the Minimum and Maximum Salary 解题报告
    Hive ,Hsql行转列、列转行实现
    vmware扩容CentOS磁盘的两种方案
    Excel - VBA实例: 遍历若干cell的值
    java-php-net-python-东软健身会员网站计算机毕业设计程序
    在mybatis的xml中使用枚举来做判断条件
    嵌入式Linux应用开发-基础知识-第十九章驱动程序基石③
    excel功能区(ribbonx)编程笔记--5 菜单
    【分布式云储存】Springboot微服务接入MinIO实现文件服务
    Spring如何解决循环依赖问题
  • 原文地址:https://blog.csdn.net/chongbin007/article/details/125359167