我开发了一个基于 Beancount 的账本托管服务 HostedBeans,欢迎大家来了解纯文本复式记账并试用我的服务。
标签 #C++讲稿

C++ 讲稿 6.循环语句A

By 精英王子

CC-BY-NC-SA(署名-非商业性使用-以相同方式共享) 3.0

注:解说在图片下方

原始幻灯片(持续更新):https://docs.google.com/presentation/d/1nv8Vc_ychYkVzamL69aanRL33lYgyAydju8i0Ip85Mg/edit

解说写在讲者备注

1

有时我们需要不断执行某个操作一定的次数,或者执行某个操作直到某种情况出现。

这时就用到了循环语句。

2

这是一个简单的for语句,在C++中for语句用来进行循环。
循环即按照某些条件,执行相同的代码,但代码中变量的值可能不同,所以可能每次循环都会呈现出不同的结果。

循环必须有终止条件,否则就成了死循环(当然,死循环在某些情况下是故意设计的),所以在每一次循环的时候都要更新一些变量的值,并判断是否达到了终止的条件。

初始化表达式(语句)会在循环开始前执行一次,通常用来定义与循环有关的变量,并赋初值。

条件表达式即用于判断是否循环,当条件表达式为真时,循环会继续进行,每次循环开始前都会重新对条件表达式进行判断。

更新表达式用于更新循环中的变量,使之可以在一定次数的循环后达到终止条件,更新表达式会在每次循环之后执行。

在这里,我在初始化表达式里面定义了一个变量i,并将它的值设置为0.

条件表达式是i<10,即只有i小于10时才继续循环。

更新表达式是i++. 它的作用是每次循环后把i加一,这个我们稍后介绍。

如此一来,循环中的语句便可以执行十次,十次后将等于10, 不满足条件i<10, 循环将结束。

3

如果用流程图表示前面那个程序,将会是这样。

4

自增、自减运算符。如i++,i&#8211;,是i=i+1,i=i-1的简写形式。

前缀和后缀的区别就是,前缀形式先将变量的值作为整个表达式的值,再对变量进行自增、自减运算。

后缀形式先对变量进行自增、自减运算,再将这个变量的值作为整个表达式的值。

自增、自减运算符只能用于变量,不能用于字面值。比如1++,因为1=1+1这样的表达式是错误的。

5

之前我们不止一次提到表达式和语句的概念,现在我们来讨论一下什么是表达式,什么是语句。

一般来讲,表达式由值和运算符组成,值是一个很宽的概念,可以是表达式、字面值、变量、函数返回值等。

运算符就是上节课我们提到的那些运算符,以及这节课新学到的自增/自减运算符,当然,还有很多运算符我们没有学习。

单个的值(单个的字面值、变量)也是表达式。

说了这么多,表达式的特点就是,所有表达式都具有一个值。

6

语句是特殊的语法结构,比如之前学到过的for、if、return、switch、变量定义语句等等。

所有表达式加上一个分号,就可以成为一个语句,功能是对这个表达式进行求值。求值是计算表达式的值的过程,如果表达式中含有具有副作用的运算符(如自增运算符),就会在求值时体现出副作用。

对于1这样一个字面值,加上一个分号可以成为一个语句,功能是对1进行求值,结果还是1,而且结果没有被储存到任何地方。这个语句对整个程序完全没有任何影响(通常会被编译器优化功能删除掉),我们称这个表达式没有副作用。

反之,a=b+c这个表达式在求值过程中(没错,记住赋值号也是一个普通的运算符),会把b+c的结果赋值给a,求值前后a的值发生了变化,我们称这个表达式有副作用

但反之不成立,语句去掉分号不一定能成为表达式。

if、for等结构被视为一条语句,虽然其中可能包含多条语句。

回到之前的for语句,你是否发现,被标注为“初始化表达式”的地方被写了一个语句——int i=0; 一个变量定义语句。

这是一个例外,C++规定for的初始化表达式可以是变量定义语句,定义的变量仅在这个for结构之内有效。

7

因为现在学习的内容越来越复杂,我会随时穿插习题。

8

再来看一个例子,它的功能是计算1+2+3+4+5+6+7+8+9+10的和。

首先我们定义了一个变量sum,用来储存它们的和。之前我们都在使用单个字母做变量的名字,这是因为那些变量实在没什么意义,起不出什么好名字。

大家应该尽可能使用有意义的英文单词作为变量名以增加代码的可读性,sum是和的意思。

初始化表达式中我将i(index)的初值设置为了1,因为我们要从1开始相加;条件表达式是i<=10,因为我们要计算10和10以下的整数的和,更新表达式依旧是i++.

sum+=i;的意思是sum=sum+i;即把sum和i相加,赋值给sum. 这句话会循环执行十次,每次i的值都是不同的,分别是1、2、3、4&#8230;&#8230;10.

这样每次循环都将i加到sum上,循环结束时,sum中的数就是我们要的结果了。

最后输出sum.

9

这个就很好理解了,不再详细讲解。

组合赋值运算符除了列出的五个还有一些。它们的优先级和赋值运算符相同,结合性也相同(向右结合)

10

逗号运算符连接两个表达式,(从左到右)逐个计算表达式的值,并将最后一个表达式的值作为整个表达式的值。

利用逗号运算符我们可以在一个语句(表达式)中完成多个表达式的求值。

比如for的条件表达式,只能提供一个表达式,但我们可以通过逗号运算符,将两个表达式连接成为一个表达式,作为for的条件表达式。

看下面的例子,将逐个计算a=1、b=2,c=3,并将c=3(即3)作为整个表达式的值,所以d=3.

值得注意的是逗号表达式的优先级非常低,几乎是优先级最低的运算符,在很多情况下,我们都需要加括号。

并非C++代码中所有的逗号都是逗号运算符,比如变量定义语句中的逗号,是变量定义语句中固有的结构,不是逗号运算符。

之前我也强调过,在C++中同一个符号,在不同的上下文,具有不同的含义。

11

while是C++中另一种循环语句,以while关键字开始,后面括号里直接就是条件表达式,满足这个条件,就会继续循环。

如果用while语句改写上面的程序,将会是这样。

将初始化语句移至循环开始之前,将更新表达式放入循环体。

12

通过之前的例子,我们可以得出这样一种大致的等价关系。

它们都可以用来进行循环,功能上没有区别,只是表达形式上有区别。

通常for用来进行已知循环次数的循环,而while用来进行需要达到某种条件的循环。

13

14

循环还没讲完,下节课接着讲。

C++ 讲稿 5.条件语句

By 精英王子

CC-BY-NC-SA(署名-非商业性使用-以相同方式共享) 3.0

注:解说在图片下方

原始幻灯片(持续更新):https://docs.google.com/presentation/d/1yA9HuxRrAQJNyucXv2EvosYreR5YxfXmeY3MxqhTQbo/edit

解说写在讲者备注

1

在此之前,我们编写的程序都像是一条直线,一句一句从头执行到位。

这节课我们会介绍条件语句,它可以令你的程序根据不同的输入,选择不同的分支来执行。进而获得不同的结果。

2

关系运算就是比较两个值的大小,或者两个值是否相等。

值得注意的是等于用两个等号表示,因为一个等号是赋值号,这点很容易被忘记。

关系运算的结果是bool类型,即是(true)/否(false).

需要明确这个概念:关系运算是一种普通的运算,和加减法无异,只不过这种运算通过比较来实现。

看右面最后一句,关系运算符的左右,可以是(字面值) ,也可以是表达式,或者变量,甚至函数的返回值。

3

逻辑运算是对bool类型的运算,即对是/否的运算,原理与数学中的逻辑联结词、物理中的逻辑电路相通。

通常逻辑运算用来对关系运算的结果进行加工,对关系运算的结果进行取反(最后一句),或者连接(第四句、第五句)。

C++中的逻辑运算符存在一种“短路效应”.

如右面被标红的那句,||的左面已经为true, 无论右面是何值,结果都将是ture, 所以C++在能够确定整个式子的结果的时候,会跳过右半部分的计算。

在&&运算时也存在类似情况,若左面的值为false,那么无论右面为何值,整个式子都是false, C++会跳过右半部分的计算。

这种短路效应在这个例子中无关紧要,当右半部分是一个(有副作用的表达式,如)函数时,短路效应将导致右半部分不会被计算(函数不会被调用).

4

不做过多解释,参见数学、物理书

5

这是一个简单的if语句的例子。
if语句的功能是根据一定的条件,决定是否要执行一段代码。

if后面跟着一个括号,括号中是一个bool类型的表达式,这个表达式的值决定了if是否执行接下来的代码。

我们之前介绍过,在C++中,花括号表示一个整体。在这里,这对花括号中的语句,就是当括号中的表达式为真时,if要执行的代码。

花括号中可以有任意行代码、一行、多行、没有,都可以。

当花括号中只有一行代码的时候,花括号可以省略。

按照通常的习惯,为了阅读方便,每个花括号中的代码都会向右缩进(比如4个空格), 在编辑器中按Tab可以缩进。

如果我输入了一个负数5, 表达式a<=0的值将会是true, 将会执行if中的代码,输出一行文字。

而如果我输入了一个正数3, 表达式a<=0的值将会是false, 会跳过if中的代码,不会有文字输出。

if是C++的关键字。

6

if else语句是对if语句的扩展,在if的语句块后面可以加上一个else, 并再附加一个语句块,这个语句块会在if语句的条件不成立的时候被执行。

同样,如果语句块(花括号)中只有一行,那么花括号是可以省略的,就像幻灯片上面那样。

if else语句中,无论括号中的表达式是真是假,都会有一个语句块被执行。当表达式为真时,if后的语句块被执行,为假时,else后的语句块被执行。

else也是C++中的关键字。

7

有些人在面对复杂的逻辑流程的时候,喜欢画流程图来帮助理解。

其实流程图可以看作是草稿一样,以比代码更清晰的方式来展现整个程序的逻辑。

而有的人并不喜欢流程图,他们觉得代码比流程图更容易理解。

8

else if 这看起来是一种新的语法,但其实不是,只不过将多个if else组合到了一起,并省略了花括号。

if会与离自己最近的else结合,形成一个if else语句。同时,整个if else语句,被认为是一个语句,单独包含在花括号中时可以省略花括号。

9

?:运算符可以认为是if else语句的简写形式,可以在一行内写完。

不要奇怪,它也是一个运算符,和加号减号一样,只不过它需要三个操作数。

10

但凡你学过一点数学,你应该知道4 + 3 * 2在数学中结果是10, 很高兴地告诉你,在C++里面也一样。

但是为什么是5呢?换成其他运算符又会怎样呢?

决定计算顺序的指标有两个:运算符的优先级,和运算符的结合性。

同时你可以任意添加括号,来改变计算顺序。

11

C++的运算符分为一元、二元、三元运算符,前面的数字代表运算符有几个操作数。

例如负号,它只需要一个操作数,所以叫一元运算符。

而加号需要两个操作数,所以叫二元运算符。

这个表中仅列出了我们学过的运算符,还有很多运算符我们没学过。

记不住优先级怎么办?加括号!

12

因为空间有限,我在一行中写了多个语句,这在C++中是允许的。

switch同样提供了分支的功能,它针对一个表达式可能是多个值之一的情况。

如在这里,月份只可能是1-12中的一个数。

switch后是一个括号,里面是要判断的表达式。再之后是一个大括号。

大括号中有若干个case关键字,后面跟着一个值和一个冒号。

当a的值和任意一个case后的值相等时,程序就会跳到此处执行。

(值得注意)默认情况下,程序会一直执行下去,会跨越多个case, 除非你手动用break语句退出switch.

如果要判断的表达式不和任何一个case匹配,就会执行default后的代码。

switch, case ,break, default都是C++的关键字。

13

14

如果要在屏幕上打印十次同一个字符串,除了把输出语句复制十次还有其他方法么?

C++ 讲稿 4.处理数据

By 精英王子

CC-BY-NC-SA(署名-非商业性使用-以相同方式共享) 3.0

注:解说在图片下方

原始幻灯片(持续更新):https://docs.google.com/presentation/d/1kcyy3IevzXQI5Ce0n60ERZmPfbPywErbCSkdazBkGXg/edit

解说写在讲者备注

1

可以说数据就是编程的核心,任何一个程序无非都是接收一些数据,通过加工,再输出一些数据。

这里的数据可以是文字、数字、图像、声音等等。

在第二节Hello World中我们已经见到了如何定义变量,如何利用变量进行简单的运算,这节课我们会详细了解如何使用变量。

2

变量用于储存数据。

这是一条定义变量的语句,就好像为变量申请到了储存的空间,供以后储存数据使用。

double是数据类型,数据类型必须是之前已经定义过的,double在这里表示浮点数,稍后我们会介绍更多的数据类型。

a是变量的名字,这是由你决定的,当然,给变量命名也有一些规则,稍后介绍。在之后的代码中,你就可以用a这个名字来表示这个变量了。

最后是一个分号,在C++中不光是定义变量的语句,所有语句都要以分号来结尾。

3

double a,b; 像这样可以同时定义两个变量,它们的类型都是double,名字分别是a和b.

这和下面两句,分别定义a和b是完全等价的。

还记得以两个斜杠开头的那一行么,那是注释,编译器会无视它。

double a=1.23;还可以像这样,在定义变量的同时,给他一个初始的值。

(在这个例子中,其他情况存在例外)这和下面两行是等价的。

等号在这里是“赋值号”,用来把右边的值复制到左面的变量中。

4

在给变量命名的时候,我们需要遵守一些规则。

这里的不推荐是C++标准规定的,以下划线开头的变量可能被编译器保留用于特殊用途。

C++的关键字就是在C++中有特殊意义的词,它们是语法的一部分,不用用来做变量名,但是可以是变量名的一部分(如print).

要尽量选择有意义的单词,以便于阅读代码。

5

C++的每个变量都有一个类型,变量的类型决定了它能储存何种数据、进行何种运算,一个变量的类型一旦确定就不能更改。

C++中表示整数的数据类型有4种,他们的区别只是长度。short表示稍短一点的整数,int表示最适合CPU计算的长度的整数,long是稍长一点(其实在Windows XP/7上他们和int一样长),long long则更长。

幻灯片上列出的是他们在GCC、Windows XP/7上的具体长度,其他操作系统、编译器可能不同。C++没有明确规定某个数据类型的长度,这样保证了它能够运行在任何平台上,如手机、计算器等等。

在这些数据类型名称的前面加上unsigned,即表示无符号。比如int是区分正负的,可以储存负数,而unsigned int则是不区分符号的,只能储存正数。

因为少了一位用来表示符号的位,所以无符号类型要比有符号类型能表示的数的范围大一倍。

通过上节课的知识,我们可以算出各个数据类型可以表示的数字的范围,例如short是16bit,可以表示65536个数,因为short是区分符号的,所以可以表示-32768到32767. 而unsigned short则可以表示0-65535.

这里的short、int、long、unsigned都是C++的关键字,你不能用它们作为变量名。

6

就像一个轮子一样,如果超出了它能够储存的最大值,就会从头开始。

这种现象叫溢出,在C++中,溢出是不会有警告的,需要自己注意。

7

浮点数有三种,同样,区别仅仅是长度。同样,不同平台具体的长度可能不同,以上是GCC在Windows XP/7的长度。

浮点数永远区分正负,没有对应的无符号版本,同样float和double都是C++的关键字。

8

bool是这样的一种数据类型,它表示是(true)或者否(false),表现上就好像一个比特一样,但它实际上会占用一个字节的空间。

在C++中true代表是,false代表否。同时,其他类型的数据(如整数)也可以向bool类型转换,在C++中0表示否,其他非0的数都表示是。

bool、true、false都是C++的关键字。

9

字符类型刚好是一个字节,可以储存一个字符。

在C++里面,字符要用单引号括起来,字符是指一个字母或者一个符号,而不是多个字母或符号。

或者你可以直接写字符对应的ACSII码,两种方法是等价的。

char同样是C++的关键字。

10

string表示一个字符串,可以是英文、符号、中文,甚至是空的。

值得注意的是,string并不是C++的关键字,也不是C++语法的一部分,它来自标准库,所以我们需要在程序开头加上#include表示这个程序需要使用来自标准库的string.

以反斜杠开头的叫转义字符,可以用它们来表示一些无法直接输入的字符,比如换行、双引号等等,如果确实需要表示反斜杠本身,要使用两个反斜杠。

11

%表示求模,即a%b表示a整除b后的余数。

b=10.0/3.0; 之前我们知道=是赋值号,用来把右面的值复制到左边的变量中。

但在这里,右边并不是一个值,而是一个算式,所以会先计算这个算式的值。之前我们还讲到,类型决定了它能够进行何种运算。

10.0在这里并不是变量,而是一个值(字面值),但它也有类型,它是浮点数,通过在整数10后面加上小数点,可以让它变成浮点数,进行浮点数的计算,得到带小数的结果3.3333.

如果改成10/3,那么10和3都是整数,他们会进行整数的计算,计算结果会省略小数,即3.

虽然b可以储存小数,但这个除法计算是在赋值给b之前发生的,赋值给b的值已经是整数3了。

12

前面的课程提到,标准库中提供了众多实现基础功能的函数,今天我们介绍其中的几个数学函数。

如幻灯片,值得注意的是C++标准库中三角函数有关的函数均使用弧度制。

上面有一段代码演示了如何使用函数,首先是一个函数名,然后是括号,括号里面是以逗号隔开的参数列表。

参数就是你传递给函数的数据,比如我们要算4个平方根,就要将4作为参数传递给sqrt函数,具体有几个参数,取决于具体的函数。

比如pow接受两个参数,它会计算第一个参数的第二个参数次幂。

调用函数后,函数会返回计算结果,你可以将计算结果直接赋值给变量,就像直接书写一个值一样。

这些数学函数来自标准库的cmath部分,需要加入对应的包含语句。

13

14

如果我们要计算一个一元二次方程的根怎么办?我们需要判断一元二次方程的判别式(b^2-4ac)与0的大小关系。

下节课我们将讨论如何利用条件语句进行逻辑判断,让程序不再是一条直线,而是可以分支的。

精子生于 1995 年,英文 ID jysperm.

订阅推送

通过 Telegram Channel 订阅我的博客日志、产品和项目的动态:

王子亭的博客 @ Telegram


通过邮件订阅订阅我的博客日志、产品和项目的动态(历史邮件):

该博客使用基于  Hexo  的  simpleblock  主题。博客内容使用  CC BY-NC-ND  授权发布。最后生成于 2023-12-20.