零基础C++(3) 认识变量和输出

Orijinal Video İçeriğiVideoyu Genişlet
  • 大家好,我是封尘,今天我们正式进入CR家基础课的学习。
  • 先介绍一下变量,让我们了解什么是变量及其在编程中的作用。
  • 在CR家中,变量是用来存储数据值的一种实体。

大家好,我是封尘,今天呢,我们正式进入CR家基础课的这样一个学习。

先介绍一下变量。那么我们在编程过程中使用的最多的就是这样一个变量。变量是什么呢?我们先看一下变量的定义。

在CR家中,变量是用来存储数据值的一种实体。每个变量呢都有一个类型,这个类型决定了变量可以存储的数据种类以及变量在内存中所占的空间大小。那么空间大小我们留给后面去讲,我们先记住变量它相当于是一种实体,它存储的是一种数据。

那么变量是分各种类型的。我们先举一个通俗一点的例子。我们家中都会有这种收纳柜或者是收纳箱,收纳柜纯属是我们的物品。物品就相当于数据,收纳柜就相当于这个变量。

不同的柜子有不同的类型,有的可以装内衣,有的装袜子,但是你不能把袜子放到内衣的那里面,对吧,毕竟它的用途不一样。

我们来看,这个袜子呢,我们给它放到这个袜子的收纳柜里,这个收纳柜呢,我们就可以理解成它是一个袜子类型,它存储的是个袜子。内衣收纳柜呢,它是专门收纳内衣的一些杂物的收纳柜,它是收纳一些我们平时用的一些工具,像螺丝刀、铅笔和卷尺之类的。你不能把铅笔卷尺扔到你内衣的收纳柜里,那就很乱了。

所以,一个收纳柜在我们定义好了之后就知道它是什么类型,它存储什么数据,给它开批多大。例如说,你装杂物的这种收纳柜,你可能要大一点,才能装各种各样的杂物;而可能装袜子的收纳柜就小一点,因此这也就对应了这个变量所在内存中的一个大小。

那么这只是一个通俗的理解,接下来我们来看第二个知识,这是一个补充的知识。实际上在计算机中,我们存储的数据都是按照二进制存储的。在计算机组成里,大家如果在大学中学过,知道负数是用补码,正数是用原码来存储的,都是一个二进制。

对于没有学过计算机的也不要紧,这里只是做个理解。我们看一下怎么去理解它:在计算机中,数据是用二进制存储的,一个字节占用了8比特,比特就是位的概念。什么是位呢?

我们现在用的各种电子设备,例如我们的电脑,大家看多少GB、多少KB、多少MB,我们就知道这是一个容量存储的单位。我们先不管它最小的容量的存储单位就是这个,再往上八位构成了一个字节,就这么理解就可以了。

例如说数字2会转化为二进制的这样一个数。计算机想存储2的时候,就存储的是这样一个数值,把这个数值放到计算机为我们分配好的这个存储单元里。那么这个存储单元,它本身还有一个地址,假设这个存储单元的地址为5。

那么转化为二进制就是这个二进制数。大家再一次去理解,这是一种二进制的数字2,我把它存储到这个存储单元里。这个存储单元好比是我们的收纳柜,这个二进制数好比是我们的数据。

我们看上面的各种类型。我们存储单元把它存储好了之后,计算机怎么去访问存储单元中的数据呢?它实际上会通过寻址的方式,也就是说它首先要找到存储单元的地址。

我们每开辟这样一个存储单元,或者是我们每使用计算机自动为我们分配的存储单元,都会有一个这样的地址。当我们取出这个存储单元中的数据的时候,都要先通过这个地址来找。因此我们了解在我们使用任何存储单元的时候,都知道有一个存储单元的地址,相当于门牌号。我们通过这个01这个门牌号找到了这个房间,然后再访问取出这个房间里存储的东西,理解就是这样。

为什么要介绍这样一个概念呢?因为后续我们会讲到指针的概念。在CR家和C语言的课程里,它不同于其他语言,是一个强内存操作语言。所以指针是CR家开发人员一辈子都摆脱不了的一个最重要的利器,当然也会产生很多负面的问题,所以大家在后面可以感受到。

所以说我们再次理解存储单元。我们可以理解成是这样的一个变量,简单一点的去理解可能不是特别严谨,但我们就先把存储单元理解成是这样的一个变量,存储了这样一个01的数据。

那么这个是个数据,这是个变量。我们也知道每一个变量它都会有一个地址。记住这样一个图,大家以后学指针的时候可以对比的去理解。这是做一个铺垫。

变量的声明和初始化:在C++中,首先我们要声明一个变量,然后可选择地去初始化它。声明变量的时候,我们要指定变量的类型和名称。C++是一个静态语言,也是强类型语言,它不同于一些脚本语言,比如Python、JS,Python和JS是不带类型的,或者是不需要声明类型的,但它们可以从解释去推断。

而C++在我们使用一个变量之前需要进行声明,并且指定这个变量的类型。我们看一下,我们声明了一个整形变量age,它未做初始化。int是整形的意思,age是这个变量的名字。那么这么写的话,这个age里默认会存储什么数据呢?

这个age实际上存储的是一个很大的数,或者是一个很小的数,这个取决于编译器,也可能是一个未定义的数,因为我们没有把这个age给它赋值。那么在C++赋值的概念大家可以理解成让这个age里存储一个默认的值。

那么没有让这个age存储默认的值,它在使用的时候会有很大的风险。在实际的开发中,我们遇到了很多在debug环境下不会出问题,但在release环境下通过内存的优化,这种age会有一个未定义的值,会产生很严重的问题。

所以在这里我们看到了这只是做一个声明,A值是int类型,这个A值是变量的名。接下来我们看一下,我们声明并初始化了一个变量height。这个height是int类型,变量名是它的初始值,变成了175,所以以后我们在使用height的时候,它的值就是175。

接下来我们看一下声明这个double,是一种类型叫双精度类型,大家可以理解成我们平时在数学中使用的那种小数,或者是很多位的这样一个小数。这个double就好比是3.145926这种数字,它就是double类型。

接下来,我们进行了一次初始化变量,并声明并初始化一个字符型的这样一个变量。这个char是一个字符类型,变量名是gender,它的值为m。字符类型跟其他不太一样,像我们看到的这是浮点数,这是一个整数。那么字符类型需要两个单引号中间放上我们字符的名字。

我们了解了这样一个变量的声明和初始化之后,我们来看变量的命名规则。在C++中,变量的命名可以包含字母、数字和下滑线,但是记住不能用数字开头。如果以数字开头的话,编译器就会报错误。

C++是大小写敏感的,比如说我们定义了两个变量,一个叫age,一个叫大写的Age,它们其实不是一个变量。

变量的类型:我们看一下C++中支持多种基本的数据类型,那么基本的数据类型是什么意思呢?就是C++为我们初始化定义好的一些类型,比如说int是一个整形,short是一个短整形,shortint差别不大,short存储的空间更小一点。后面会给大家介绍long是长整形,适用于存储很大的数字,比如42亿,可能用int就不太够了,而我们可以用long。

浮点型分别有floatdoublelong double。其中,double是双精度,float是普通的一个浮点型,double的存储范围实际上比float可能会更大一些,回头我们做一下测试。

字符型就是这个char,我们已经理解到,它其实就是占一个字节,一个字节是8位,我们可以理解成X就是占了8位。

大家听到这里,可能每个变量的类型对应的大小,我们可能不是特别理解,没关系,这在下一节给大家介绍变量的对应的存储大小。

布尔类型是表示是与非,也就是真与假。比如说我吃饭了吗?要么就是吃了,要么就是没吃。又或者说今天下雨了,有人说今天下雨了,但今天没有下雨。他说的今天下雨的这句话就是假的,因此bool类型实际上可以理解成truefalse

C++还会有一些复合数据类型,例如结构体类型、联合体类型和class类型。这些是复合数据类型,对于复合数据类型我们在之后详解,如果一下子把这些类型的引入过来,可能会有一些压力的,尽量简单一点。

使用变量:首先我们先包含这个投文件,这个投文件是用来做输入和输出的,先把它包含进来。接下来我们定义了这样一个int类型的返回值main,是一个函数的名字,括号是函数所要携带的参数。不需要携带参数,括号里就什么都不要写,两个花括号表示在这里面我们要写这个函数里面执行的内容。

这一段概念对于初学者来说可能有一些突兀,因此大家只需要理解我想要使用这种输入输出的工具,这种函数是在系统帮我们定义的,我们就要去包含系统提供的投文件。这是一种规矩,大家记住就好。

比如说你想使用我们家的这样一个螺丝刀或者卷尺,你是不是要给我打电话,或者来找我,我把这个工具箱给到你。所以,包含这个投文件的过程就好比是在引用工具箱的这个过程,然后你才能打开这个工具箱里面所提供的工具才能使用。

cout就是用来输出的,它是在这样一个头文件里声明的,所以我们先包含这个头文件才能去使用std::cout进行输出。

继续看这样一个函数体,函数体里面我们初始化了一个变量ab。我们看int a = 5b = 10,这是一个初始化的表达式。当想要在一个初始化的表达式中初始化多个变量的时候,我们可以用逗号。当然,我们不想在一个表达式里初始化多个变量,想要分开初始化,我们可以采用这样一种方式,分别初始化先把a初始化成5,再把b初始化成10,均可。

有的时候为了简洁,我们可以这样写,通过逗号分割在一行里给它初始化好。接下来这是一个运算,运算在后面会介绍。在这里大家先感受一下,a + b 的值赋值给sum。我们知道在做数学题的时候,可能理解经常会这样写:1加1等于2,但我们在做C++编程的时候,这个2好比是sum。我们定义了这样一个sum变量来计算这个1加1的值,a就好比是1,b也好比是1,所以要反过来写。

那么怎么理解这样一句话呢?这样一句话就是说变量a和变量b进行相加,相加肯定会得出一个结果,这个结果再赋值给这个sum,即把这个结果填充到这个sum里。因此,通过等号相当于把这个值给到了这个sum

然后我们看一下输出求和的结果。这里的std::cout,为什么要std::呢?这是一个作用域(scope)。作用域的话,就是说cout虽然包含在这样一个头文件里,但它是处于这样一个作用域中去定义的。

这个在之后也会介绍,大家使用的时候直接照抄就好。学习一个知识最基本的套路:第一点是先去理解,第二点去模仿,第三点去应用。大家先把这一段代码理解了,然后模仿着它去写。

使用这个std::cout作为输出,输出的是一个内容,首先它输出后面可以跟这样一个字符串。接下来可以通过两个箭头衔接这样的一个a,也就是说,字符串后面再拼上这样一个a。大家可以理解成把a输出到这个字符串里面,他们俩进行了拼接。同样的道理又把这个**&输出到这个变量a里,又进行了拼接,b又输出到这个变量&**里,又进行拼接,最终会整个输出这样一句话。

我们来给大家演示一下。通过这样一个函数,我们看,我实际上把它抽离到这个函数里了,我们在main函数里也可以去掉这样一个函数。我们先把这个Hello World去掉,我们看它输出的是The sum of 5 and 10 is 15

我们记一下它这个输出格式。然后我们回到这里,the sum of 5是前面的这一句话,a等于5,所以下面就把a拼到了这个sum后面,就通过这个箭头做这样的拼接。这句话我们再回顾一下,接续进行拼接之后得到的结果就是这个。

大家可以多练习一下,接下来我们看一下输出运算。输出运算是我们刚才说的,通过标准输出流来完成的,叫做std::coutstd是作用域,作用域就好比是一个大的区域,比如说我是在北京的这样一个朝阳区,你是在北京的这样一个昌平区,我们区域不一样,但在这里都有同名的地址,诸如有个7号楼、3号楼、21号院。因此,北京的昌平区也有朝阳区,并且都有同样的地址,通过这个作用域区分。

所以这个cout,我们在以后的编程中可能会用到其他的一些第三方的库里,也会提供这样一个输出工具,可能也叫cout,但是作用域是不一样的,使用的是C++标准的作用域。因此,若我们要用其他的cout,前面就要加其他的这样一个作用域。

std::cout是C++标准库中的一个对象,它代表输出设备,通常是屏幕。为了使用std::cout来输出数据,我们需要包含iostream,因为它是在这里面做声明,并且它的头文件在cpp里做定义。如果初学者对上面部分觉得生疏,可以先将其背下来。

下面是一个简单的C++示例,咱们看一下是如何使用std::cout进行输出文本和数字的。首先,我们输出字符串,std::cout直接跟这样一个字符串进行输出。我们输出数字,直接std::cout输出这样一个数字。

接下来,我们输出浮点数,std::cout输出这样一个浮点数。这个浮点数跟这样一个字符串进行了拼接。然后我们输出字符,输出字符之后我们先初始化了这样一个字符给到这样一个chch里存储的就是a

大家还记得赋值吗,这个等号在编程里我们就不叫做等号了。你不能说x = ch,可以这么说x ch,然后赋值符号后面接上去ch变量。

接下来,我们进行了这样一个输出ch。之后,我们想要输出一个布尔类型的值,因为我们看一下这是布尔类型的变量,而这是变量名后面是一个数值。布尔类型只能存储truefalse。当然,想要在这里存储1也是可以的,存储一个-1也可以。

那么-1和1其实都是true。为什么在C++里,这样设计呢?只要是非0的数都是true;等于0时它就是false。所以这里为了防止混淆,C++做了提升,允许大家使用一些数字,但尽可能地使用truefalse去标识它是一个Bool类型的变量。

我们可以先把这个std::cout里面先给它写入这样一个值,大家可以理解成这个箭头是把后面的值写入到这个cout里,也就是说把一个配置让它生效。

这样我们就启动了truefalse的输出。接下来输出的就是一个true类型。如果不用它,我们知道它等于true。默认情况下,如果输出的值是1。如果是false,默认情况下输出便是0。

因为在C++里,如果数值跟false做转换,默认值就是一个0。这部分内容我们在后期章节中也会介绍。

大家听不太懂可以等后面的讲解。我们把这个输出再给它打开。如果说我们这个布尔类型,我们给它复制成-1。我说过只要不是0的数复制给这样一个bool类型的变量,那么这个变量是true;若被复制成0了,它才是false

我们看一下这次输出的结果,看看它是false。这个大家做个理解就好,bool类型以后会常用。然后C++开启truefalse的输出大家做理解就可以了,初学者无需去深究理解。

接下来,C++还支持一些格式化的输出,这里通常涉及到更复杂的语法。在iomanip的这样一个投文件中,我们定义了一些操作服务,例如说setw是设置我们输出的数据的宽度,setprecision是设计这样一个输出的精度。

比如说,我们经常会输出3.14,如果我们把它宽度设置为2,那么它会补一个空位,然后精度为这个2,就会输出1.4。如果精度为3就是3.14。

我们可以用C++20引入一些新特性,例如一些格式化的输出,它可以把输出运算符做了拼接,把整个拼接成的字符串输出到这个流里,写入到这个流里。当然,后期我们可以在C++20中使用std::format格式化输出一个我们所希望的特定形式的字符串。

这部分引入的其实是比较晚的,大家可以练习在评论区去练习一下,定义一个变量π,初始化一个变量为3.14。再初始化一个变量int类型,设置变量值为5,然后分别输出这两个变量的值。最后初始化一个bool类型的数值为-10,打印这个布尔变量的值,看看是true还是false

这一简单的内容其实比较简单,就到这里。我会把文档贴在视频的下方,大家可以去理解一下。