C++感受6-Hello World 交互版

news/2024/5/9 22:55:58
  • 变量、常量
  • 输入、输出、流
  • getline() 函数读入整行输入
  • Hello() 函数复习
  • 新定义函数 Input() 实现友好的人机交互
  • 还有 “痘痘” 为什么挤不到的分析……

 

1. DRY 原则简介

上一节课,我们写了两版“问候”程序。第一版的最大问题是重复的内容比较多,每一次问候都在重复从 cout 到 endl 的代码,中间只有人名不同。

刚学编程的人可能会说:“代码重复怕什么啊?在电脑里 复制、 粘贴 文本非常快啊!”

问题不在于写代码是快还是慢,而在于重复的代码,难以修改、难以维护。

重复的代码,它们的背后的业务逻辑往往是相同或者高度相似的。如果有一天,这个业务逻辑发生改变,就会造成代码中所有重复的地方都要修改。我们现在的代码才几行而已,如果有一天q有上千,上万行代码,我们很可能都无法找出所有重复的地方,一个个修改过去也极大可能引发新的错误。

“不要到处写重复的代码”,这已经成为专门一条行业内的编码规矩,称为 “DRY”原则,也就是 “Dont’t repeat yourself”,不要重复你自己。

2. 新情景、新需求

第二版的问候程序,有很大的进步。因为我们把重复的,问候操作,写成一个函数,叫Hello(),多次调用。这样一来,将来,如果问候操作,需要变化,我们也只需要修改这个Hello()函数即可。

// 我的第一个函数
void Hello(std::string_view XXX)
{std::cout << "你好," << XXX << "!" << std::endl;
}

 这一节课,我们要为问候业务,提出新的场景需求:模拟在上班路上,碰到谁,就问候谁的过程。

碰上谁,就问候谁……那我们能事先知道每一天上班会碰到谁吗?当然无法预知。这样一看,现有的这第二版问候程序就显得非常“死板”了。每一次运行这个程序,都是先问候志玲,再问候幂幂,再问候冰冰……无论运行多少次,它的问候过程都是一成不变的。

这就说到了“变”!我们需要可以变的姓名;这就引出这节谭,们要学习第一个重要的知识点:变量。

3. 认识变量和常量

程序中的数据,可以按可变和不可变区分,分成两大类:常量和变量。

3.1 常量

常量,就是在程序运行之后,无法修改,或禁止修改它的“量”的数据。

这里的“量”,更通俗易懂的说法是一个数据的“值”,或者说,一块内存里存放的内容。

我们以后会重点讲解常量。不过,大家要在今天记住这两个描述:“无能力修改” 和 “禁止修改”。

来举一个“恶俗”,但绝对管用的例子吧——

假设你是一个非常喜欢挤别人痘痘的人。然后,有个女生说她后背某个地方长了一颗很大的痘痘,可是她不告诉你这颗痘痘的位置。请问,你能挤掉一颗你看不见,摸不着的痘痘吗?当然不能,这就叫“无能力修改”。

另外一种情况,这颗痘痘就长在女生鼻头上,你看得见,摸得着,但是你能伸手就挤掉它吗?也不能,因为人家女生不允许你动它。

这就是将来我们会学习到的,最常见的两种类型的常量:一种是代码在客观上没有能力修改的数据,一种在语法上明确标明不让修改的数据。上一课第一版代码中的名字字符串,就是第一种,叫“字面常量”。它就像我们白纸黑字签下的字,一旦写下,就涂改不了。

3.2 变量

初中学习的代数,当一个数据我们暂时不知道它会是什么值时,我们可以用个字母,比如 x、y、z,来暂时先代表这个数据。在程序中,一个数据,我们暂时不知道它会是什么值;或者,知道它一开始的值,但这个值会随着程序的运行而不断变化,这情况下,我们也可以用一个字母,或者更好的,用一个单词来表达它,表达这个会变化的数据。

今天,我们不知道什么?答,我们不知道每一天上班路上会先遇到谁,后遇到谁。所以,就让我们写的C++程序,定义第一个真正意义上的变量,取名为 “” 吧!

你当然也可以使用 X 来表达,这样显得更加有科技感和神秘感。但是,我觉得用名字是“谁”这个变量,来表达程序中可能遇到谁谁谁谁……想一想是不是也挺直观的?

没错,这也是我们今天学习到又一个重要的知识点:变量的名字一定要能直观地表达它的作用

来看一些常量与变量使用对比的例子——

  • “我的体重是 60 公斤”:人的体重很少一成不变,所以我们得用变量表达它,这个变量的名字可以叫 weight。

  • “我的身高 175 厘米……”:也一样,从小到大再到老,身高也会变化,这个变量可以叫 height。

3.3 变量常见使用过程

结合用变量表达待问候的人名的例子,我们来看看变量最常见的使用过程。

(1)定义变量

要使用变量,首先需要定义变量。C++定义变量时,需要给出变量名字,还需要直接或间接给出变量的类型。今天我们学习其中的“直接”方式:

变量类型 变量名字;

即:先写下变量的类型,再写下它的名字,然后用分号结束,这是定义变量的一种常见语法。

在我们的例子,变量名是,它实际是要表达人的名字,所以它的类型应该是字符串。在 C++ 的标准库中,有一个叫 string 的类型,用来表达字符串。

std::string 谁;  // 定义了一个变量,名字叫谁,类型是 std::string

大家还记得前面课堂学习到的名字空间的知识点吧?特别是这个 std:: 的写法,你应该很熟悉了。

这样定义的变量谁,一开始时,它并不持任何字符内容(或者说,它持有一个空的字符串)。

2)修改变量的值

有了一个变量,接下来,就可以修改它的“量”了,也就是为它赋值。你可能猜到了,赋值操作在C++中,就是日常的 “=” 操作符(等号)。

下面演示了赋值 “张三” 给 的代码:

谁 = "张三";  // 修改这个变量的值 (量、内存)

(3)使用变量

变量很方便用来传递一个值,比如,我们可以把 谁 作为之前我们写的 Hello() 函数的入参,以实现将 谁 的当前值(第2步中的 “张三”)传递给 Hello() 函数的入参(还记得吗,这个入参是一个“偷窥狂”,哦不是,是“观察者”)……

Hello(谁);  // 将谁的当前值,传递给 Hello() 函数入参,再于函数内部输出其值

(4)再改,再用

变量变量,比孙悟空还善变,悟空才能连续72变,我们的变量可以无穷尽地变下去……

谁 = "李天王";
Hello(谁);谁 = "孙悟空";
Hello(谁);// ...

3.4 变量使用完整示例代码

#include <iostream>
#include <string>
#include <string_view>void Hello(std::string_view XXX)
{std::cout << "你好," << XXX << "!" << std::endl;
}int main()
{std::string 谁; 谁 = "志玲";Hello(谁);谁 = "幂幂";Hello(谁);谁 = "冰冰";Hello(谁);谁 = "热巴";Hello(谁);谁 = "真木阳子";Hello(谁);谁 = "井川遥";Hello(谁);谁 = "Lily Collins";Hello(谁);
}

问题来了:这个使用变量的版本,感觉写起来,比之前的常量版本还啰嗦呀?

4. 人机交互!

4.1 认识 getline()

尽管用了变量,但这个版本每次运行起来,输出结果还是一成不变;甚至写起来比常量的那个版本,还要麻烦、还啰嗦,并且,没有引入什么新功能呀?!

我们准备这样来模拟每天上班路上遇到谁问候谁的过程:我们让用户(其实,就是我们自己),在程序运行时,通过键盘输入一个姓名,输入谁,就表示我们遇到谁。

我们要输入的是一个姓名,一个字符串。并且,如果是外国人的话,那么他们的姓名中间可能包含空格。C++标准库提供了一个 getline() 的函数,特别适合于读入整行的字符串,包括中间的空格。

getline() 有两个入参。第一个入参指定输入流。什么叫“输入流”?

【输入、输出】:首先来理解什么叫“输入”:往程序里“塞”数据,就叫“输入”。大家顺便可以理解一下什么叫 “输出”,程序往外“吐”数据,就叫输出,也就是,编程时讲的输入和输出,是以程序为中心来理解的。

【流】:那什么叫流:水流、电流,都是流。流就是在同一个方向上的排着队的一大堆数据。比如,“车流”就是:同一个行驶方向上,有很多车一辆接一辆地往前走。

本站深入讲解,包含多个实践项目的 C++“流”的高级课程:
《C++“流”编程视频辅导》课程 建议及时加深学习

我们现在写的程序,暂时只能使用键盘往程序里输入数据,一阵“噼噼啪啪”敲键盘,就可以往程序里输入一大串字符,因此它满足“输入流”的概念的三个要素:

  • 同一个方向:键盘到主机
  • 支持连续:噼噼啪啪快速输入,一个字符都不会丢
  • 支持排队(即有序):无论你击键有多少,都不可能出现先输入字符的后到,后输入的字符先到的乱序情况

所以,C++标准库就把键盘输入,包装成一个 标准字符输入流,并且预先定义成一个变量。

如果是我写的标准库,那这个变量的名字肯定得叫 噼噼啪啪,可惜不是。
这个预先定义的,代表标准输入流,或者说,绝大多数情况下,代表键盘的变量,它的真正的名字叫 cin。c指字符,in 指输入 。加上标准库名字空间直接限定,就是 std::cin。

getline() 函数的第二个入参,在本例中,我们给的是我们自己定义的字符串变量,也就是

当程序这样写时:

getline(std::cin, 谁); 

执行该句代码并完成 getline() 的调用之后,变量的值,就是用户从键盘上输入的一行文本。输入一行文本,是指用户输入一些普通字符内容(包括汉字内容)之后,非常潇洒的拍下键盘上的回车键。getline()开始从行首一直读到行尾,不含回车换行

如果用户在此期间就是不碰键盘,那程序就会“卡”在这一行一动不动。

4.2 问候程序的人机交互第一版

#include <iostream>
#include <string_view>
#include <string>void Hello(std::string_view XXX)
{std::cout << "你好," << XXX << "!" << std::endl;
}int main()
{std::string 谁; std::getline(std::cin, 谁);Hello(谁);std::getline(std::cin, 谁);Hello(谁);
}

为了不浪费版面,暂时就只支持上班路上遇到两个吧!后面的遇到的,管他是大老板还是小保安,管她是不是你暗恋的办公室女神,咱们就全都假装没看到。

5. 是时候看视频了……

ffls09-HelloWorld-交互版

6. 最终版本代码

将 “遇见” 的过程,也封装成一个函数:Input(),该函数返回用户输入的姓名,并且提供了更好的人机交互界面。

#include <iostream>
#include <string_view>
#include <string>// 负责问候(输出)
void Hello(std::string_view XXX)
{std::cout << "你好," << XXX << "!" << std::endl;
}// 负责遇见(输入)
std::string Input()
{std::cout << "遇见谁了?请输入他的名字:";std::string name;std::getline(std::cin, name);return name;
}int main()
{std::string 谁; 谁 = Input(); // 遇见谁Hello(谁);  // 问候谁谁 = Input(); // 纵不遇见你Hello(谁);   // 也想问候你
}

「本课终」


http://www.mrgr.cn/p/56770044

相关文章

以链表为基础实现链式队列——————遍历、入队、出队

以链表为基础实现链式队列 ​ 如果打算以链表作为基础来实现队列的操作,可以避免内存浪费以及避免内存成片移动,只需要确定队头和队尾即可,一般把链表头部作为队头,可以实现头删,把链表尾部作为队尾,可以实现尾插。​ 需要注意的点:遍历队列需要备份地址 出队需要考虑空…

Windows设置开机自启动项

一、常见软件的开机自启设置大部分安装的软件,在设置中都带有“设置开机自启”的选项,直接在软件本身的设置中勾选相应开关项即可。 二、本身无开机自启的软件或一些绿色便携式的软件 (一)实现原理Windows自带了一个启动文件夹,在此文件夹中的软件都会在开机后进行启动操作…

个人音乐播放网站项目(SpringBoot+Linux部署上线)

在做完第一个博客系统项目以后&#xff0c;接着做下一个项目&#xff1a;音乐播放网站项目&#xff0c;此项目应用的技术栈和第一个项目是差不多的&#xff0c;即算是学完SSM等知识以后的两个入门级Java开发项目吧。 此项目包含的核心功能有&#xff1a; 一、登录、注册、退出…

李彦宏:程序员将不复存在! 周鸿祎回怼!网友:先把百度程序员都开除了!

近日&#xff0c;百度创始人、董事长兼首席执行官李彦宏在央视《对话》•开年说的访谈中指出&#xff1a;“基本上说以后其实不会存在“程序员”这种职业了&#xff0c;因为只要会说话&#xff0c;人人都会具备程序员的能力”。 “未来的编程语言只会剩下两种&#xff0c;一种…

Unsortbin attack原理及分析

Unsortbin attack原理 ✔️条件:首先要实现Unsortbin attack前提是可以控制Unsortbin attack chunk的bk指针 ✔️目的:我们可以实现修改任意地址为一个比较大的值 ✔️原理:1.Unsortbin的来源 1.当一个较大的 chunk 被分割成两半后,如果剩下的部分大于MINSIZE,就会被放到 …

flutter release 报错 Error: SocketException: Failed host lookup:

flutter 的 debug 模式没有任何问题 &#xff0c;打了release 包后一直报下面的错&#xff0c;查了一下是 因为没有网络权限 Error: SocketException: Failed host lookup: yomi-test-aws-sg.yomigame.games (OS Error: No address associated with hostname, errno 7) 按照下…

新手Pytorch入门笔记-transforms.Compose()

我使用的图片是上图&#xff0c;直接下载即可 transforms.Compose 是PyTorch中的一个实用工具&#xff0c;用于创建一个包含多个数据变换操作的变换对象。这些变换操作通常用于数据预处理&#xff0c;例如图像数据的缩放、裁剪、旋转等。使用transforms.Compose 可以将多个数据…

ClickHouse 高可用之副本

文章目录 ClickHouse 副本支持副本的引擎配置高可用副本副本应用1.副本表概述2.创建副本表3.写入模拟数据4.副本验证 扩展 —— 在 Zookeeper 中查看副本表信息 ClickHouse 副本 ClickHouse 通过副本机制&#xff0c;可以将数据拷贝存储在不同的节点上。这样&#xff0c;如果一…

运行django

确保app被注册 urls.py中编写url 视图对应关系 命令行启动 python manage.py runserver

iOS - 多线程-GCD-队列组

文章目录 iOS - 多线程-GCD-队列组1. 队列组1.1 基本使用步骤 iOS - 多线程-GCD-队列组 开发过程中&#xff0c;有时候想实现这样的效果 多个任务并发执行所有任务执行完成后&#xff0c;进行下一步处理&#xff08;比如回到主线程刷新UI&#xff09; 1. 队列组 可以使用GC…

npm run dev, serve和build的区别

真实命令分别为npm run vite,npm run vite build,npm run vite preview ctrl+c结束运行的npm项目

算法06链表

算法06链表 一、链表概述1.1概述1.2链表的组成部分&#xff1a;1.3链表的优缺点&#xff1a; 二、链表典例力扣707.设计链表难点分析&#xff1a;&#xff08;1&#xff09;MyLinkedList成员变量的确定&#xff1a;&#xff08;2&#xff09;初始化自定义链表&#xff1a;&…

OpenHarmony语言基础类库【@ohos.util.LinkedList (线性容器LinkedList)】

LinkedList底层通过双向链表实现&#xff0c;双向链表的每个节点都包含对前一个元素和后一个元素的引用。当需要查询元素时&#xff0c;可以从头遍历&#xff0c;也可以从尾部遍历&#xff0c;插入、删除效率高&#xff0c;查询效率低。LinkedList允许元素为null。 LinkedList…

谷歌 hackbar 不能使用的问题

谷歌 hackbar 不能使用的问题 下载 hackbar 插件:https://github.com/Mr-xn/hackbar2.1.3 解压文件,将其拖入 chrome 扩展程序中点击详情,点击下面来源的链接 会跳转到插件的安装位置,进入theme/js文件,打开hackbar-panel.js文件,将以下三处disable_hackbar()函数替换成i…

数据结构_链表_双向循环链表的初始化、插入、删除、修改、查询打印(基于C语言实现)

通过C语言实现双向循环链表的相关功能, 并通过了Linux平台测试, 注释完整.版本:2024年4月26日 V1.0 发布于博客园/*** @file name : DoubleLinkedList.c* @brief : 实现双向循环链表的相关功能* @author :RISE_AND_GRIND@163.com* @date :2024/04/26* @version :…

【后端】python与django的开发环境搭建指南

安装Git 双击Git 客户端安装文件&#xff0c;在安装页面&#xff0c;单击“Next” 在安装路径选择页面&#xff0c;保持默认&#xff0c;单击“Next” 在功能组件选择页面&#xff0c;保持默认&#xff0c;单击“Next” 在开始菜单文件夹设置页面&#xff0c;保持默认&am…

什么是用户体验(UX)文案,为什么它很重要?

网上购物如今比以往任何时候都更加相关。所以我们将以此为例说明什么是用户体验&#xff08;UX&#xff09;文案&#xff0c;以及为什么它很重要。 假设你去了一个在线商店。你需要执行一系列操作&#xff1a; 找到合适的部分选择你感兴趣的产品弄清楚它们是什么&#xff0c;…

forward 函数在深度神经网络程序中确实用于表示程序逻辑,特别是网络的前向传播过程。它描述了输入数据如何通过网络的每一层,并最终得到输出预测值的流程

在深度神经网络&#xff08;例如卷积神经网络&#xff0c;CNN&#xff09;的程序中&#xff0c;forward 函数通常用于描述网络的前向传播&#xff08;forward pass&#xff09;过程。前向传播是神经网络的核心操作之一&#xff0c;它指的是输入数据通过网络的每一层&#xff0c…

【论文解读】QUEST: Query Stream for Practical Cooperative Perception

QUEST 摘要引言QUERY COOPERATION PARADIGMQUEST FRAMEWORKA. Overall ArchitectureB. Cross-agent Query Interaction 实验结论 摘要 合作感知通过提供额外的视点和扩展感知领域&#xff0c;可以有效地提高个体感知性能。现有的合作模式要么是可解释的(结果合作)&#xff0c;…

猿人学内部练习平台第11题

第11题:人均会解jsl 控制台抓包可以看到,页面请求了两次 https://www.python-spider.com/challenge/11 第一次返回了一段js代码,第二次返回了所需数据:对比两次请求参数发现,只有cookie中的__jsl_clearance发生了变化,其他参数均相同,因此该值应该是第一次返回的js生成…