1.17 内存的概念
integer1、integer2和sum等变量名实际上对应于计算机内存中的地址(location)。每个变量都有名称(name)、类型(type)、长度(size)和值(value)。
在图1.6所示的加法程序中,执行下列语句时:
cin >>integer1;
用户输入的值放在C++编译器为integer1指事实上的内存地址中。假设用户输入integer1的值45,则计算机将45放在地址integer1中,如图1.7。
integer1
45
图1.7内存中的值
无论何时将新值放入内存地址,这个值将取代该地址中原有的值,并删除前一个值。
运行前面提到的加法程序,当执行下中句时:
cin>>integer2;
假设用户输入舋,则计算机将72放在地址integer2中,如图1.8。注意编译器不一定将这两个地址指定为内存中相邻地址。
程序取得integer1和integer2值后,它将这两个值相加,并将和放在变量sum中。下列语句:
sum=integer1+integer2;
进行加法运算,同时也删除一个值,即把integer1和integer2的和放进地址sum中时,sum原有的值丢失。计算sum之后,内存如图1.9。注意integer1和integer2的值和计算前一样,虽然这些值在计算机进行计算时使用,但并不删除。因此,从一个内存地址读取数值时,这个过程是非破坏性的。
integer1
45
integer2
72
图1.8 两个变量值之后的内存值
integer1
45
integer2
72
sum
117
图1.9 计算之后的内存值
1.18 算术运算
大多数都要进行算术运算。算术运算符见图1.10,注意这里使用了许多代数中没有使用的符号。星号(*)表示乘法、百分号(%)表示求模(modulus)将在稍后介绍。图1.10所示的算术运算符都是二元运算符,即这些运算符取两个操作数。例如,表达式"integer1+integer2"包含二元运算符“+”和两个操作数integer1和integer2。
C++操作 算术运算符 代数表达式 C++表达式 加 + f+7 f+7
减 - p-c p-c
乘 * bm b*m
除 / x/y或x÷y x/y
求模 % r mod s r%s
图1.10 算术运算符
整除(即除数和被除数均为整数)取得整数结果。例如,表达式7/4得1,表达式17/5得3。注意,整除结果忽略分数部分,不用取整。
C++提供求模(modulus)运算符“%”即求得整除的余数。求模运算是个整数运算符,只能使用整数操作数。表达式x%y取得x除以y的余数,这样,7%4得3,17%5得2。后面几章将介绍求模运算符许多有趣的应用。如确定一个数是否为另一个数的倍数(确定一个数为奇数或偶数是这个问题的一个特例)。
常见编程错误 1.4
对非整型操作数使用求模运算衔是个语法错误。
C++中的算术运算表达式应以直线形式在计算机中输入。这样,a除以b应输入为"a/b",使所有常量、变量和运算符放在一行中。编译器通常不接受下列代数符号:
a
-
b
但有些特殊专业软件包支持复杂数学表达式更自然的表示方法。
C++表达式中括号的使用和代数表达式中相同。例如,要将a乘以b+c的和,可以用:
a*(b+c)
C++中算术运算符的运算顺序是由运算符的优先级规则确定的,与代数中的相同:
1. 括号中的表达式先求值,程序员可以用括号指定运算顺序。括号具有最高优先级,对于嵌套括号,由内存向外层求值。
2. 乘法、除法、求模运算优先。如果表达式中有多个乘法、除法、求模运算,则从左向右求值。乘法、除法、求模的优先级相同。
3. 然后再进行加法和减法。如果表达式中有多个加法和减法,则从左向右求值。加法和减法的优先级相同。
运算符优先级保证C++按正确顺序采用运算符。从左向右求值指的是运算符的结合律(associativity),也有一些运算符结合律是从右向左。图1.11总结 了运算符优先级规则,引入其它C++运算符时,这个表可以扩充,详细的运算符优先级请参见附录。
运算符 运算 求值顺序
( ) 括号 最先求值,如果有嵌套括号,则先求最内层表达式的值,如果
同一层对括号,则从左向右求值。
*、/、或% 乘、除、求模 其次求值。如果有多个,则从左向右求值。
+或- 加、减 最后求值。如要有多个,则从左向右求值。
图 1.11 算术运算符优先级
下面用几个表达式说明运算符优先级规则。每个例子都列出代数表达式和对应的C+表达式。
下例求五个值的算术平均值:
a+b+c+d+e 代数: m = ------------ 5 C++: m = (a+b+c+d+e)/5;
括号是必须的,因为作法的优先级比加法高,要把整个和(a+b+c+d+e)除以5,如果不加括号,则a+b+c+d+e/5的取值为:
a+b+c+d+(e/5)
下例是直线的方程:
代数: y = mx+b
C++: y = m*x+b;
不需要括号,乘法优先于加法,因此先乘后加。
下列包含模(%)、乘、除、加、减运算:
代数: z = pr%q+w/x-y
C++: z = p * r % q + w / x - y;
⑥ ① ② ④ ③ ⑤
语句下面的圆圈数字表示C++采用运算符的顺序。乘法、求模和除法首先从左向右求值(结合律为从左向右)因为它们的优先级高于加法和减法。然后进行加法和减法运算,也是从左向右求值。
并不是有多对括号的表达式都包含嵌套括号。例如下列表达式不包含嵌套括号:
a * (b+c)+c*(d+e)
这些括号在同一层。
要更好地了解运算符优先级规则,考虑二次多项式的求值:
y = a * x * x + b * x + c;
⑥ ① ② ④ ③ ⑤
语句下面的圆圈数字表示C++采用运算符的顺序。C++中没有指数运算符,因此我们把x2表示为x*x,稍后会介绍标准库函数pow(数)。由于pow所需要的数据类型有一些特殊情况,因此放第3章再介绍。
假设变量a、b、c、x初始化如下:a=2,b=3,c=7和x=5。
上述赋值语句可以加上多余的括号,使代码更清晰:
y=(a*x*x)+(b*x)+c;
编程技巧1.15
和代数中一样,可以在表达式中加上多余的括号,使代码更清晰,这些括号称为冗余括号。冗余括号常用于组合表达式中的子表达式,使表达式更加清晰。
1.19 判断:相等与关系运算符
本节介绍简单的C++ if结构,使程序根据某些条件的真假做出判断。如果条件符合,即为真(true),则执行if结构体的语句;如果不符合,即条件为假(false),则不执行语句,稍后将举例说明。
if结构中的条件可以用相等运算符(equality operator)和关系运算符(relational operator)表示,如图1.13 关系运算符具有相同的优先级,结合律为从左向右。相等运算符的优先级也相同,但低于关系运算符的优先级,结合律也为从左向右。
标准代数相等与关系运算符 C++相等与关系运算符 C++条件举例 C++条件含义 = == x==y x等于y ≠ != x!=y x不等于y 关系运算符 > > x>y x大于y < < x<y x小于y ≥ >= x>=y x大于或等于y ≤ <= x<=y x小于或等于y
图 1.13 相等与关系运算符
常见编程错误1.5:
如果==、!=、 >=和<=运算符的符号对之间出现空格,则会出现语法错误。
常见编程错误1.6:
逆转!=、 >=和<=运算符的符号顺序(变为=!、=>、和=<)通常会出现语法错误。将!=写成=!有时不会出现语法错误,但会出现逻辑错误。
常见编程错误1.7
不要把相等运算符==与赋值运算符=混淆起来。相等运算符表示等于,而赋值运算符表示取、取值或赋值。有人把相等运算符读作双等于。稍后会介绍,把相等运算符==与赋值运算符混淆起来可能不会造成明显的语法错误,但可能造成相当明显的逻辑错误。
下例用六个if语句比较用户输入的两个数。如果其中任何一个if语句的条件成立,则执行与该if相关联的输出语句。图1.14显示了这个程序和三个示例输出。
注意图1.14的程序边疆使用流读取操作输入两个整数。首先将一个值读到num1中,然后将一个值读到num2中。if语句的缩排是为了提高程序的可读性。另外,注意图1.14中每个if语句体中有一条语句。第2章将会介绍结构体中有多条语句的if 语句(将语句体放在花括号“{ }”中)。
// Fig.1.14:fig01_14.cpp // Using if statements,relationnal // operators,and equality operators #include<iosream.h> int main() { int num1,num2; cout<<"Enter two integers,and I will tell you " <<"the relationships they satisfy: "; cin>>num1>>num2; // 读取两个整数 if(num1==num2) cout<< num1<<"is equal to "<< num2<< endl; if(num1!=num2) cout<< num1<< " is not equal to "num2<< endl; if(num1< num2) cout<< num1<< " is less than "<< num2<< endl; if(num1>num2) cout<< num1<< " is greater than "<< num2<< endl; if(num1<=num2) cout<< num1<< " is less than or equal to " << num2<< endl; if(num1>=num2) cout<< num1<< " is greater than or equal to " << num2<< endl; return; // 返回一个程序正常结束的标识 }
输出结果:
Enter two integers,and I will tll you The relationships they satisfy: 3 7 3 is not equal 7 3 is less than 7 3 is less than or equal to 7 Enter two integers,and I will tell you the relationships they satisfy:22 12 22 is not equal 12 22 is gretaer than 12 22 is greater than or equal to 12 Enter two integers,and I will tell you the relationships they satisfy:7 7 7 is equal to 7 7 is less than or equal to 7 7 is greater than or equal to 7
图1.14 使用相等和关系运算符
编程技巧1.16
if语句中的缩排可以提高程序的可读性,突出结构体
编程技巧1.17
程序中一行只放一条语句
常见编程错误1.8
if语句的打件后面的右括号之后紧跟着分号通常是个逻辑错误(但不是语法错误)。分号使if结构体变成空的,不管打件是否为真,这个if结构都不进行任何操作。更糟糕的是,原先if结构体变成if结构后面的语句,不管条件如何总是执行,通常会使程序产生错误结果。
注意图1.14中空格的用法。在C++语言中,空白字符(如制表符、换行符和空格)通常都被编译器忽略。因此,语句中可以根据程序员的爱好加上换行符和空格,但不能用换行符和空格分隔标识符。
觉编程错误1.9
把main写成ma in是语法错误。
编程技巧1.18
长语句可以分成多行。如果一条语句要分成多行,可以在分隔列表的逗号或长表达式的运算符后面断行。如果语句要分成两行或多行后续行可以编排。
图1.15显示了本章介绍的运算符优先级,运算符优先顺序从上向下递减。注意赋值运算符之后的所有运算符结合律均为从左向右。加法是左结合的,因此表达式x+y+z求值为(x+y)+z。赋值运算符是从右向左结合的,因此表达式x=y=0求值为x=(y=0),首先将0赋给y,然后将结果0赋给x。
运算符 结合律 类型 ( ) 从左向右 括号 * / % 从左向右 乘 + - 从左向右 加 << >> 从左向右 流插入/读取 < <= > >= 从左向右 关系 == != 从左向右 等于 = 从右向左 赋值
图 1.15 运算符优先级和结合律
编程技巧1.19
编写包含多个运算符的表达式时要参考运算符优先级,确保表达式中的运算符按所要求的运算。如果无法确定复杂表达式中的求值顺序,可以用括号强制顺序,就像代数式中一样。注意,有些运算符(如赋值运算符)是从右向左结合的,而不是从左向右。
前面介绍了C++的许多特性,包括在屏幕上打印数据,从键盘输入数据、进行计算和作出判断。第2章利用这些知识介绍结构化编和 ,将会学到更多的编程技巧,介绍如何指定和改变语句执行顺序(称为控制流)。
1.20 新型头文件与名字空间
本节是为使用支持ANSI/ISO草案标准的编译器用户提供的。草案标准指定了许多旧式C++头文件的新名,包括iostream.h,大多数新式头文件不再用扩展名.h。图1.16改写图1.2,演示新型头文件和两种使用标准库头文件的方法。
第3行:
#include<iostream>
演示新型头文件 名语法。
第5行:
using namespace std;
指定用std名字空间(namespace),这是C++中的新特性。名字空间可以帮助程序员开发新的软件组件而不会与现有软件组件产生命名冲突。开发类库的一个问题是类和函数名可能已经使用。名字空间能为每个新软件组件保持惟一的名称。
// Fig. 1.16:fig01_16.cpp // Using new-style header files #include<iostream.h> using namespace std; int main() { cout<<"Welcom to C++! "; std::cout<<"Welwcom to C++! "; return 0; }
输出结果: Welcom to C++! Welcom to C++!
图 1.16 使用新型头文件
C++草案标准中的每个头文件用名字空间std保证今后C++标准库操作的每个特性是惟一的,不会与其它程序员开发的软件组件混淆起来,程序员不能用名字空间定义新的类库。上述语句只是表示我们使用C++标准库中的软件组件,要定义自己的类库,则可以将我们的所有类和函数放在名字空间deitel中,使我们的类库与所有其它公司的类库和C++标准类库区别开来。
程序中出现"using namespace std"语句之后,就可以像第9行那样用cout对象将数值输出到标准输出流中。如果使用两个或几个类库,其中有的特性名称相同,则可能引起名称冲突。这时就要用名字空间来完全限定所用的名称,例如第10行的std::cout:
std::cout<<"Welcom to C++!";
cout的完全限定名为std::cout,如果全部采用这种形式,虽然比较繁琐,但程序中第5行的"using namespace std"语句就没有必要了。using语句可以在C++标准库中使用每个名称的简写版本(或其它指定名字空间的名称)。我们将在本书稍后详细介绍名字空间。目前并不是所有C++环境都已经支持新的头文件的命名格式。
为此,我们在本书大部分地方使用旧式头文件 ,只在介绍C++标准新特性时才使用新的头文件命名格式,使用新格式时将特别注明。
考研英语真题http://www.kyjxy.com/yingyu/zhenti/
考研专业目录http://www.kyjxy.com/yuanxiao/zhengce/