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

文章目录

  • 前言
  • 一、单字符I/O
  • 二、缓冲区
    • 为什么要引入缓冲区?
    • 文件结尾
    • 补充
    • ==**注意几点**==
  • 重定向和文件
    • 重定向输入
    • cmd是什么?
    • 重定向输出
    • 组合重定向
    • 小试牛刀:文件输出
  • 创建更友好的用户界面
    • 使用缓冲输入
  • 如果您发现文章有错误请与我留言,感谢


前言


`

一、单字符I/O

getchar()和putchar()每一次只能处理一个字符。
你可能认为这种方法实在太笨拙了,毕竟与我们的阅读方式相差甚远。但是,这种方法很适合计算机。而且,这是绝大多数文本(即,普通文字)处理程序所用的核心方法。为了帮助读者回忆这些函数的工作方式,请看程序 。该程序获取从键盘输入的字符,并把这些字符发送到屏幕上。程序使用while循环,当读到#字符时停止。

#include<stdio.h>
int main()
{char ch;while ((ch = getchar()) != '#')putchar(ch);return 0;
}

在这里插入图片描述

读者可能好奇,为何输入的字符能直接显示在屏幕上?如果用一个特殊字符(如,#)来结束输入,就无法在文本中使用这个字符,是否有更好的方法结束输入?要回答这些问题,首先要了解C程序如何处理键盘输入,尤其是缓冲和标准输入文件的概念。

二、缓冲区

在这里插入图片描述
每一个数都是重复的,像这样回显用户输入的字符后立即重复打印该字符是属于无缓冲(或直接)输入,即正在等待的程序可立即使用输入的字符。

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

在这里插入图片描述

为什么要引入缓冲区?

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

虽然缓冲输入好处很多,但是某些交互式程序也需要无缓冲输入。
例如,在游戏中,你希望按下一个键就执行相应的指令因此,缓冲输入和无缓冲输入都有用武之地。

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

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

程序使用的缓冲是行缓冲。键盘输入通常是行缓冲输入,所以在按下Enter键后才刷新缓冲区。

本章着重理解C把输入和输出设备视为存储设备上的普通文件,尤其是把键盘和显示设备视为每个C程序自动打开的文件stdin流表示键盘输入,stdout流表示屏幕输出。 getchar()、putchar()、printf()和scanf()函数都是标准I/O包的成员,处理这两个流。

以上讨论的内容说明,可以用处理文件的方式来处理键盘输入。例如,程序读文件时要能检测文件的末尾才知道应在何处停止,因此,C的输入函数内置了文件结尾检测器。既然可以把键盘输入视为文件,那么也应该能使用文件结尾检测器结束键盘输入。下面我们从文件开始,学习如何结束文件。

文件结尾

计算机操作系统要以某种方式判断文件的开始和结束。检测文件结尾的一种方法是,在文件末尾放一个特殊的字符标记文件结尾。 检测文件结尾的一种方法是,在文件末尾放一个特殊的字符标记文件结尾。

这个特殊的字符标记一般是:Ctrl+Z。

在下面的程序中,要结束输入,在按下 Ctrl+Z后,程序会就结束。

在这里插入图片描述

补充

getchar()函数

int getchar (void)

getchar()函数的返回类型为 int 整型 参数为 void

此时大家肯定会想,getchar()函数不是用来输入单个字符的吗,为什么返回类型为 int 整型呢 ?
1、getchar其实返回的是字符的ASCII码值(整数)。
2、getchargetchar在读取结束或者失败的时候,会返回EOF。

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

为什么是-1?
因为getchar()函数的返回值通常都介于0~127,这些值对应标准字符集。
但是,如果系统能识别扩展字符集,该函数的返回值可能在0~255之间。
所以无论哪种情况,-1都不对应任何字符,所以,该值可用于标记文件结尾。
某些系统也许把EOF定义为-1以外的值,但是定义的值一定与输入字符所产生的返回值不同。
另外,char型本身就是无符号型

#include <stdio.h>
#include <string.h>
int main()
{int ch = 0;  //因为 getchar() 返回类型为 intwhile ((ch = getchar()) != EOF) // 连续输入单个字符{printf("%c",ch);  // 输出一个字符//putchar(ch);    // 此时 printf("%c",ch) 与  putchar(ch)  输出结果一样}return 0;
}

此时 printf(“%c”,ch) 与 putchar(ch) 输出结果一样

注意几点

  • 不用定义EOF,因为stdio.h中已经定义过了
  • 不用担心EOF的实际值,因为在stdio.h中用#define 预处理指令定义,可以直接使用
  • 变量ch的值从char变成int,因为char类型的变量只能表示0~255的无符号整形,但是EOF的值是-1,还好,getchar()的实际返回值是int.所以他可以读取EOF字符
  • 使用该程序进行键盘输入,要设法输入EOF字符,而不是字符EOF,也不能输入-1(输入-1会传输两个值,一个连字符和一个字符1。)正确的方法是,找到当前系统的需求,许多系统会把一行最开始处的Ctrl + Z作为文件结尾的信号。

我们暂停一会。既然程序能把用户输入的内容拷贝到屏幕上,那么考虑一下该程序还可以做什么。(上面的程序文件名是pp.cpp)

假设以某种方式把一个文件传送给它,然后它把文件中的内容打印在屏幕上,当到达文件结尾发现EOF信号时停止。

或者,假设以某种方式把程序的输出定向到一个文件,然后通过键盘输入数据用pp.cpp 来储存在文件中输入的内容。

假设同时使用这两种方法:把输入从一个文件定向到pp.cpp中,并把输出发送至另一个文件,然后便可以使用pp.cpp来拷贝文件。

重定向和文件

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

重定向输入

我们找到pp.exe的位置

在这里插入图片描述

输入cmd
在这里插入图片描述

cmd是什么?

CMD是Windows操作系统中的命令提示符(Command Prompt)程序,它是一种命令行工具,可以让用户通过键入命令来与计算机进行交互。

CMD是Windows中一个基本的系统组件,它提供了一个简单的方式来执行诸如文件管理、网络管理、系统配置等各种任务。通过命令提示符,用户可以通过简单的命令来执行这些任务,而无需打开图形用户界面(GUI)。
————————————————

原文链接:https://blog.csdn.net/weixin_43783942/article/details/129470999

会出现这个界面
在这里插入图片描述
我们打开pp.exe,程序是可以运行的,输入Ctrl+Z终止程序。

在这里插入图片描述

创建一个pp.txt(文本文件),内容在右侧
在这里插入图片描述
下来把pp.txt的内容导入pp.exe程序

pp.exe<pp.txt

在这里插入图片描述
如果跨文件夹访问要加上文件位置

重定向输出

下来用键盘输入,输出给文件而不是屏幕

在这里插入图片描述
确实是输出到文件里了
在这里插入图片描述

组合重定向

把输入从一个文件pp2.txt定向到 pp.exe中,并把输出发送至另一个文件pp3.txt

没有任何问题

在这里插入图片描述

注意:在一条命令中,输入文件名和输出文件名不能相同。 echo_eof < mywords > mywords…<–错误
原因是> mywords在输入之前已导致原mywords的长度被截断为0.

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

  • 重定向运算符连接一个可执行程序(包括标准操作系统命令)和一个数据文件不能用于连接一个数据文件和另一个数据文件,也不能用于连接一个程序和另一个程序。

  • 使用重定向运算符不能读取多个文件的输入,也不能把输出定向至多个文件。

小试牛刀:文件输出

不使用重定向,因为重定向的可移植性差,用C语言程序直接打开文件。

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
int main()
{char fname[100];FILE* fp;int ch;printf("Enter the name of the file :");scanf("%s", fname);fp = fopen(fname, "r");if (fp == NULL){printf("Failed open the file,bye");exit(1);}while ((ch = getc(fp)) != EOF)putchar(ch);fclose(fp);return 0;
}

我想看看我写的代码,文件名是源.cpp

在这里插入图片描述
非常成功。

创建更友好的用户界面

大部分人偶尔会写一些中看不中用的程序。还好,C提供了大量工具让输入更顺畅,处理过程更顺利。不过,学习这些工具会导致新的问题。本节的目标是,指导读者解决这些问题并创建更友好的用户界面,让交互数据输入更方便,减少错误输入的影响。

使用缓冲输入

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

我们以一个猜谜程序为例。用户选择一个数字,程序猜用户选中的数字是多少。

我们关注的重点在输入和输出。缓冲区

#include <stdio.h>
#include <stdlib.h>
int main(void)
{int guess = 1;printf("Pick an integer from 1 to 100. I will try to guess it.\n");printf("Respond with a y if my guess is right and with an n if it's wrong.\n");printf("Uh...is your number %d?\n", guess);while(getchar()!='y')//scanf('%c',ch)=getchar(){printf("Well, then, is it %d?\n",++guess);}printf("I knew I could do it!\n");return 0;
}

可以看出,每次输入 n 时,程序打印了两条消息。这是因为输入 n 后,我们还按下了 Enter 进行换行,然后还读取了一个换行符,下一次循环中,getchar() 读取了这个换行符并打印了第二条消息。当我们输入多个字符时也会出现多行消息。

改进
使循环读取并丢弃输入的数据

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
int main(void)
{int guess = 1;printf("Pick an integer from 1 to 100. I will try to guess it.\n");printf("Respond with a y if my guess is right and with an n if it's wrong.\n");printf("Uh...is your number %d?\n", guess);while (getchar() != 'y')//no sir输入1.n{printf("Well, then, is it %d?\n", ++guess);while (getchar() != '\n')//2.o不等于\n继续循环while (getchar() != '\n')直到\ncontinue;}printf("I knew I could do it!\n");return 0;
}

在这里插入图片描述

continue的理解
1.continue本身的性质一直读到末尾
2.书上的意思是他只是一个占位符,

在这里插入图片描述
这的确是解决了换行符的问题。但是,该程序还是会把f被视为n。我们用if语句筛选其他响应.首先,添加一个char类型的变量储存响应:char r ;

修改后的循环如下:

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
int main(void)
{int guess = 1;char r;printf("Pick an integer from 1 to 100. I will try to guess it.\n");printf("Respond with a y if my guess is right and with an n if it's wrong.\n");printf("Uh...is your number %d?\n", guess);while ((r = getchar()) != 'y'){if ( r == 'n')printf("Well, then, is it %d?\n", ++guess);elseprintf("I understand only n or y\n");while (getchar() != '\n');}printf("I knew I could do it!\n");return 0;
}

如果您发现文章有错误请与我留言,感谢

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/470324.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

[职场] 优质简历怎么做 #学习方法#笔记

优质简历怎么做 简历是求职的“敲门砖”&#xff0c;直接影响着求职成败。然而&#xff0c;不少求职者对简历不太重视&#xff0c;认为简历就是写自己的经历。因此&#xff0c;在招聘现场&#xff0c;常会看到这样的简历&#xff1a;有的是从某招聘网站直接下载而来&#xff0c…

用163邮箱或者outlook接收国科大邮箱的邮件

使用如图下路径&#xff0c;创建一个新的密码&#xff0c;用于在163大师邮箱或者outlook登录即可 如果不行&#xff0c;则需要手动配置邮箱服务器 参考网址&#xff1a;中国科学院邮件系统帮助中心

AcWing 112. 雷达设备(区间贪心)

[题目概述] 假设海岸是一条无限长的直线&#xff0c;陆地位于海岸的一侧&#xff0c;海洋位于另外一侧。 每个小岛都位于海洋一侧的某个点上。 雷达装置均位于海岸线上&#xff0c;且雷达的监测范围为 d&#xff0c;当小岛与某雷达的距离不超过 d 时&#xff0c;该小岛可以被雷…

ChatGPT高效提问—prompt实践(漏洞风险分析-重构建议-识别内存泄漏)

ChatGPT高效提问—prompt实践&#xff08;漏洞风险分析-重构建议-识别内存泄漏&#xff09; 1.1 漏洞和风险分析 ChatGPT还可以帮助开发人员预测代码的潜在风险&#xff0c;识别其中的安全漏洞&#xff0c;而不必先运行它&#xff0c;这可以让开发人员及早发现错误&#xff0…

【VScode配置HTML如何编译 基础 JavaScript 实例】

基础 JavaScript 实例 VScode用JavaScript输出文本用JavaScript改变HTML元素一个外部JavaScript VScode 打开扩展搜索 右键看到即可 用JavaScript输出文本 <!DOCTYPE html> <html> <head> <meta charset"utf-8"> </head> <body…

计网体系结构

计算机网络的概述 概念 网络&#xff1a;网状类的东西或系统。 计算机网络&#xff1a;是一个将分散的、具有独立性功能的计算机系统&#xff0c;通过通信设备与线路连接起来&#xff0c;由功能完善的软件实现资源共享和信息传递的系统。即计算机网络是互连(通过通信链路互连…

VBAR设置方法

Uboot源码&#xff1a; /** Setup vector:* (OMAP4 spl TEXT_BASE is not 32 byte aligned.* Continue to use ROM code vector only in OMAP4 spl)*/ #if !(defined(CONFIG_OMAP44XX) && defined(CONFIG_SPL_BUILD))/* Set V0 in CP15 SCTLR register - for VBAR to …

Linux设置jar包开机自启动

步骤 1、新建jar包自启文件 sudo vi /etc/init.d/jarSysInit.sh 按i键进入编辑模式输入以下内容&#xff1a; export JAVA_HOME/home/jdk/jdk-11.0.22 export CLASSPATH.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar:$JAVA_HOME/jre/lib/rt.jar export PATH$PATH:$JAVA_…

FT2232调试记录(2)

FT2232调试记录 &#xff08;1&#xff09;获取当前连接的FTDI设备通道个数:&#xff08;2&#xff09;获取当前连接的设备通道的信息:&#xff08;3&#xff09;配置SPI的通道:&#xff08;4&#xff09;如何设置GPIO:&#xff08;5&#xff09;DEMO测试&#xff1a; FT2232调…

微信小程序开发学习笔记《17》uni-app框架-tabBar

微信小程序开发学习笔记《17》uni-app框架-tabBar 博主正在学习微信小程序开发&#xff0c;希望记录自己学习过程同时与广大网友共同学习讨论。建议仔细阅读uni-app对应官方文档 一、创建tabBar分支 运行如下的命令&#xff0c;基于master分支在本地创建tabBar子分支&#x…

Pure Pursuit控制器路径跟随

参考博客&#xff1a; Pure Pursuit 纯追踪法 Autoware(Pure pursuit代码学习) 1 Pure Pursuit纯追踪法 适用场景&#xff1a;低速场景&#xff08;速度过高会产生转弯内切以及超调&#xff09; 简化前轮转向角和后轴将遵循的曲率之间的关系 (Gx,Gy)是下一个需要追踪的路点&a…