C++排雷:17. 输入整行字符串的getline(空行输出、回车吸收)问题

需求:

  • 输入字符
  • 可选择整行输入和逐字输入两种模式
    问题代码:
#include<iostream>
#include<string>

using namespace std;
int main()

{
	int choice;
	cout << "整行输入请输入1,逐字输入请输入0\n";
	cin >> choice;
	
	if (choice==1)
	{
		string content_str;
		cout << "现在是整行输入模式\n"<<"请整行输入你要输入的内容\n";
		while (getline(cin, content_str))
		{
				cout << content_str << endl;
			//if (content_str.empty())
			//{
			//	break;
			//}
		}
	}
	
	else if(choice==0)
	{
		cout << "现在是逐字输入模式\n" << "请逐字输入你要输入的内容\n";
		char content_str;
		while (cin>>content_str )
		{
			cout << content_str<<endl;
		}
	}
	
	else
	{
		cout << "输入有误\n";
	}

	return 0;
}

我们choice输入1进入整行输入模式,运行结果如下:
在这里插入图片描述
很奇怪,还没有cin,就已经进入了结构体,运行了cout语句了。看来先进入循环后,执行一次再进行条件判断吧?

为了检测,这里把string content_str;

  • 修改为string content_str(“初始值”);
    再运行:
    在这里插入图片描述
    这一结果推翻了之前的推测,现在情况有些难以判断,所以设置断点进行debug:
    在这里插入图片描述进入while之前,初始值正确设置,讲道理,如果不先经过条件判断,直接运行语句的话,直接输出的应该是“初始值”而非空行。
    这里继续下一句,奇怪的事情发生了:
    在这里插入图片描述可以看到,本次并没有提示控制台输入,而是直接进入了结构体,一进去content_str的值就被清空了!
  • 个人认为这个错误是很严重的,如果我想以空行为条件判断,那么在程序一运行时,就直接进入了空行条件结构体了。

很奇怪啊,结构体是在content_str的作用域内的,为什么一进去就清空了呢?我怀疑是getline的作用,使cin直接接受了回车,将回车推到了content_str内,所以输出了空行。

那么回车是从哪里来的呢?分析整个流程:

  • 在确定输入模式的时候,我在控制台敲了1+回车
  • 在conten_str的定义下,输出的“ cout << “现在是整行输入模式\n”<<“请整行输入你要输入的内容\n”; ”当中有两个换行符

先考虑第一个情况,这里把模式1的代码块拿出来单独运行:
在这里插入图片描述果然!空行消失了
问题找到了,那,到底是什么原因,使前面cin输入的1+回车影响到了content_str呢?

原来键盘是输入到缓冲区的,cin 和cin.getline()实际上是从缓冲区读入数据,当缓冲区有内容时,会直接从缓冲区读取,不会要求键盘输入。

  • cin只是在缓存区中,把字符读走,会剩余/n在缓存区中
  • 但是getline对/n极度敏感,导致getline刚开始读入便遇到/n于是停止读入数据。

因此,要在cin与getline之间加入

  • cin.get();
  • 或cin.ignore();
    这样,程序就可以正常运行了,吸收了换行符后,可以加入循环退出语句:
			if (content_str.empty())
			{
				break;
			}

其中cin.get()用来舍弃输入流中不需要的字符 或者舍弃回车。
cin.ignore( a, ch )表示从 cin 中提取并忽略字符。而每抛弃一个字符,它都要进行计数和比较字符:如果计数值达到 a 或者被抛弃的字符是 ch ,则cin.ignore() 函数执行终止;否则,它继续等待。

  • cin.ignore(1024, ‘\n’),通常把第一个参数设置得足够大,这样实际上是为了只有第二个参数 ‘\n’
    起作用,所以这一句就是把回车(包括回车)之前的所以字符从输入缓冲流中清除出去。
  • 如果默认不给参数的话,默认参数为cin.ignore(1, EOF),即把EOF前的1个字符清掉,没有遇到EOF就清掉一个字符然后结束

热门文章

暂无图片
编程学习 ·

最流行的两种vue打包成apk框架,简述

最流行的两种vue打包成apk框架 1、使用Dcloud-HbuilderX打包app基础打包(可忽略)配置manifest.json文件 在HbuilderX中找到:发行—>原生app打包(云打包) 注意HbulderX一个账号只打包5次。 等待一段时间打包成功,查询打包状态,返回一个网站,打开下载即可。Vue项目打包ap…
暂无图片
编程学习 ·

flume采集多个文件夹日志

在flume1.6版本及之前,如果想要监控多个目录下的多个文件,可以使用Filelistener,在flume1.7之后,增加了TAILDIR,主要是监控文件的变化 参考配置: #配置Agent a1 的组件 a1.sources=r1 a1.sinks=s1 a1.channels=c1#描述/配置a1的source1 a1.sources.r1.type=TAILDIR #偏移量…
暂无图片
编程学习 ·

广东工业大学黎权之的百度云使用经验分享

广东工业大学黎权之的百度云使用经验分享 我将在这篇文章分享自己用了百度云这么多年来的经验。 一、百度云的分享链接食用方法 1.将分享链接完整的分享给别人 这种最直接,但如果是敏感资源的话链接容易失效 2.将分享链接/s/后的内容和提取码一同分享给别人 同样如果是敏感资源…
暂无图片
编程学习 ·

mvc:resources 配置不生效问题

学习springMVC框架的时候,用到jquery,于是配置mvc:resources标签,可是依然会拦截js文件,网上搜了很久都找不到原因,配置如下:于是仔细观察,原来是mapping和location写反了?修改如下:这样居然就可以了?大家普遍出现的关于mvc:resources标签的问题我就不说了,网上也会…
暂无图片
编程学习 ·

安装JDK

安装JDK 前提 要准备好jdk的包:jdk-8uxxx-linux-x64.tar.gz //JAVA 8 版本都可以 笔者这里使用的171 下载地址:Java SE 8 存档下载. 步骤 一、 解压jdk:tar -zxvf jdk-8u171-linux-x64.tar.gz二、 设置环境变量,编辑文件添加如下: vi /etc/profile export JAVA_HOME=/us…
暂无图片
编程学习 ·

(python version) 劍指offer 35. 复制链表的复制

题目描述 请实现 copyRandomList 函数,复制一个复杂链表。在复杂链表中,每个节点除了有一个 next 指针指向下一个节点,还有一个 random 指针指向链表中的任意节点或者 null。 来源:力扣(LeetCode)解题思路 剑指书上的方法 1.方法一第一步:复制原始链表上的每个节点N、创…
暂无图片
编程学习 ·

支付宝小程序转微信小程序?

问题概述 支付宝小程序做完后,开始转战微信小程序;网上搜了一下都是都是微信转支付宝,并且还有转换工具(实名羡慕。。),并没有找到支付宝转换微信小程序的前车之鉴。由于拿到的是一半的项目,因此准备将支付宝与微信的区别整理出来,然后在开发者工具或者vscode进行全局替…
暂无图片
编程学习 ·

JAVA学习之路(3) request的总结

文章目录引言Request对请求行数据的操作Request对请求头数据的操作Request对请求头数据的操作通用方式中文乱码问题请求转发 引言 在httpServlet类中,我们只需要调用doGet和doPost方法即可以实现对应的功能。对应这两个方法,有两个穿进去的参数对象,一个是response,一个是r…
暂无图片
编程学习 ·

前端学习-javascript-(1)预览

组成 DOM—Document Object Model 文档对象模型—操作返回到文档(界面) doucument对象 ———————————————— BOM—Browser Object Model 浏览器对象模型—操作浏览器本身 window对象 ———————————————— ECMAScript 解释器 ———————————…
暂无图片
编程学习 ·

json从立地到成佛

文章目录诞生于JavaScript,json的前世今生json含义json诞生搞清json兄弟姐妹,看清区别json VS xml小小翻译官,json的应用前端ajax+json异步传输:跨平台webservice:非关系数据库存储(Nosql)拒绝四不像,json语法有要求json语法规则json名称/值json对象json数组JavaScript对象…
暂无图片
编程学习 ·

C语言求两个数的最大公约数

#include<stdio.h> int main () {int i,j,t;scanf("%d %d",&i,&j);int m;if(i>j)//比较两者大小,让i存储两者较小的数; {t=i; //如果I>J,i j 位置互换 i=j;j=t;}for(m=i;m>0;m--)//因为两数的最大公约数必然是比两数最大的数字小,可能小于…
暂无图片
编程学习 ·

MyBatis中#{}和${}的区别详解 区别

区别1.#将传入的数据都当成一个字符串,会对自动传入的数据加一个双引号。如:order by #user_id#,如果传入的值是111,那么解析成sql时的值为order by "111", 如果传入的值是id,则解析成的sql为order by "id".2.将传入的数据直接显示生成在sql中。如:or…
暂无图片
编程学习 ·

firewalld管理方式

1.firewalld的开启 systemctl stop iptables systemctl disable iptables systemctl mask iptables systemctl unmask firewalld systemctl enable --now firewalld2.关于firewalld的域trusted 接受所有的网络连接home 用于家庭网络,允许接受ssh mdns ipp-client samba-clie…
暂无图片
编程学习 ·

python读取Excel工作簿、工作表

python读取Excel工作簿、工作表 最近需要用python操作Excel表格,因此大概学习了一下如何操作,表较简单但是很实用,这里记录一些简单的操作。 import xlrd # 读取工作簿 wb=xlrd.open_workbook(招生表.xls) # 读取工作簿下所有的工作表 ws=wb.sheets() # 读取工作簿下所有工作…
暂无图片
编程学习 ·

linux监控网卡抓包

/usr/sbin/tcpdump -n -e -i eth0 tcp port 8090tcpdump 的抓包保存到文件的命令参数是-w xxx.cap 抓eth1的包 tcpdump -i eth1 -w /tmp/xxx.cap 抓 192.168.1.123的包 tcpdump -i eth1 host 192.168.1.123 -w /tmp/xxx.cap 抓192.168.1.123的80端口的包 tcpdump -i eth1 host …
暂无图片
编程学习 ·

软件测试(软件测试生命周期,描述一个bug,定义bug级别,bug生命周期,如何开始第一次测试,测试执行和bug管理,测试工作中的人际关系处理)

一、软件测试的生命周期 对比软件的生命周期和bug的生命周期 软件的生命周期:需求分析——计划——设计——编码——测试——运行维护 软件测试的生命周期:需求分析——测试计划——测试设计、测试开发——测试执行——测试评估 bug的生命周期: 软件测试&软件开发生…
暂无图片
编程学习 ·

AJAX

原生AJAX ajax概念:在不进行整个页面的更新的情况下,局部更新界面。 局部刷新技术 ajax 和请求数据有关 它的出现开始前后端分离 ajax出现之前 开发人员前端和后端都做 前后端分工 中间由ajax来对接 ajax就是异步的javascript和xml(树形结构文档 xhml—写法和html写法一…
暂无图片
编程学习 ·

一文教你如何在IDEA上安装scala插件并创建工程

大家好,我是不温卜火,是一名计算机学院大数据专业大二的学生,昵称来源于成语—不温不火,本意是希望自己性情温和。作为一名互联网行业的小白,博主写博客一方面是为了记录自己的学习过程,另一方面是总结自己所犯的错误希望能够帮助到很多和自己一样处于起步阶段的萌新。但…
暂无图片
编程学习 ·

Android动画(五)PropertyValuesHolder和KeyFream使用

今天给大家介绍PropertyValuesHolder和Keyframe,在动画中也是属于比较重要的东西,请大家细品,接下来步入主题概述先看看本篇要实现的效果吧PropertyValuesHolderofInt(),ofFloat()和ofObject()KeyFreamKeyframe.ofObject(); 概述 前几篇给大家介绍了ObjectAnimator的ofInt(),of…