【跟着陈七一起学C语言】今天总结:C语言的输入/输出相关知识

news/2024/11/17 21:33:13/

友情链接:专栏地址

知识总结顺序参考C Primer Plus(第六版)和谭浩强老师的C程序设计(第五版)等,内容以书中为标准,同时参考其它各类书籍以及优质文章,以至减少知识点上的错误,同时方便本人的基础复习,也希望能帮助到大家
 
最好的好人,都是犯过错误的过来人;一个人往往因为有一点小小的缺点,将来会变得更好。如有错漏之处,敬请指正,有更好的方法,也希望不吝提出。最好的生活方式就是和努力的大家,一起奔跑在路上


文章目录

  • 【思维导图】
  • 🚀字符输入/输出和输入验证
    • ⛳一、单字符I/O:getchar()和putchar()
      • 🎈(一)getchar()
      • 🎈(二)putchar()
    • ⛳二、缓冲区
      • 🎈(一)缓冲输入和无缓冲输入
      • 🎈(二)使用缓冲输入
      • 🎈(三)完全缓冲I/O和行缓冲I/O
    • ⛳三、键盘输入和文件
      • 🎈(一)文件、流和键盘输入
      • 🎈(二)文件结尾
        • 1.检测文件结尾
        • 2.返回值EOF
    • ⛳四、重定向连接程序和文件
      • 🎈(一)重定向输入
      • 🎈(二)重定向输出
      • 🎈(三)组合重定向
    • ⛳五、输入输出中需要注意的问题
      • 🎈(一)缓冲输入带来的问题
      • 🎈(二)混合数值和字符输入
    • ⛳六、输入验证(防御性编程)
    • ⛳七、C语言实现菜单浏览


【思维导图】

在这里插入图片描述

我的总结方式一般是先搞一段程序过来,然后再逐行的学习相关的知识点

 

🚀字符输入/输出和输入验证

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

getchar()和 putchar()每次只处理一个字符。你可能认为这种方法实在太笨拙了,毕竟与我们的阅读方式相差甚远。但是,这种方 法很适合计算机。而且,这是绝大多数文本(即,普通文字)处理程序所用的核心方法。
 
自从ANSI C标准发布以后,C就把stdio.h头文件与使用getchar()和 putchar()相关联,这就是为什么程序中要包含这个头文件的原因(其实, getchar()和 putchar()都不是真正的函数,它们被定义为供预处理器使用的宏,

🎈(一)getchar()

getchar函数是从标准的输入设备(如键盘)上输入一个字符,不带任何参数,格式为:
getchar():
getchar函数将输入的第一个字符作为函数的返回值,通常使用这个函数时,将函数的返回值赋予一个字符变量或者整型变量。

#include <stdio.h> //getchar是C语言的标准库函数
int main()
{	char ch;ch = getchar();printf("%c %d\n",ch,ch);printf("%c %d\n",ch-32,ch-32);return 0;
}

程序运行时输入 abc。得到结果应该为a

🎈(二)putchar()

putchar函数是向标准输出设备(屏幕)上输出一个字符的C语言标准函数,格式为:
putchar(ch);
ch可以是变量、常量,转义字符或表达式。数据类型可以是字符型或整型。当ch是整型数据时,输出的是与其相对应的ASCII码值。

#include <stdio.h>
int main()
{   int p;char q; //此时定义的是字符变量,不是字符串,所以只能将一个字符的值赋予qp=98;q='a';putchar(p);printf("\n");putchar(q);return 0;
}

执行结果输出:

b 
a

 

⛳二、缓冲区

🎈(一)缓冲输入和无缓冲输入

无缓冲输入:即正在等待的程序可立即使用输入的字符

缓冲输入:用户输入的字符被收集并储存在一个被称为缓冲区(buffer)的临时存储区,按下Enter键后,程序才可使用用户输入的字符

为什么要有缓冲区:首先,把若干字符作为一个块进行传输比逐个发送 这些字符节约时间。其次,如果用户打错字符,可以直接通过键盘修正错误。当最后按下Enter键时,传输的是正确的输入。

拓展:
 
1.虽然缓冲输入好处很多,但是某些交互式程序也需要无缓冲输入。例如,在游戏中,你希望按下一个键就执行相应的指令。因此,缓冲输入和无缓冲输入都有用武之地。
 
2.ANSI C和后续的C标准都规定输入是缓冲的
 
3.回显无缓冲输入的getche()函数和用于无回显无缓冲输入的getch()函数(回显输入意味着用户输入的字符直接显示在屏幕上,无回显输入意味着击键后对应的字符不显示)
 
4.UNIX系统使用另一种不同的方式控制缓冲。在 UNIX系统中,可以使用ioctl()函数(该函数属于UNIX库,但是不属于C标 准)指定待输入的类型,然后用getchar()执行相应的操作

在这里插入图片描述

🎈(二)使用缓冲输入

缓冲输入用起来比较方便,因为在把输入发送给程序之前,用户可以编辑输入。但是,在使用输入的字符时,它也会给程序员带来麻烦。缓冲输入要求用户按下Enter键发送输入。这一动作也传送了换行符,程序必须妥善处理这个麻烦的换行符。

🎈(三)完全缓冲I/O和行缓冲I/O

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

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

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

⛳三、键盘输入和文件

🎈(一)文件、流和键盘输入

文件:文件(file)是存储器中储存信息的区域。通常,文件都保存在某种永久存储器中(如,硬盘、U盘或DVD等)。毫无疑问,文件对于计算机系统相当重要。例如,你编写的C程序就保存在文件中,用来编译C程序的程序也保存在文件中

后者说明,某些程序需要访问指定的文件。当编译储存在名为 echo.c 文件中的程序时,编译器打开echo.c文件并读取其中的内容。当编译器处理完后,会关闭该文件。其他程序,例如文字处理器,不仅要打开、读取和关闭文件,还要把数据写入文件。C 是一门强大、灵活的语言,有许多用于打开、读取、写入和关闭文件的库函数

1.C可以使用主机操作系统的基本文件工具直接处理文件,这些直接调用操作系统的函数被称为底层 I/O (low-level I/O)。 由于计算机系统各不相同,所以不可能为普通的底层I/O函数创建标准库, ANSI C也不打算这样做
 
然而从较高层面上,C还可以通过标准I/O包 (standard I/O package)来处理文件。这涉及创建用于处理文件的标准模型和一套标准I/O函数。在这一层面上,具体的C实现负责处理不同系统的差异,以便用户使用统一的界面。
 
2.上面讨论的差异指的是什么?例如,不同的系统储存文件的方式不同。 有些系统把文件的内容储存在一处,而文件相关的信息储存在另一处;有些系统在文件中创建一份文件描述。在处理文件方面,有些系统使用单个换行符标记行末尾,而其他系统可能使用回车符和换行符的组合来表示行末尾。 有些系统用最小字节来衡量文件的大小,有些系统则以字节块的大小来衡量。
 
如果使用标准 I/O 包,就不用考虑这些差异。因此,可以用 if (ch == ‘\n’)检查换行符。即使系统实际用的是回车符和换行符的组合来标记行末尾,I/O函数会在两种表示法之间相互转换。

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

键盘输入:绝大部分系统(不是全部)都有办法通过键盘模拟文件结尾条件,C把输入和输出设备视为存储设备上的普通文件,尤其是把键盘和显示设备视为每个C程序自动打开的文件。stdin流表示键盘输入,stdout流表示屏幕输出。getchar()、putchar()、 printf()和scanf()函数都是标准I/O包的成员,处理这两个流。

🎈(二)文件结尾

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

1.检测文件结尾

检测文件结尾的一种方法是,在文件末尾放一个特殊的字符标记文件结尾

CP/M、IBM-DOS和MS-DOS的文本文件曾经用过这种方法。如今,这些操作系统可以使用内嵌的Ctrl+Z字符来标记文件结尾。这曾经是操作系统使用的唯一标记, 不过现在有一些其他的选择,例如记录文件的大小。所以现代的文本文件不一定有嵌入的Ctrl+Z,但是如果有,该操作系统会将其视为一个文件结尾标记

在这里插入图片描述

操作系统使用的另一种方法是储存文件大小的信息。

如果文件有3000字节,程序在读到3000字节时便达到文件的末尾。MS-DOS 及其相关系统使用这种方法处理二进制文件,因为用这种方法可以在文件中储存所有的字符, 包括Ctrl+Z。新版的DOS也使用这种方法处理文本文件。UNIX使用这种方法处理所有的文件。

2.返回值EOF

无论操作系统实际使用何种方法检测文件结尾,在C语言中,用getchar()读取文件检测到文件结尾时将返回一个特殊的值,即EOF(end of file的缩写)。scanf()函数检测到文件结尾时也返回EOF

通常, EOF定义在stdio.h文件中:#define EOF (-1)

为什么是-1?因为getchar()函数的返回值通常都介于0~127,这些值对 应标准字符集。但是,如果系统能识别扩展字符集,该函数的返回值可能在 0~255之间。无论哪种情况,-1都不对应任何字符,所以,该值可用于标记文件结尾。
 
某些系统也许把EOF定义为-1以外的值,但是定义的值一定与输入字符所产生的返回值不同。如果包含stdio.h文件,并使用EOF符号,就不必担心EOF值不同的问题。这里关键要理解EOF是一个值,标志着检测到文件结尾,并不是在文件中找得到的符号。

如何在程序中使用EOF?

把getchar()的返回值和EOF作比较。如果两值不同,就说明没有到达文件结尾。也就是说,可以使用下面这样的表达式:

int ch;
while ((ch = getchar()) != EOF)
  1. 不用定义EOF,因为stdio.h中已经定义过了。
  2. 不用担心EOF的实际值,因为EOF在stdio.h中用#define预处理指令定义,可直接使用,不必再编写代码假定EOF为某值。
  3. 变量ch的类型从char变为int,因为char类型的变量只能表示0~255的无符号整数,但是EOF的值是-1,还好,getchar()函数实际返回值的类型是 int,所以它可以读取EOF字符。如果实现使用有符号的char类型,也可以把 ch声明为char类型,但最好还是用更通用的形式。
  4. 由于getchar()函数的返回类型是int,如果把getchar()的返回值赋给char类 型的变量,一些编译器会警告可能丢失数据。
  5. 使用该程序进行键盘输入,要设法输入EOF字符。不能只输入字符EOF,也不能只输入-1(输入-1会传送两个字符:一个连字符和一个数字 1)。正确的方法是,必须找出当前系统的要求。例如,在大多数UNIX和 Linux系统中,在一行开始处按下Ctrl+D会传输文件结尾信号。许多微型计算机系统都把一行开始处的Ctrl+Z识别为文件结尾信号,一些系统把任意位置的Ctrl+Z解释成文件结尾信号。
     

⛳四、重定向连接程序和文件

程序可以通过两种方式使用文件。

第 1 种方法是,显式使用特定的函数打开文件、关闭文件、读取文件、写入文件,诸如此类。

第 2 种方法是,设计能与键盘和屏幕互动的程序,通过不同的渠道重定向输入至文件和从文件输出。

换言之,把stdin流重新赋给文件。继续使用getchar()函数从输入流中获取数据,但它并不关心从流的什么位置获取数据。虽然这种重定向的方法在某些方面有些限制,但是用起来比较简单,而且能让读者熟悉普通的文件处理技术。

重定向的一个主要问题与操作系统有关,与C无关。尽管如此,许多C 环境中(包括UNIX、Linux和Windows命令提示模式)都有重定向特性,而 且一些C实现还在某些缺乏重定向特性的系统中模拟它。

🎈(一)重定向输入

重定向输入让程序使用文件而不是键盘输入

echo_eof < words

<符号是UNIX和DOS/Windows的重定向运算符。该运算符使words文件与stdin流相关联,把文件中的内容导入echo_eof程序。echo_eof程序本身并不知道(或不关心)输入的内容是来自文件还是键盘,它只知道这是需要导入的字符流,所以它读取这些内容并把字符逐个打印在屏幕上,直至读到文件结尾。因为C把文件和I/O设备放在一个层面,所以文件就是现在的I/O设 备

🎈(二)重定向输出

重定向输出让程序输出至文件而不是屏幕

echo_eof>mywords

>符号是第2个重定向运算符。它创建了一个名为mywords的新文件,然后把echo_eof的输出(即,你输入字符的副本)重定向至该文件中。重定向把stdout从显示设备(即,显示器)赋给mywords文件。如果已经有一个名为 mywords的文件,通常会擦除该文件的内容,然后替换新的内容(但是,许 多操作系统有保护现有文件的选项,使其成为只读文件)。所有出现在屏 的字母都是你刚才输入的,其副本储存在文件中。在下一行的开始处按下 Ctrl+D(UNIX)或Ctrl+Z(DOS)即可结束该程序

🎈(三)组合重定向

假设希望制作一份mywords文件的副本,并命名为savewords。 只需输入以下命令即可:

echo_eof < mywords > savewordsecho_eof > savewords < mywords

在UNIX、Linux或Windows/DOS系统中使用两个重定向运算符 (<和>)时,要遵循以下原则:

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

重定向是一个命令行概念,因为我们要在命令行输入特殊的符号发出指令
 
如果不使用命令行环境,也可以使用重定向。首先,一些集成开发环境提供了菜单选项,让用户指定重定向。其次,对于 Windows系统,可以打开命令提示窗口,并在命令行运行可执行文件。
 

⛳五、输入输出中需要注意的问题

🎈(一)缓冲输入带来的问题

混合使用 getchar()和 scanf()时,如果在调用 getchar()之前,scanf()在输入行留下一个换行符,会导致一些问题。不过,意识到这个问题就可以在程序中妥善处理

🎈(二)混合数值和字符输入

假设程序要求用 getchar()处理字符输入,用 scanf()处理数值输入,这两 个函数都能很好地完成任务,但是不能把它们混用。因为 getchar()读取每个 字符,包括空格、制表符和换行符;而 scanf()在读取数字时则会跳过空格、 制表符和换行符。
 

⛳六、输入验证(防御性编程)

在实际应用中,用户不一定会按照程序的指令行事。用户的输入和程序 期望的输入不匹配时常发生,这会导致程序运行失败。作为程序员,除了完成编程的本职工作,还要事先预料一些可能的输入错误,这样才能编写出能检测并处理这些问题的程序。

常用的方法:

  1. 使用关系表达式来排除
  2. 检查scanf()的返回值
  3. 常需要涉及if选择结构
     

⛳七、C语言实现菜单浏览

许多计算机程序都把菜单作为用户界面的一部分。菜单给用户提供方便的同时,却给程序员带来了一些麻烦。

在这里插入图片描述

同样也是第五点中提到的问题


行文至此,落笔为终。文末搁笔,思绪驳杂。只道谢不道别。早晚复相逢,且祝诸君平安喜乐,万事顺意。


http://www.ppmy.cn/news/40990.html

相关文章

python 变量类型标注

目录 一、概述 1、描述 2、常用的数据类型 3、mypy模块 二、使用 1、基本使用 2、函数参数返回值添加类型标注 1. 指定多个参数的方式 2. Callable 3. Iterator 2、混合类型检查改进 1.联合运算符 3、类型别名更改 一、概述 1、描述 变量类型注解是用来对变量和函…

matplotlib 齐次坐标系 绘制 2D 闪烁斑点

绘制闪烁的斑点群&#xff0c;需要考虑几个群体属性&#xff1a;群体的生成位置 (xylim)&#xff0c;斑点数量 (n)&#xff0c;斑点的半径均值 (r)&#xff0c;斑点的寿命均值 (delta) 而对于每一个斑点&#xff0c;又需要考虑斑点个体属性&#xff1a;出生时间 (start)、出生位…

Makefile学习6 - 条件判断

一. 前言 条件判断语句可以根据一个变量的值来控制make执行或者忽略Makefile的特定部分。条件语句可以是两个不同变量或者变量与常量值的比较。条件语句只能用于控制make实际执行的Makefile文件部分&#xff0c;不能控制规则的shell的执行过程。Makefile使用条件控制可以做到处…

Java知识点学习(第5天)

重载和重写的区别 重载&#xff1a;发生在同一个类中&#xff0c;方法名必须相同&#xff0c;参数类型不同、个数不同、顺序不同、方法返回值和访问修饰符可以不同&#xff0c;发生在编译的时候。 重写&#xff1a;发生在父子类中&#xff0c;方法名、参数列表必须相同&#…

国货之光!打工人必装的8个软件,你都用过没?|办公|效率|创作

给大家分享8款非常强大&#xff0c;但知名度不高的国产软件&#xff0c;每一个都堪称精品&#xff0c;喜欢的话记得点赞和关注哦~ 第一款是 火绒安全软件 火绒安全软件没有任何&#xff0c;具有推广性质的弹窗、没有捆绑打扰用户的行为&#xff1b;占用资源极少&#xff0c;&a…

【Docker】Docker安装Hadoop分布式集群

Docker安装分布式Hadoop集群 一、准备环境 1. 查看docker的hadoop镜像 docker search hadoop2. 拉取stars最多的镜像 docker pull sequenceiq/hadoop-docker3. 拉取完成后查看镜像是否已到本地 docker images 4. 运行第一个容器hadoop102 docker run --name hadoop102 …

不可变数据类型

不可变对象 不可变(immutable)&#xff1a; 即对象一旦被创建初始化后&#xff0c;内存中该类型的值永远不会改变&#xff0c;之后的每次改变都会产生一个新对象。 作为不可变类型&#xff0c;最主要的特性表现是&#xff1a;一旦创建&#xff0c;只要修改&#xff0c;就会在托…

cv2(OpenCV)下载安装

cv2对应库是OpenCV&#xff0c;官网下载链接&#xff1a;https://www.lfd.uci.edu/~gohlke/pythonlibs/#opencv 最好下载对应python版本的&#xff0c;通过pip命令安装可能会出现版本过高或者过低的问题&#xff0c;导致import cv2没问题&#xff0c;但是内部函数无法调用。 …