C++基础知识
上一篇 / 下一篇 2008-04-14 15:50:26 / 个人分类:C++教程
1.3 操作符/运算符(Operators)
前面已经学习了变量和常量,我们可以开始操作他们。C++提供一系列的运算符,它们是一组关键字或非字母但是在所有键盘上都有的符号。运算符是C++语言的基础,所以非常重要。
你不需要背下所有这一小节的内容,这些细节知识仅供你以后需要时参考 。
赋值Assignation (=)
赋值运算符的功能是将一个值赋给一个变量。
a = 5;
将整数5赋给变量a。= 运算符左边的部分叫做lvalue (left value),右边的部分叫做rvalue (right value)。lvalue 必须是一个变量,而右边的部分可以是一个常量,一个变量,一个运算(operation)的结果或是前面几项的任意组合。
有必要强调赋值运算符永远是将右边的值赋给左边,永远不会反过来。
a = b;
将变量b (rvalue)的值赋给变量a (lvalue),不论a当时存储的是什么值。同时考虑到我们只是将b的数值赋给a,以后如果b的值改变了并不会影响到a的值.
例如:如果我们使用以下代码(变量值的变化显示在绿色注释部分):
a = 10; // a:10 b:?社区门户 l~;Gw z!x
b = 4; // a:10 b:4社区门户eY]/a3im6HI
a = b; // a:4 b:4社区门户C:R1j!W2m;``z d/|.r
b = 7; // a:4 b:7
以上代码结果是a的值为4, b的值为7。最后一行中b的值被改变并不会影响到a,虽然在此之前我们声明了a = b; (从右到左规则right-to-left rule)。
C++拥有而其他语言没有的一个特性是赋值符 (=) 可以被用作另一个赋值符的rvalue (或rvalue的一部分) 。例如:
a = 2 + (b = 5);
等同于:
b = 5;社区门户e\+N-Ld/H
a = 2 + b;
它的意思是:先将5赋给变量b,然后把前面对b的赋值运算的结果(即5)加上2再赋给变量a,这样最后a中的值为7。因此,下面的表达式在C++中也是正确的:
a = b = c = 5; //将5同时赋给3个变量a, b和c。
数学运算符Arithmetic operators ( +, -, *, /, % )
C++语言支持的5种数学运算符为:
- + 加addition
- - 减subtraction
- * 乘multiplication
- / 除division
- % 取模module
加减乘除运算想必大家都很了解,它们和一般的数学运算符没有区别。
唯一你可能不太熟悉的是用百分号(%)表示的取模运算(module)。取模运算是取两个整数相除的余数。例如,如果我们写a = 11 % 3;,变量a的值将会为结果2,因为2是11除以3的余数。
社区门户 e Fm1Hvs组合运算符Compound assignation operators (+=, -=, *=, /=, %=, >>=, <<=, &=, ^=, |=)
C++以书写简练著称的一大特色就是这些组合运算符compound assignation operators (+=, -=, *= 和 /= 及其他) ,这些运算符使得只用一个基本运算符就可改写变量的值:
value += increase; 等同于 value = value + increase;
a -= 5; 等同于 a = a - 5;
a /= b; 等同于 a = a / b;
price *= units + 1; 等同于 price = price * (units + 1);
其他运算符以此类推。
`V*IZ.a a0
递增和递减Increase and decrease
书写简练的另一个例子是递增(increase)运算符 (++)和递减(decrease) 运算符(--)。它们使得变量中存储的值加1或减1。它们分别等同于+=1和-=1。因此:
a++;
&@4J S/W
]c'j$Z._0a+=1;社区门户
wPB2jw
a=a+1; 社区门户u[+K
Y s-l
在功能上全部等同,即全部使得变量a的值加1。
它的存在是因为最早的C编译器将以上三种表达式的编译成不同的机器代码,不同的机器代码运行速度不一样。现在,编译器已经基本自动实行代码优化,所以以上三种不同的表达方式编译成的机器代码在实际运行上已基本相同。
这个运算符的一个特点是它既可以被用作prefix前缀,也可以被用作后缀suffix,也就是说它既可以被写在变量标识的前面(++a),也可以被写在后面(a++)。虽然在简单表达式如a++或++a中,这两种写法代表同样的意思,但当递增increase或递减decrease的运算结果被直接用在其它的运算式中时,它们就代表非常不同的意思了:当递增运算符被用作前缀prefix (++a) 时,变量a的值线增加,然后再计算整个表达式的值,因此增加后的值被用在了表达式的计算中;当它被用作后缀suffix (a++)时,变量a的值在表达式计算后才增加,因此a在增加前所存储的值被用在了表达式的计算中。注意以下两个例子的不同:
| Example 1 | Example 2 |
|---|---|
B=3; |
B=3;社区门户{1x]^o` |
在第一个例子中,B在它的值被赋给A之前增加1。而在第二个例子中B原来的值3被赋给 A然后B的值才加1变为4。
社区门户Ag%hlg关系运算符Relational operators ( ==, !=, >, <, >=, <= )
我们用关系运算符来比较两个表达式。如ANSI-C++ 标准中指出的,关系预算的结果是一个bool值,根据运算结果的不同,它的值只能是真true或false。
例如我们想通过比较两个表达式来看它们是否相等或一个值是否比另一个的值大。以下为C++的关系运算符:
| == | 相等Equal |
| != | 不等Different |
| > | 大于Greater than |
| < | 小于Less than |
| >= | 大于等于Greater or equal than |
| <= | 小于等于Less or equal than |
下面你可以看到一些实际的例子:
| (7 == 5) | 将返回false. |
| (5 > 4) | 将返回true. |
| (3 != 2) | 将返回true. |
| (6 >= 6) | 将返回true. |
| (5 < 5) | 将返回false. |
当然,除了使用数字常量,我们也可以使用任何有效表达式,包括变量。假设有a=2, b=3和c=6,
| (a == 5) | 将返回false. |
| (a*b >= c) | 将返回true 因为它实际是(2*3 >= 6) |
| (b+4 > a*c) | 将返回false因为它实际是(3+4 > 2*6) |
| ((b=2) == a) | 将返回true. |
注意:运算符= (单个等号)不同于运算符== (双等号)。第一个是赋值运算符(将等号右边的表达式值赋给左边的变量);第二个(==)是一个判断等于的关系运算符,用来判断运算符两边的表达式是否相等。因此在上面例子中最后一个表达式((b=2) == a),我们首先将数值2赋给变量b,然后把它和变量a进行比较。因为变量a中存储的也是数值2,所以整个运算的结果为true。
在ANSI-C++标准出现之前的许多编译器中,就像C语言中,关系运算并不返回值为真true或假false的bool值,而是返回一个整型数值最为结果,它的数值可以为0,代表"false"或一个非0数值(通常为1)来代表"true"。
逻辑运算符Logic operators ( !, &&, || )
运算符 ! 等同于boolean 运算NOT (取非),它只有一个操作数(operand),写在它的右边。它做的唯一工作就是取该操作数的反面值,也就是说如果操作数值为真true,那么运算后值变为假false,如果操作数值为假false,则运算结果为真true。它就好像是说取与操作数相反的值。例如:
| !(5 == 5) | 返回false,因为它右边的表达式(5 == 5)为真true. |
| !(6 <= 4) | 返回true因为(6 <= 4)为假false. |
| !true | 返回假false. |
| !false | 返回真true. |
逻辑运算符&&和||是用来计算两个表达式而获得一个结果值。它们分别对应逻辑运算中的与运算AND 和或运算OR。它们的运算结果取决于两个操作数(operand)的关系:
| 第一个操作数 rmoj)J-g&l/sU0a |
第二个操作数 s!ro y[n^0b |
结果 KsCR[0a && b |
结果 V xATA6K6O6z N/U,w:@2D0a || b |
|---|---|---|---|
| true | true | true | true |
| true | false | false | true |
| false | true | false | true |
| false | false | false | false |
例如 :
9n+b {^I2S9q0( (5 == 5) || (3 > 6)) 返回true ( true || false ).
]/eJMv#z0
条件运算符Conditional operator ( ? )
条件运算符计算一个表达式的值并根据表达式的计算结果为真true或假false而返回不同值。它的格式是:
如果条件condition 为真true,整个表达式将返回esult1,否则将返回result2。
| 7==5 ? 4 : 3 | 返回3,因为7不等于5. |
| 7==5+2 ? 4 : 3 | 返回4,因为7等于5+2. |
| 5>3 ? a : b | 返回a,因为5大于3. |
| a>b ? a : b | 返回较大值,a 或b. |
位运算符Bitwise Operators ( &, |, ^, ~, <<, >> )
位运算符以比特位改写变量存储的数值,也就是改写变量值的二进制表示:
| op | asm | Description |
|---|---|---|
| & | AND | 逻辑与 Logic AND |
| | | OR | 逻辑或Logic OR |
| ^ | XOR | 逻辑异或Logical exclusive OR |
| ~ | NOT | 对1取补(位反转)Complement to one (bit inversion) |
| << | SHL | 左移Shift Left |
| >> | SHR | 右移Shift Right |
变量类型转换运算符Explicit type casting operators
变量类型转换运算符可以将一种类型的数据转换为另一种类型的数据。在写C++中有几种方法可以实现这种操作,最常用的一种,也是与C兼容的一种,是在原转换的表达式前面加用括号()括起的新数据类型:
:qD7j3wZ(ln i(W| ^6H0float f = 3.14;社区门户mC2f#U\ ]X5t
i = (int) f;
以上代码将浮点型数字3.14转换成一个整数值(3)。这里类型转换操作符为(int)。在C++中实现这一操作的另一种方法是使用构造函数constructor 的形式:在要转换的表达式前加变量类型并将表达式括在括号中:
以上两种类型转换的方法在C++中都是合法的。另外ANSI-C++针对面向对象编程(object oriented programming)增加了新的类型转换操作符 (参考Section 5.4, Advanced class type-casting).
L:H6I#k{w(R5X0
sizeof()
这个运算符接受一个输入参数,该参数可以是一个变量类型或一个变量自己,返回该变量类型(variable type) 或对象(object)所占的字节数:
这将会返回1给a,因为char是一个常为1个字节的变量类型。
sizeof返回的值是一个常数,因此它总是在程序执行前就被固定了。
k!iFNzR kg0
其它运算符
在本教程后面的章节里我们将看到更多的运算符,比如指向指针的运算或面向对象编程特有的运算,等等,我们会在它们各自的章节里进行详细讨论。
!m8Z%YkMR7@e0
运算符的优先度Priority of operators
当多个操作数组成复杂的表达式时,我们可能会疑惑哪个运算先被计算,哪个后被计算。例如以下表达式:
a = 5 + 7 % 2
我们可以怀疑它实际上表示:
a = 5 + (7 % 2) 结果为6,还是 a = (5 + 7) % 2 结果为0?
正确答案为第一个,结果为6。每一个运算符有一个固定的优先级,不仅对数学运算符(我们可能在学习数学的时候已经很了解它们的优先顺序了),所有在C++中出现的运算符都有优先级。从最从最高级到最低级,运算的优先级按下表排列:
| 优先级社区门户p EOysar%Q-O Priority |
运算符 fxETy0Operator |
描述社区门户dY/Gg1?Ty Description |
结合方向 'p(S'^yh0Associativity |
|---|---|---|---|
| 1 | :: | 范围scope | Left |
| 2 | () [ ] -> . sizeof | !cl_WUd4~0 |
Left |
| 3 | ++ -- | 递增/递减increment/decrement | Right |
| ~ | 求补Complementto one (bitwise) | ||
| ! | 取非unary NOT | ||
| & * | 指针Reference 和取地址Dereference (pointers) | ||
| (type) | 数据类型转换Type casting | ||
| + - | Unary less sign | ||
| 4 | * / % | 数学运算符arithmetical operations | Left |
| 5 | + - | 数学运算符arithmetical operations | Left |
| 6 | << >> | 位移bit shifting (bitwise) | Left |
| 7 | < <= > >= | 关系运算符Relational operators | Left |
| 8 | == != | 关系运算符Relational operators | Left |
| 9 | & ^ | | 位操作Bitwise operators | Left |
| 10 | && || | 逻辑运算符Logic operators | Left |
| 11 | ?: | 条件Conditional | Right |
| 12 | = += -= *= /= %= >>= <<= &= ^= |= | 赋值运算符Assignation | Right |
| 13 | , | 逗号Comma, 分隔号Separator | Left |
结合方向Associativity定义了当有同优先级的多个运算符在一起时,哪一个必须被首先运算,最右边的还是最左边的。
所有这些运算符的优先级顺序可以通过使用括号parenthesis signs (和)来控制,而且更易读懂,例如以下例子:
a = 5 + 7 % 2;
根据我们想要实现的计算的不同,可以写成:
a = 5 + (7 % 2); 或者
+Yx%v
t%W4O
{0a = (5 + 7) % 2;
所以如果你想写一个复杂的表达式而不敢肯定各个运算的执行顺序,那么就加上括号。这样还可以使代码更易读懂。
1.4 控制台交互(Communication through console)
控制台(console)是电脑的最基本交互接口,通常包括键盘(keyboard)和屏幕(screen)。键盘通常为标准输入设备,而 屏幕为标准输出设备。
在C++的iostream函数库中,一个程序的标准输入输出操作依靠两种数据流:cin 给输入使用和cout给输出使用。另外,cerr和clog也已经被实现――它们是两种特殊设计的数据流专门用来显示出错信息。它们可以被重新定向到标准输出设备或到一个日志文件(log file)。
因此cout (标准输出流)通常被定向到屏幕,而cin (标准输入流)通常被定向到键盘。
通过控制这两种数据流,你可以在程序中与用户交互,因为你可以在屏幕上显示输出并从键盘接收用户的输入。
z!BNkO0
输出Output (cout)
输出流cout与重载(overloaded)运算符<<一起使用:
cout << 120; // 打印数字 120 到屏幕上
w9M `/M[Hhy ky@7~0cout << x; // 打印变量 x 的值到屏幕上
运算符<<又叫插入运算符(insertion operator) 因为它将后面所跟的数据插入到它前面的数据流中。在以上的例子中,字符串常量Output sentence,数字常量120和变量x先后被插入输出流cout中。注意第一句中字符串常量是被双引号引起来的。每当我们使用字符串常量的时候,必须用引号把字符串引起来,以便将它和变量名明显的区分开来。例如,下面两个语句是不同的:
}4^B!G$?(w0cout << Hello; // 把变量Hello存储的内容打印到屏幕上
插入运算符insertion operator (<<)可以在同一语句中被多次使用:
上面这一行语句将会打印 Hello, I am a C++ sentence 到屏幕上。插入运算符(<<) 的重复使用在我们想要打印变量和内容的组合内容或多个变量时有所体现:
如果我们假设变量age的值为24,变量zipcode的值为90064,以上句子的输出将为: Hello, I am 24 years old and my zipcode is 90064
必须注意,除非我们明确指定,cout并不会自动在其输出内容的末尾加换行符,因此下面的语句:
cout << "This is another sentence.";
将会有如下内容输出到屏幕:
This is a sentence.This is another sentence.
虽然我们分别调用了两次cout,两个句子还是被输出在同一行。所以,为了在输出中换行,我们必须插入一个换行符来明确表达这一要求。在C++中换行符可以写作\n:
cout << "Second sentence.\nThird sentence.";
将会产生如下输出:
Second sentence.社区门户X;C9{)FfuT
Third sentence.
另外,你也可以用操作符endl来换行,例如:
cout << "Second sentence." << endl;
将会输出:
Second sentence.
当操作符endl被用在buffered streams中时有一点特殊:它们被flushed。不过cout 默认为unbuffered,所以不会被影响。 你可以暂时不管这一点。
你可以使用\n或endl来指定cout输出换行,请注意前面所讲的两者的不同用法。
社区门户d:~tGJN;O
输入Input (cin)
C++中的标准输入是通过在cin数据流上重载运算符extraction (>>) 来实现的。它后面必须跟一个变量以便存储读入的数据。例如:
cin >> age;
声明一个整型变量age然后等待用户从键盘输入到cin并将输入值存储在这个变量中。
cin 只能在键盘输入回车键(RETURN)后才能处理前面输入的内容。因此即使你只要求输入一个单独的字符,在用户按下回车键(RETURN)之前cin将不会处理用户的输入的字符。
在使用cin输入的时候必须考虑后面的变量类型。如果你要求输入一个整数,extraction (>>) 后面必须跟一个整型变量,如果要求一个字符,后面必须跟一个字符型变量,如果要求一个字符串,后面必须跟一个字符串型变量。
| // i/o example社区门户0p8W
b.l(Kh(K7Z #include <iostream.h>社区门户(Xr6f~Y(Xnky } int main () -yy:W%L8]~0{ 5~_Wt9t0int i; 2}9l%C)`V2A.} dCk0cout << "Please enter an integer value: ";社区门户)P ` g5uC.y` cin >> i;社区门户,i ?iR1C cout << "The value you entered is " << i;社区门户/RrrbrQRK cout << " and its double is " << i*2 << ".\n";社区门户6HD5t${)KK,ZM2h return 0; O:dOsU,_ X Q0} |
Please enter an integer value: 702 F5k OM5W/| Bx0The value you entered is 702 and its double is 1404. |
使用程序的用户可以使引起错误的原因之一,即使是在最简单的需要用cin做输入的程序中(就像我们上面看到的这个程序)。因为如果你要求输入一个整数数值,而用户输入了一个名字(一个字符串),其结果可能导致程序产生错误操作,因为它不是我们期望从用户处获得的数据。当你使用由cin 输入的数据的时候,你不得不假设程序的用户将会完全合作而不会在程序要求输入整数的时候输入他的名字。后面当我们看到怎样使用字符串的时候,我们将会同时看到一些解决这一类出错问题的办法。
你也可以利用cin 要求用户输入多个数据 :
等同于:
cin >> b;
在以上两种情况下用户都必须输入两个数据,一个给变量a,一个给变量b。输入时两个变量之间可以以任何有效的空白符号间隔,包括空格,跳跃符tab或换行。
导入论坛 引用链接 收藏 分享给好友 推荐到圈子 管理 举报
TAG:
标题搜索
日历
|
|||||||||
| 日 | 一 | 二 | 三 | 四 | 五 | 六 | |||
| 1 | 2 | 3 | 4 | 5 | 6 | ||||
| 7 | 8 | 9 | 10 | 11 | 12 | 13 | |||
| 14 | 15 | 16 | 17 | 18 | 19 | 20 | |||
| 21 | 22 | 23 | 24 | 25 | 26 | 27 | |||
| 28 | |||||||||
我的存档
数据统计
- 访问量: 5244
- 日志数: 64
- 书签数: 3
- 建立时间: 2007-06-08
- 更新时间: 2008-05-27

