370 likes | 534 Views
第 4 章 操作及其控制. 学习目的: ① 掌握基本数据类型与操作 ; ② 掌握 C++ 的主要语句 ; ③ 熟练掌握 C++ 提供的顺序控制 ; ④ 熟悉 include 等预处理指令。. 4.1 基本操作与运算符 4.2 表达式 4.3 语句 4.4 预处理指令. 4.1 基本操作与运算符. 操作又称为运算,通用程序设计语言提供多种操作,每种操作都用运算符标记,如:加( + )、减( - )、乘(*)、除( / )等算术运算,以及指针运算、移位等各种语言特有的操作。 运算符分类: 根据操作数个数: 单目运算符、双目运算符及三目运算符;
E N D
第4章 操作及其控制 学习目的: ① 掌握基本数据类型与操作; ② 掌握C++的主要语句; ③ 熟练掌握C++提供的顺序控制; ④ 熟悉include等预处理指令。 4.1基本操作与运算符 4.2表达式 4.3语句 4.4预处理指令
4.1 基本操作与运算符 操作又称为运算,通用程序设计语言提供多种操作,每种操作都用运算符标记,如:加(+)、减(-)、乘(*)、除(/)等算术运算,以及指针运算、移位等各种语言特有的操作。 运算符分类: 根据操作数个数: 单目运算符、双目运算符及三目运算符; 按照功能不同: 算术运算符、关系运算符、逻辑运算符、位操作运 算符、赋值运算符等 另外, 可按优先级和结合性对算符进行分类。 4.1.1 赋值操作 4.1.2 算术操作 4.1.3 增1(减1)操作 4.1.4 关系、逻辑操作 4.1.5 条件运算符
4.1.1 赋值操作 赋值操作用于改变数据对象的值,基本类型变量的赋值操作一般由赋值符 =表示,其具体语义是将 =左侧数据对象的值改变为 = 右侧表达式的值(常数为表达式的一种形式): 注意: 对于字符串的赋值采用 memset()、memcpy()、strcpy()等函数进行。 int nVar(0); nVar=4; nVar=nVar+2; nVar+=2; int *pN=&nVar; *pN=8;
4.1.2 算术操作 包括加、减、乘、除、取负、取余数,分别以+、-、*、/、-、%等运算符代表 。 注意: 对整型数据的除法操作,其结果为整型数据,例如:5.0/2.0=2.5、 2.0/4=0.5,但5/2=2、 2/4=0,相当于进行除法后保留商的整数部分。 其中 % 的操作数要求为int型,而其它运算符要求操作数为基本数据类型或指针类型等。复杂运算的书写规则与人类的习惯相似: 3+4 n*(x+4) 对于用户自定义类型或构造类型,需要由用户重新给出上述运算符所代表的具体操作 (运算符重载)。
4.1.3 增1(减1)操作 格式为: ++prefix_exp --prefix_exp 1. 前缀增1(减1)运算符 要求操作数prefix_exp是整型、浮点型或指针型,并且必须是一个可修改的左值表达式(即表达式没有const属性),例如整型变量等。前缀增1(减1)操作结果的类型与操作数类型相同,且结果是左值,运算后prefix_exp的值加(减)1,表达式的值同此。因此x=++Val相当于x=Val+1和Val=Val+1两个操作的复合,例如当变量Val的值为5时,表达式x=++Val的结果是x的值为6,Val的值也为6。 int n=0; ++n; ++(++n);
4.1.3 增1(减1)操作 格式为: postfix_exp ++ postfix_exp -- 2. 后缀增1(减1)运算符 对操作数postfix_exp的要求与前缀增1(减1)运算符相同。运算结果类型与操作数类型相同,但不再是左值。 int n=0; n ++; ++n; (n++)=2;
4.1.4 关系、逻辑操作 这两种操作经常出现在条件判断中,关系操作有六种: > (大于)< (小于)==(相等) >=(大于等于)<=(小于等于)!= (不相等) 关系操作结果的类型为布尔型或逻辑型,例如3==4的值为false、6>2的值为true。 逻辑操作有三种: &&(逻辑与)||(逻辑或)!(逻辑非) 逻辑运算操作数类型为逻辑型,结果为逻辑型,具体操作语义如下: 两操作数都为真,逻辑与运算的结果为真,否则为假。 两操作数中至少一个为真,逻辑或运算结果为真,否则为假。 操作数为真,逻辑非运算结果为假,否则为真。
4.1.5 条件运算符 该运算符是一个三目运算符,格式如下: exp0 ? exp1 : exp2 语义是,如果exp0为真,则该表达式的值为exp1,否则表达式的值为exp2。表达式的类型与exp1和exp2中类型高的(4.2.1)一个相同。 使用方法举例如下: int MaxAB = (A>B) ? A : B;
4.2 表达式 运算符与操作数相结合形成的式子称为表达式。常见的简单表达式有算术表达式、逻辑表达式、关系表达式、赋值表达式等。简单表达式通常由一个运算符与一两个操作数构成,用来表述算法中最基本的简单操作。复杂的表达式由多个表达式复合而成,它们可以用来描述算法中的一个模块或者是复杂的处理。 任何表达式在运算后都会产生一个结果,这个结果具有某种类型和数值,称作表达式的类型和值。 4.2.1 隐含类型转换 4.2.2 强制类型转换 4.2.3 表达式内的顺序控制 4.2.4 运算符的优先级 4.2.5 运算符的结合性
4.2.1 隐含类型转换 每个表达式的值都具有确定类型,取决于运算符的种类和操作数类型,当二目运算符的两个操作数类型不同时,不能直接进行运算,必须进行适当的类型转换。 对于基本数据类型,这种类型转换通常为语言所内建,因此称为隐含类型转换。隐含类型转换的规律是将低类型的操作数转换为高类型,对算术运算符而言,常见类型的高低顺序如下: int→unsigned→long→unsigned long→float→double 上述类型中int类型最低,double类型最高,当低类型和高类型同时出现在一个运算符操作数中时,低类型将被转换为高类型,例如当算术运算符两个操作数中有一个的类型为double时,则运算前另一个操作数将被转换成double类型,然后进行浮点型的算术运算,运算后的结果也将为double型;总之,计算算术表达式的值时,如果两个操作数的类型不同,所采用的方针是用存储宽度较大的类型存放存储宽度较窄的操作数,这样做的目的是为了不丢失信息。
4.2.2 强制类型转换 当操作数的类型不同,而且不属于基本数据类型时,经常需要强制类型转换,将操作数转化为所需的类型。强制类型转换具有两种形式,称为显式强制转换和隐式强制转换。 1. 显式强制类型转换 格式为: type(<expression>) 或 (type)<expression> type为类型描述符,如int、float等。<expression>为表达式。经强制类型转换运算符运算后,返回一个具有type类型的数值,这种强制类型转换操作并不改变操作数本身,运算后操作数本身未被改变,例如: int nVar=0xab65; char cChar=char(nVar); 上述强制类型变换的结果是将整型值0xab65的高端两个字节去掉,而将低端两个字节的内容作为char型数值赋值给变量cChar,经过类型变换后nVar的值并没有发生改变。
4.2.2 强制类型转换 隐式类型转换发生在赋值表达式和有返回值的函数调用表达式中。在赋值表达式中,如果赋值符左右两侧的操作数类型不同,则将赋值符右侧操作数强制转换为赋值符左侧操作数类型的数值后赋值给赋值符左侧的变量。 在函数调用时,如果return后面表达式的类型与函数返回值类型不同,则在返回值时将return后表达式的数值强制转换为函数返回值类型后再将值返回。例如: 2. 隐式强制类型转换 int nVar; double dVar=3.88; nVar=dVar; //执行本语句后,nVar的值为3,而dVar仍然是3.88
? (3+5)*8 3+5*8 3+(5*8) 4.2.3 表达式内的顺序控制 表达式的值与操作数类型有关,也与运算顺序有关。 应用括号直接控制表达式中子表达式的求值顺序,能够避免运算结果的不确定性。例如:按习惯a*b/c可以利用括号写成(a*b)/c,否则有可能理解为a*(b/c),这两个表达式的值通常是不一样的,比如(3*2)/3=2,而3*(2/3)=0。
4.2.4 运算符的优先级 制定运算符的优先级的目的是解决表达式语义的二义性,高优先级运算符所代表的操作先进行、低优先级运算符代表的操做的后进行,在一定程度上可以解决二义性问题。 +、-、*、/等4种基本操作的执行顺序与人们所习惯的四则运算规则相同。常用运算符的优先级如下:
4.2.5 运算符的结合性 结合性用于多个具有相同优先级运算符出现在一起时运算顺序的控制,具有左结合性的运算符左边优先于右边,因此将从左至右逐个运算符地进行运算,而具有右结合性的运算符的运算顺序与此相反。 只有单目运算符、条件运算符和赋值符是右结合的,其他运算符均为左结合。 a=b=c 等价于 a=(b=c) a+b+c 等价于 (a+b)+c 3+4+5-8 等价于 ((3+4)+5)-8 3*4/5*8 等价于 ((3*4)/5)*8 3*4*8/5 等价于 ((3*4)*8)/5
4.3 语句 语句是构成程序的基本单元,简单语句用于表示一种单一功能的操作,复合语句、选择语句、循环语句等复杂语句可能代表多个操作组成的一种复杂操作或功能。 语句由单词按照语句的语法规则组成,单词间以分隔符、运算符或若干个空格符分隔,语句通常以一个特殊的符号结束,例如C++的语句以分号做为结束标志。 4.3.1 表达式语句 4.3.2 语句间顺序控制 4.3.3 复合语句 4.3.4 选择语句 4.3.5 循环语句 4.3.6 直接顺序控制
4.3.1 表达式语句 表达式语句(Expression Statement)的形式很简单,在C++中,只要在任何表达式的结尾缀以分号 ; 就构成了表达式语句。例如: x=10*y; l=5, m=6, n=7; mb=a&(b|c); a+b; fun(x, y); y=MyFunction(3, 8); 表达式语句是一个大家族,因为表达式本身的种类就很多,我们在编程中最常用到的表达式语句是变量赋值语句、增1语句、减1语句。如下述的程序段: int n=0; while(n<10) { x=2*n; // 赋值语句 ++n; // 增1语句 }
4.3.2语句间的顺序控制 作为算法实现工具,通用程序设计语言通常都提供描述算法三种基本控制结构的具体方式,使用三类语句构成程序的三种基本控制结构: 顺序结构 使用顺序语句实现。顺序语句指一组语句的执行顺序与语句的物理排列顺序相同。 选择结构 使用选择语句加以实现。选择有两种形式:条件语句和开关语句。 循环结构 使用循环语句加以实现。循环语句有三种形式:do语句、for语句和while语句
4.3.3 复合语句 复合语句是由花括号 { },及其内部语句组成,作为一个整体在语法上是一条语句,尽管其内部可能包含多条语句。复合语句具有明显的块特色,所以也称为块语句。 复合语句可以嵌套,即复合语句的内部可以含有其他复合语句。复合语句可以单独使用,将程序的一部分利用 { } 扩起来作为相对独立的一块形成良好的编程风格,但更常用于if语句、switch语句或循环语句中。另外,如果在复合语句中嵌入了一条或多条说明变量,则常称这种复合语句为分程序或块结构。
a==10 a==9 a==8 true false true false true false b=30 b=21 b=20 b=9 if语句 语句 布尔表达式 else 语句 if ) ( 4.3.4 选择语句 1 条件语句 从上述语法图可得两种常用形式: 格式一: if ( <布尔表达式> ) <语句> 格式二: if ( <布尔表达式> ) <语句1> else <语句2> if(a==8) b=9; else { if(a==9) b=20; else { if(a==10) b=21; else b=30; } }
<语句> } switch语句 <整型表达式> default <语句> <整型常量表达式> case switch : ( ) { : 4.3.4 选择语句 2 开关语句
例 4.1 编程统计输入流中字符A的数目,字符A与a的数目,输入字符总数。 #include "iostream.h" void main() { int nA(0), nAa(0), nTotal(0); for( ; ; ) { char c; cout<<"Please enter a character! "; cin>>c; switch( c ) { case '\033': //Enter ESC to terminate goto Termination; case 'A': nA++; case 'a': nAa++; default : nTotal++; } } Termination : cout<<"The total number of 'A' is "<<nA<<endl; cout<<"The total number of 'A' and 'a' is "<<nAa<<endl; cout<<"The total number of characters is "<<nTotal<<endl; }
4.3.4 选择语句 例 4.2 编写程序统计输入流中-1、0和+1的个数。 #include "iostream.h" void main() { int nNegtive(0), nZero(0), nPositive(0); for( ; ; ) { int i; cout<<"Please enter a integer! "; cin>>i; switch( i ) { case -1: nNegtive ++; break; case 0 : nZero ++; break; case 1 : nPositive ++; break; case 100 : goto Termination; default : cout<<"Illegal integer!"<<endl; } } Termination : cout<<"The total number of -1 is " <<nNegtive<<endl; cout<<"The total number of 0 is " <<nZero<<endl; cout<<"The total number of 1 is " <<nPositive<<endl; } 2 开关语句
for语句 <表达式1> <表达式2> <语句> <表达式3> 计算<表达式1> 计算<表达式3> for true 计算<表达式2> 执行<语句> false 退出循环 ) ; ; ( 4.3.5 循环语句 1. for 语句 例 4.3 用for循环计算自然数1~10之和。 #include <iostream.h> void main( ) { int nSum(0); for(int i=1; i<=10; i++) nSum+=i; //1到10循环 cout<<"The sum is "<<nSum<<endl; //显示结果 }
while句 while 语句 <表达式> true 执行<语句> 计算<表达式> false 退出循环 ( ) 4.3.5 循环语句 2. while语句 例4.4 用while循环计算自然 数1~10之和。 #include <iostream.h> void main() { int i(0), nSum(0); while(i<=10) //1到10循环 { nSum+=i; i++; } cout<<"The sum is "<<nSum<<endl; }
执行<语句> true 计算<表达式> false 退出循环 do语句 <表达式> <语句> while do ( ) 4.3.5 循环语句 3. do 语句 [例4.6] 用do循环计算自然数1~10之和。 #include <iostream.h> void main() { int i(0), nSum(0); do { nSum+=i; } while(++i<=10); //1到10循环 cout<<"The sum is "<<nSum<<endl; //显示结果 }
4.3.5 循环语句 循环中的初始化表达式、条件表达示等可以是一些复杂的表达式,甚至包括循环变量的声明也可能出现在循环中,下面所列为循环的一些用法,学习循环时可以借鉴: 4. 复杂条件循环 for(int i=0; i<10; i++) for(; *lpsz != '\0' && _istdigit(*lpsz); lpsz = _tcsinc(lpsz)) for(; nCount--; ++pElements) for(; nCount--; ++pDest, ++pSrc) for(; hWndChild != NULL; hWndChild=::GetNext(hWnd, GW_HWND)) while((dwResult = RegEnumKey(hCurrentKey, 0, szSubKeyName, 255)) while((pWndT = pWndDlg->GetNextDlgGroupItem(pWndStart)) != NULL)
4.3.5 循环语句 例4.7 已知a为5×4阶矩阵,b为4×6阶矩阵, 编程求这样两个矩阵的乘积矩阵,将 结果输出在屏幕上。 #include <iostream.h> #include "string.h" void main() { int i, j, k; int a[5][4], b[4][6], c[5][6]; memset(c, 0, sizeof(int)*5*6); // Initialize c //Followings for entering the elements of matrix a for(i=0; i<5; i++) for(j=0; j<4; j++) { cout<<"a["<<i<<", "<<j<<"]="; cin>>a[i][j]; } 5. 多重循环 a= b= 。
//Followings for inputing the elements of matrix b for(i=0; i<4; i++) for(j=0; j<6; j++) { cout<<"b["<<i<<", "<<j<<"]="; cin>>b[i][j]; } //Followings for calculating and outputing the elements of matrix c cout<<endl<<endl<<"The product matrix is:\t"<<endl; for(i=0; i<5; i++) { for(j=0; j<6; j++) { for(k=0; k<4; k++) c[i][j]+=a[i][k]*b[k][j]; cout<<c[i][j]<<"\t"; } cout<<endl; } }
4.3.6 直接顺序控制 2. break 语句 3. continue 语句 1. goto 语句 #include <iostream.h> void main() { int nCount(0); int nCtrl(0); MyLabel: nCtrl++; nCount+=nCtrl; if( nCtrl<10 ) goto MyLabel; cout << " The sum is " << nCount <<endl; } while(cin>>i) { if(i==8) break; } cout<<i; int n(0); for(int i=0; i<=100; i++) { if(i%2==0) continue; n+=i; }
4.4 预处理指令 预处理指令不是程序运行时刻的有效操作,而是用以指示编译器在对源代码编译之前进行必要的预处理。 C++的所有预处理指令都以 # 开始,除了注释外,每条预处理指令占用单独的一行,同一行不能有其它预处理指令和C++语句,而且与C++语句不同,预处理指令不以分号结束。 预处理指令(亦称编译指令)不是语言的一部分,但实际上几乎C++、Java等语言的任何程序都离不开它,它为编程者提供了控制编译器行为的手段,扩展了编程环境的使用范围,在程序组织和管理上给编程者带来方便。 4.4.1 文件包含指令 4.4.2 宏定义指令 4.4.3 条件编译指令*
4.4.1 文件包含指令 #include <filename> 或 #include "filename" 首先按调用编译器时行命令中所指示的路径查找,然后按语言环境所设置的默认include目录去查找 文件包含指令(嵌入指令或include指令),格式: 例如: #include 〈c:\user\WangMing\Firt\common.h〉 #include "c:\user\WangMing\Firt\common.h " 注意: 由于预处理指令不是C++指令,因此上述表示路径的反斜杠 只用一个反斜杠。如果在C++程序中使用字符串表示路径, 则这个字符串中必须用双斜杠。例如: char FileName="c:\\user\\WangMing\\Firt\\common.h"; 预处理器首先在含有该条include语句的文件所在目录中查找,然后在所有包含该文件的文件所在的目录中查找,再按调用编译器时行命令中所指示的路径查找,最后按语言环境所设置的默认include目录去查找。
4.4.2 宏定义指令 宏定义是高级语言编译器提供的常用预处理指令,其目的是使用某一标识符标识某个文本字符串,分为无参数宏及有参数宏两类,格式如下: #define <MacroName> <CharString> 或 #define <MacroName>(<arglist>)<CharString> 使用方法示例如下: #define PI 3.1415926 #define max(a, b) \ ((a)>(b))?(a):(b); void main() { int nRadius=3.0; int nArea=nRadius*nRadius*PI; }
4.4.2 宏定义指令 #define max(a, b) (a>b)? a : b; int kk=2+max(1, 2); 宏的不安全性 #define PI 3.1415926 #define max(a, b) \ ((a)>(b))?(a):(b); void main() { int nRadius=3.0; int nArea=nRadius*nRadius*PI; }
4.4.2 宏定义指令 宏定义是高级语言编译器提供的常用预处理指令,其目的是使用某一标识符标识某个文本字符串,分为无参数宏及有参数宏两类,格式如下: #define <MacroName> <CharString> 或 #define <MacroName>(<arglist>)<CharString> 使用方法示例如下: #define PI 3.1415926 #define max(a, b) \ ((a)>(b))?(a):(b); void main() { int nRadius=3.0; int nArea=nRadius*nRadius*PI; }
4.4.2 宏定义指令 Visual C++为带参数宏定义提供了三个常用运算符:#、#@、## #define PrintString(a) #a " John" //注意此处John前有一个空格 cout<<PrintString( My name is ); //参数两侧的空格将被忽略 展开后: cout<<"My name is John"; 字符串化运算符 # 将右操作数变为字符串 字符化运算符 #@ 将右操作数变为字符 #define makechar(x) #@x a = makechar(b); 展开后: a = 'b'; 标识粘接运算符 ## 将两个标识(Token)粘接形成一个新标识 #define paster( n ) printf( "token" #n " = %d", token##n ) int token9 = 9; paster( 9 ); 展开后: printf( "token9 = %d", token9 );
4.4.3 条件编译指令* 高级语言通常都提供控制编译器执行流程的指令—条件编译指令。C++的编译器支持的条件编译指令为#if、#else、#elif、#endif,其语义与C++语言的if等语句相类似,使用方法也相近(注意这里多了一个#endif),可以参见if语句的用法。 常与这几个指令一起应用的是一个类似于函数的运算符defined(),其使用方法是defined(标识符),如果括号内标识符目前是定义的,则该表达式的值非0,否则为0。 #if defined(__CHINESE) cout<<"本程序用汉字进行提示"<<endl; #else cout<<"Prompt in English in this programm"<<endl; #endif