首页 服务器 编程 必备知识 搜索引擎 圩日手册
站内搜索
最近浏览
推荐文章
热文排行

第七章 运算符、表达式、语句


7.1 算术运算符

  7.1.1 加减乘除

  7.1.2 求模运算

  7.1.3 赋值运算

  7.1.4 自运算

  7.1.5 ++ 和 -- 运算

7.2 算术类型转换

  7.2.1 隐式类型转换

  7.2.2 显式类型转换

7.3 关系运算

7.4 逻辑运算

7.5 表达式

7.6 语句

我们已经学会如何用变量来表达数据,比如我们现在要写一个《工资管理系统》……我看到很多学员本来昏昏欲睡的眼睛刷地放出了光芒:“老师,我们现在就能写《工资管理系统》系统了吗?”

回答:不能,我们刚刚学了点基础而已。不过,至少我们可以猜想,要写一个工资管理系统,总得懂得如何表达“工资”这个信息吧?还有像职工的年纪,职工人数等等,都得用C/C++语言来表达,这些我们现在都会啊!

double gongZi;  //工资

int    nianLin; //年龄

int    zhiGongRenShu; //职工人数

看看,上面那些定义变量的代码,你都看得懂,写得出的吧?我们还是颇有成就感的。

 

本章,我们将学习如何对数据进行运算。

7.1 算术运算符

7.1.1 加减乘除

先来学习最基本也最常用的加减乘除等运算。在C++中,加减乘除分别使用字符 '+'、'-'、'*'、'/'作为运算符号。

加、减、乘的操作没有什么需要特别说明之处,和生活中的相关运算完全一样,如:

int a = 1 + 2 - 3 * 4;

得到的结果:a等于 -9。当然,乘号使用*表示,这你得记。

除运算除了使用反余杠'/'表示以外,很重要的一点是别忘了,对于整数类型,或字符类型的数据进行除运算时,小数部分将被截掉,因为整型类型的数据不能保存小数部分,如:

int a = 5 / 2;

得到结果:a 等于 2,而不是2.5。

注意:可能大家会以为,之所以 5 /2 结果是2,是因为我们让一个整型变量a等于它,其实原因并不是因为a是int类型,请看:

float a = 5 / 2;

虽然a现在被声明为实型,但执行这句程序,a的值仍然是2。事实上,精度丢失是在计算机计算5/2时就发生了。所以,准确的写法是:

 

float a = 5.0 / 2;

或者:

float a = 5 / 2.0;

或者:

float a = 5.0 / 2.0;

也就是说,只有除数或被除数至少需要有一个是明确指定为实型,除运算才能得到小数部分。这里我们也更明确类似于5和5.0在计算机中的区别:虽然数值大小一样,但加了5.0被当成实型数对待,而5则被当成整型数。

 

7.1.2 求模运算

除了 + - * / 以外, % 操作也是C++常用的操作符。% 并不是进行“百分比”的运算。在C和C++里, % 进行求余数运算,求余数也称“求模”,以下是求余操作的例子:

int a = 5 % 2;

结果是,a 等于 1,即:5 除以2,余数为1。

 

7.1.3 赋值运算

差点忘了,我们已经很熟悉的等号:= ,C,C++称为赋值操作。看看例子,是不是很熟悉:

int a = 10;

再如:

int b;

b = a;

或:

int c = 12 * 2;

 

在C++中,可以使用连等操作:

int a ,b;

a = b = 100;

结果是,a和b都为100。

7.1.4 自运算

先来看一个计算机编程中常有的语句例子:

 

int a = 10;

a = a + 1;

 

上面的代码执行后,结果a的值是11。可能不是很理解 a = a + 1;这种运算。

首先可能会认为,a 和 a + 1 怎么会相等呢?这可是个严重错误,要知道,在C,C++里,'=' 就是表示赋值操作,至于表示左右两值“相等” 的另有符号。因此,a = a + 1,所完成的工作就是:先计算出 a + 1的值,然后将该值赋给a。

假设我们的存款原为a,现在存入1元,那么新的存款就等于旧存款加上1元钱,用编程语言表达,就是 a = a +1;

在C,C++中,这样的自加操作可以有另一种表达,并且用这一种表达,计算机的运算速度比较快。

a = a +1;的另一种运算速度较快的表达方法:

a += 1;

+= 被定义为一种新的操作符(因此+和=要连着,中间不能有空格)。它实现的操作就是将其左边的量在自身的基础上加上右边表达式的值。比如:,假设a原来的值为 10,那么:

a += 2;

执行这一句后,a的值为12,即 a = 10 + 2;

 

同样的,减,乘,除,求余都有这种操作符:-= 、 *= 、/= 、%= 等。我们以后学习到的另外一些运算符,也有同样的这种对应运算。举一些例子:

假设在分别进行以下操作之前,a原值都为10。

a -= 2;

执行后,a值为8;(a = 10 - 2)

 

a *= 2;

执行后,a值为20;(a = 10 * 2)

 

a /= 2;

执行后,a值为5;(a = 10 / 2)

 

a %= 2;

执行后,a值为0; (a = 10 % 2)

 

C,C++提供这些操作符,目的仅仅是为了提高相应操作的运算速度。为什么 a += 2;会比 a = a + 2;运算得快呢?从编译的角度上看,是因为前者可以生成更短小的汇编代码。

C,C++提供这些别的语言没有的操作符,可以供我们写出优化的代码。

在某些特殊情况下,优化还可以继续。请看下一小节。

7.1.5  ++ 和 -- 运算

当运算是自加或自减1的时候,C,C++提供了更为优化的运算操作符:++,--。

设整型变量 a,原值为 10。我们已经知道,要实现对其加1,可以有以下两种写法:

方法1: a = a +1;

方法2: a += 1;

我们还知道方法2比方法1好。现在还有方法3,并且是最好的方法。

++a,或者:a++;

也就是说,在只自加1的情况下,代码 a++ 或 ++a 可以生成最优化的汇编代码。

 

同样,自减1操作也有对应的操作符:--a 或 a--;

设a原值为10,则执行 --a 或者 a--后,a的值都为9。

 

现在来谈谈 ++a 和 a++ 有什么区别。

在C,C++语言里,++a 和 --a 称为前置运算(prefix),而 a++ 和 a--称为后置运算(postfix)。

如果仅仅是进行前置工或后置运算,那么结果是相同的,这我们已经在前面谈过,我们以++为例:设a为10,则无论是 ++a 或 a++,执行结果都是让a递增1,成为11。

但在有其它运算的复杂表达式中,前置++运算过程是:先加1,然后将已加1的变量参以其它运算。后置++的运算过程是:先用未加1的变量参以其它运算,然后再将该变量加1。

听起来有些绕,我们举些例子看,还是变量a,原来值为10:

例子1:

int b = ++a; //前置++

运算结果:a的值为11,b的值也为11。

计算过程解析:

先计算 ++a,结果a值为11;

然后再计算 b = a;结果b值也为11。

 

例子2:

int b = a++; //后置++

运算结果:a的值为11,但b的值为10。

计算过程解析:

先计算 b = a;因此,b的值是未加1之前的a,所以为10;

然后再计算 a++,a的值为11。

 

再举一复杂点的表达式:

int a = 10;

int c = 5;

 

int b = a++ + c;

执行这些代码,b值为15

 

倘若换成:

int a = 10;

int c = 5;

int b = ++a + c;

执行这些代码,b值为16;

想一想,为什么?

 

上在举的是++的例子,对于--操作,其计算顺序的规定一样。

 

++和--的确能加快运算速度,但它们在前置和后置运算上的微小区别,却很空易让你的代码变得不清晰。更为不好的是,不同的编译器可能会对比有不同的解释,比如VC和BC/CB会对同一代码会有不同的编译结果,造成代码的运行结果也不一样,这是我们应该尽量避免的。所以我们建议在代码尽量不要依赖于前置和后置运算的区别。(尽管它会让你的代码看上去很象“高手”所写)。

 

7.2 算术类型转换

7.2.1 隐式类型转换

类型转换在C,C++中也属于一种运算。

前面我们举过一个例子:

float a = 5 / 2 ;

还记得a的计算结果吗?上式中,a将得到的值是2。因为在除式 5/2 中,5和2都是整数,所以计算机按整数类型进行了除运算,结果所有的小数位都被丢失了。

我们列出了三种可以解决小数位丢失的方法:

方法1: float a = 5.0 / 2;

方法2: float a = 5 / 2.0;

方法3:  float a = 5.0 / 2.0;

 

最后一种方法好理解,5.0和2.0都明确指定为实型(double),所以计算结果可以保存小数位。而像第一种:被除数5.0被指定的为实型,但除数2仍然为整型,这两种数据类型的精度不一样,这时,计算机将按哪个类型作为标准呢?

 

C++遇到两种不同数据类型的数值进行运算时,会将某个数做适当的类型转换,然后再进行转换。转换总是朝表达能力列强的方向进行,并且转换总是逐个运算符进行的。

 

以下是转换的两条方向线:

char/unsigned char --> short/unsigned short --> int/unsigned int --> double --> long double

                                                   float         --> double --> long double

 

像上面的 a = 5 / 2。计算机先计算5/2,由于 5,2一样是整型,所以计算机不作转换,算出其结果为2,然后赋值给a,因此,就算a是float类型,但仍然只能得到2的结果,而不是2.5。

而 a = 5.0 / 2。计算机在计算 5.0 / 2 时,发现5.0是实型(带小数点),而2是整型,二者不一,所以将2先自动转换成double数,然后现和5.0进行除运算。

这个转换过程,在程序运行时自动进行,称为隐式转换。

隐式(自动)转换尽量使用我们的程序更加合理,但有时它并不能完全符合我们的要求。比如:

 

int b = 5, c = 2;

float a = b / c;

 

由于除号两边的操作数:b、c都是有明确类型的变量。这时,既不会有隐式转换进行,我们也不能通过加 '.0'来改变其中某个数的数据类型:

float a = b.0 / c.0; //这种写法是错误的,不可能实现。

这种情况下,我们需要显式(强制)类型转换。

7.2.2 显式类型转换

显式类型转换也称为强制类型转换。它的语法形式有两种:

形式1 : (类型名) 变量或数值

形式2: 类型名(变量或数值)

 

实际例子如:

int b = 5, c = 2;

float a = (float)b / c;

或者:

float a = float(b) / c;

两种写法都可以将变量b强制转换为float类型。

不过,在要转换的数据类型带有修饰符时,则必须使用第一种型式。比如:(unsigned int) a;

其实,两边都加上括号有时更清晰:(unsigned int) (a);

 

7.3 关系运算

 “关系”运算?听上去很费解。

计算机系一师哥师妹正在处朋友,某晚两人在校园林荫处正在谈情说爱,突然冒出一校监:“说!你俩什么关系?”

果然不愧为计算机系的一对小情侣,以下是他们的回答:

男:“我比她高!”

女:“我比他瘦。”

男:“我比她壮!”

女:“我比他美。”

校监:“我倒!”

 

所谓的关系运算,在C,C++语言里,就是比较运算。

算术运算所得的结果是数值,而关系运算所得的结果为逻辑值,也称布尔值。即我们以前所学的bool类型允许的值:真或假。真用true表示,假用false表示。

关系操作符有:

== (比较左右值是否相等)

>  (比较左值是否大于右值)

>= (比较左值是否大于或等于右值,也称为不小于)

<  (比较左值是否小于右值)

<=(比较左值是否小于或等于右值,也称为不大于)

!= (比较左右值是否不相等)

 

比较是否相等,使用两个连写的等号表示。因此 == 和 = 是两个不同的概念,后者指赋值运算。

C,C++的不等于用 != 表示,而不是我们更常见的 <>,请大家注意。

下面举一些例子。

 

int a = 10;

int b = 9;

则:

a == b+1 运算结果: true;

a == b   运算结果: false;

a > b    运算结果: true

a >= b   运算结果: true;

b > a    运算结果: false;

a >= b+1 运算结果: true;

a <= b+1 运算结果: true;

a != b;  运算结果:true;

 

7.4 逻辑运算

 

逻辑运算有三个操作符:

!  (非,取逻辑反,NOT)

&& (逻辑与,并且,AND)

|| (逻辑或,或者,OR)

 

该到考验你是否有资质学习编程的时候了……请回答以下三个问题:

 

1、真 并且 真,结果是真是假?

2、真 并且 假,结果是真是假?

3、真 或者 假,结果是真是假?

 

三道题的答案分别是:真,假,真。

&& 对应于题目的的“并且”,而 || 对应 “或者”

当我们需要说,只有条件A和条件B都成立……用C,C++表达即是: A && B。

当我们需要说,只要条件A或者条件中成立……,这时表达为:  A || B。

 

如果你是一个女学员,追求者太多让你烦,那么你就可以开出如下条件:

 

告示:

凡追我者,请先看以下程序代码(如看懂,请先点击此处到‘没有弯路,编程摇篮’报名进修),判断自已是否符合条件,条件符合者,方可得以见本小姐一面:

a = 富和盖茨有一比;

b = 帅胜德华留三分;

见面条件:  a && b;

和比尔盖茨一样富并且和刘德华一样帅,这样的人有吗?不管你嫁得出去退不出去,现在你必须牢牢记住:

表达式:条件1 && 条件2,其运算结果要为真(true),必须条件1和条件2都为真。换言之,二者中有一个为假,那么整体条件就为假。

 

那么,如果换成或者呢?我们来看看:

a = 富和盖茨有一比;

b = 帅胜德华留三分;

见面条件:  a || b;

事情发生了巨大的变化。现在,有个丑八怪,但却和比尔盖茨一样富,你就得会会他老人家。另外有一穷光蛋,却貌如潘安(假设潘安比德仔帅点),按照条件,你也得去见见。因为你列的条件是:a 或者 b,只要其一成立,总体条件即成立。

 

最后我们来说说“!”。感叹号在C,C++拿来表达“相反”或“非、不”等意思。它的运行很简单:原来为真,加感叹号后为假,原来为假,加感叹号后为真。

 

下表列出三种逻辑操作符的使用方法:

 

符号

意思

例子

&&

并且 (and)

条件1 && 条件2

||

或者 (or)

条件1  ||  条件2

not

 ! 条件

 

下面列出了 &&(与) 操作的所有可能条件及结果:

 

真 && 真 = 真

真 && 假 = 假

假 && 假 = 假

 

下面列出了 || (或)操作的所有可能条件及结果

 

真 || 真 = 真

真 || 假 = 真

假 || 假 = 假

 

以下则为 ! 操作:

!真  = 假

!假  = 真

 

尽管课程列出了所有可能性,尽管看上去也就这几话,但大家一定要从骨子里头理解这些,不能管背住来解决问题。当我们写程序时,就会发现天天在和一堆的真假判断打交道,如果这些最基本的逻辑操作你不理解,那么就会给解决复杂的逻辑问题带来麻烦。

 

7.5 表达式

 

变量、常量、各种运算符等组成表达式,用于表达一个计算过程。

比如写一个计算圆面积,我们可以如下表达:

 

area = PAI * R * R;

其中,R是某一定义的变量,表示半径,而PAI我们事先定义的一个值为3.14的宏。

 

PAI * R * R; 是一个表达式;area = PAI * R * R;也是一个表达式。表达式组成了C,C++语句,而语句组成C,C++的程序。

 

简单的如:3 + 2 ,也是一个表达式。

 

表达式是操作符、操作数和标点符号组成的序列,用于表达一个计算过程。

 

对表达式的计算,需要考虑其各计算部分的运算优先级,其中最熟悉莫过于我们小学就学过的“括号优先,先乘除后加减”。

下面列出我们已学过的运算符的优先级:

 

按优先级高低排列的运算符:

 

级别 运算符 说明
1 ( ) 括号
2 !  +(正号) -(负号) ++ -- sizeof +,-在这里不是加减,而是指正负号
3 * / % 乘,除,求模(取余)
4 + - 加减
5 == != 等于 不等于判断
6 && 逻辑与
7 || 逻辑或
8 = += *= /= %= 赋值,自运算操作符

 

7.6 语句

C++语句和表达式并没有来格的区分。一人表达式,加上一个分号后,可以直接形成语句:

 

3 + 2;

 

计算机可以执行该语句,但它并不改变程序的运行逻辑。就像我们说话时说了一句废话。当一些表达式组合起来,完成某一相对完整的功能后,再加一个分号表示结束,这就组成一条语句。如:

 

a = 3 +2;

看,这是一行赋值语句,它改变了a的值。

 

当然,语句也可以直接是一个分号,称为空语句:

;

除非为了调试方例,否则写一句空语句纯属多余。

 

我们已经学习过两种常用的语句类型,其一为变量定义语句,其二为赋值语句。

 

变量定义语句完成指定变量的定义。

int a ,b,c;

赋值语句则实现为指定变量获得指定值的操作。

 

a = 20;

b = 10 * 2 / 3;

c = 2 * (a + b);

如上面所示,赋值时,右值(等号右边的值),可以是一简单的常数或变量,也可以是一个表达式。

 

在C,C++中,赋值语句可以使用连等:

 

a = b = 10;

 

执行这一语句时,b先等于10,然后a等于b的值,结果a和b都是10。

 

当然,变量定义语句也可以和赋值语结合,即我们以前学的,在定义变量时同时初始化。

 

int a = 10,b = 20;

int c = a * b;

 

不过,你不能在定义变量时同时使用连等来实现初始化:

int a = b = 10; //错误。

编译器会报错说,b还没定义。

 

有时候,连续的多句语句属于同一控制范围,这时,我们用一对花括号将这些语句括起:

{

  int a = 100;

  int b = a * 20;

  ....

}

 

花括号内的内容,称为复合语句

 

正是一行行语句组成C,C++程序,结果本章时,我们可以自豪地宣布:我们已经一脚迈入了C++大门的门槛!

[wangjy17908]
添加时间:2008-04-12
版权所有(C)2005-2015