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

news2025/1/18 4:30:57

文章目录

  • 前言
  • 一、单字符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() 返回类型为 int
	while ((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')直到\n
            continue;
    }
    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);
        else
            printf("I understand only n or y\n");
        while (getchar() != '\n')
           ;
    }
    printf("I knew I could do it!\n");
    return 0;
}

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

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Linux多线程[二]

线程同步 一个资源&#xff0c;我们不知道他是不是准备好了资源&#xff0c;就需要频繁申请。这时候对于这个执行流&#xff0c;多次检测&#xff0c;极大的浪费了资源。而且对于资源来说一个线程多次申请资源的时候&#xff0c;他一直申请到资源&#xff0c;别的线程申请不到…

debug - 打补丁 - 浮点数加法

文章目录 debug - 打补丁 - 浮点数加法概述笔记demo用CE查看汇编(x64debug)main()update_info()快捷键 - CE中查看代码时的导航打补丁的时机 - 浮点数加法补丁代码补丁效果浮点数寄存器组的保存END debug - 打补丁 - 浮点数加法 概述 在cm中, UI上显示的数值仅仅用来显示, 改…

微信公众号怎么做收集信息功能_轻松打造信息收集神器

微信公众号&#xff1a;轻松打造信息收集神器&#xff0c;让您的业务更上一层楼&#xff01; 在数字化时代&#xff0c;信息的传递与收集已成为企业和个人成功的关键。微信&#xff0c;作为中国最大的社交平台之一&#xff0c;其公众号功能为企业和个人提供了一个绝佳的信息收…

第三百四十七回

文章目录 1. 概念介绍2. 原理与方法2.1 知识对比2.2 使用方法 3. 示例代码4. 内容总结 我们在上一章回中介绍了"加密包crypto"相关的内容&#xff0c;本章回中将介绍characters包.闲话休提&#xff0c;让我们一起Talk Flutter吧。 1. 概念介绍 在项目中会遇到获取字…

2024年【起重机司机(限门式起重机)】考试及起重机司机(限门式起重机)模拟考试题

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 起重机司机(限门式起重机)考试是安全生产模拟考试一点通总题库中生成的一套起重机司机(限门式起重机)模拟考试题&#xff0c;安全生产模拟考试一点通上起重机司机(限门式起重机)作业手机同步练习。2024年【起重机司机…

第13章 网络 Page734 “I/O对象”的链式传递 单独的火箭发射函数,没有用对的智能指针

上一篇博文中&#xff0c;我们使用单独的火箭发射函数&#xff0c;结果什么结果也没有得到&#xff0c;原因是launch_rocket()函数结束时&#xff0c;其内的局部对象counter生命周期也结束了 那么可以将counter改为指针吗&#xff1f;在堆中分配&#xff0c;这样当函数退出时&…

SpringBoot+Tess4J实现本地与远程图片的文字识别

Spring Boot应用程序里集成Tess4J来实现OCR&#xff08;光学字符识别&#xff09;&#xff0c;以识别出本地和远程图片中的文字 一、添加依赖 <dependency><groupId>net.sourceforge.tess4j</groupId><artifactId>tess4j</artifactId><vers…

基于Echarts的可视化项目

整体的效果 概览区域 <!-- 概览区域模块制作 --><div class"panel overview"><div class"inner"><ul><li><h4>2190</h4><span><i class"icon-dot"></i>设备总数</span></…

洛谷C++简单题小练习day12—寻找最小值小程序

day12--寻找最小值--2.16 习题概述 题目描述 给出 n 和 n 个整数 ai​&#xff0c;求这 n 个整数中最小值是什么。 输入格式 第一行输入一个正整数 n&#xff0c;表示数字个数。 第二行输入 n 个非负整数&#xff0c;表示 1,2…a1​,a2​…an​&#xff0c;以空格隔开。 …

Android ·移动应用开发 创建第一个Android项目

文章目录 一、创建第一个Android项目1.1 准备好Android Studio1.2 运行程序1.3 程序结构是什么app下的结构res - 子目录&#xff08;所有图片、布局、字符串等资源&#xff09;AndroidManifest.xml 有四大组件&#xff0c;程序添加权限声明 Project下的结构 二、开发android时&…

极市平台 | 16个图像分类方向开源数据集资源汇总(附下载链接,建议收藏!)

本文来源公众号“极市平台”&#xff0c;仅用于学术分享&#xff0c;侵权删&#xff0c;干货满满。 原文链接&#xff1a;16个图像分类方向开源数据集资源汇总&#xff08;附下载链接&#xff09; 本文汇总了16个图像分类相关的开源数据集&#xff0c;均附有下载链接。要构建…

苹果手机计算器怎么进行快速删除(退格)?

文章目录 前言方法 前言 总所周知&#xff0c;不论是学生、商人&#xff0c;还是工人&#xff0c;都必须使用计算器。其中&#xff0c;苹果手机的自带计算器&#xff0c;因为完美的环境&#xff0c;所以受到大多数人的喜爱&#xff0c;使用率极高。但是&#xff0c;苹果计算器…

嵌入式Linux网络编程入门:轻松构建网络通信

大家好&#xff0c;今天给大家介绍嵌入式Linux网络编程入门&#xff1a;轻松构建网络通信&#xff0c;文章末尾附有分享大家一个资料包&#xff0c;差不多150多G。里面学习内容、面经、项目都比较新也比较全&#xff01;可进群免费领取。 为什么选择嵌入式Linux网络编程&#x…

Git快速掌握,通俗易懂

Git分布式版本控制工具 介绍 Git是一个开源的分布式版本控制系统&#xff0c;用于敏捷高效地处理任何或小或大的项目。Git是由Linus Torvalds为了帮助管理Linux内核开发而开发的一个开放源码的版本控制软件。Git可以帮助开发者们管理代码的版本&#xff0c;避免代码冲突&#…

RabbitMQ配置消息转换器

1. 默认转换器 Test public void testSendMap() throws InterruptedException {// 准备消息Map<String, Object> msg new HashMap<>();msg.put("name", "harry");msg.put("age", 21);// 发送消息rabbitTemplate.convertAndSend(&q…

FreeRTOS知识点

1>任务调度算法 1.抢占式调度&#xff1a;高优先级的任务优先执行&#xff0c;并且可以打断低优先级的任务执行。 在FreeRTOSConfig.h中开启configUSE_PREEMPTION宏&#xff0c;将宏设置为1&#xff0c;关闭&#xff08;将宏设置为0&#xff09; 2.时间片轮转&#xff1a…

什么是 Flet?

什么是 Flet&#xff1f; Flet 是一个框架&#xff0c;允许使用您喜欢的语言构建交互式多用户 Web、桌面和移动应用程序&#xff0c;而无需前端开发经验。 您可以使用基于 Google 的 Flutter 的 Flet 控件为程序构建 UI。Flet 不只是“包装”Flutter 小部件&#xff0c;而是…

Repo命令使用实例(三十八)

简介&#xff1a; CSDN博客专家&#xff0c;专注Android/Linux系统&#xff0c;分享多mic语音方案、音视频、编解码等技术&#xff0c;与大家一起成长&#xff01; 优质专栏&#xff1a;Audio工程师进阶系列【原创干货持续更新中……】&#x1f680; 优质专栏&#xff1a;多媒…

动态多目标优化算法基准测试问题JY

论文题目&#xff1a;Evolutionary Dynamic Multiobjective Optimization: Benchmarks and Algorithm Comparisons 进化动态多目标优化&#xff1a;基准测试和算法比较&#xff08;Shouyong Jiang and Shengxiang Yang, Senior Member, IEEE&#xff09;IEEE TRANSACTIONS ON …

【UE4】 通过按钮点击实现摄像机的切换 并通过鼠标控制新摄像机的旋转

效果 步骤 首先创建了4个Actor蓝图类 每个蓝图类内只拥有一个摄像机组件 将每个actor蓝图类摆放到场景的合适位置 在关卡蓝图中创建自定义事件&#xff0c;当该事件触发时切换摄像机 创建一个控件蓝图&#xff0c;在控件蓝图中创建如下5个按钮&#xff0c;并创建点击事件。按钮…