语句是程序的基本语法成分。程序设计语言的语句按功能可以分成三类:
- 声明语句 指示编译器分配内存,或者提供程序连接信息
- 操作语句 描述对数据的处理
- 控制语句 用于控制程序的执行流程。
所有程序都只能包含三种控制结构:
顺序结构、选择结构和循环结构
本章讨论C++的选择结构语句和循环结构语句及其应用。
2.1 选择控制
2.1.1 if语句
1.if 语句的形式和执行流程
- if( 表达式 )语句 ;
首先计算表达式的值,如果值为true(非0),则执行语句;否则,即表达式值为false(0),视语句为空,转向执行后续语句。
例:
:
int a=7,b=3
max = a ;
if ( b > a)//此处视为空
max = b ;
cout << "max = " << max << endl;
:
- if( 表达式 ) 语句1 ;
else 语句2 ;
执行流程如下图
//例:
:
int a=8,b=16;
if ( b > a )
max = b ;
else max = a ;
cout << "max = " << max << endl;
:
执行结果为 max=16;
2.if 语句的嵌套
-
if 语句中的执行语句如果又是另一个if语句,称为嵌套if语句
-
if 与 else 的配对关系:C++规定,else 总是与它接近的if 配对
-
使用复合语句,可以改变条件语句的执行流程
例1:一道简单题解决if嵌套问题。 编写程序计算货物运费。设货物运费每吨单价 p(元)与运输 距离 s(公里)之间有如下关系:
程序提供如下:
#include <iostream>
#include<iomanip>
using namespace std ;
int main()
{ double t , p , w , s ;
cout << "Please input weight( ton ) : " ;
cin >> w ;
cout << " Please input distsnce( kilometre ) : " ;
cin >> s ;
if ( s < 100 ) p = 30 ;
else if ( s < 200 ) p = 27.5 ;
else if ( s < 300 ) p = 25 ;
else if ( s < 400 ) p = 22.5 ;
else p = 20 ;
t = p * w * s ;
cout << " The cost is: " << setprecision(2) << t << '$' << endl ;
}
例2: 输入三个整数,按从小到大顺序输出。
解法一
数据排序。先找出最小值,放在a中,然后找次小值,放在 b中:
1. 对 a、b进行比较,把小值放于 a ; if a > b a <=>b // a < b
2. 对 a 、c 进行比较,把小值放于 a ; if a > c a<=> c // a < c , a <b
3. 对 b 、c 进行比较,把 小值放于 b ; if b > c b <=> c // a<b && b < c
4. 输出 a, b, c 的值。
# include <iostream>
using namespace std ;
int main()
{ int a, b, c, t ;
cout << " Please input three integer numbers: " ;
cin >> a >> b >> c ;
if ( a > b )
{ t = a ; a = b ; b = t ; }
if ( a > c )
{ t = a ; a = c ; c = t ; }
if ( b > c )
{ t = b ; b = c ; c = t ; }
cout << a << " " << b << " " << c << endl;
}
解法二 改变输出顺序:
3 个数的 6 种可能排列方式:
a < b < c a < b && b < c
a < c < b a < c && c < b
b < a < c b < a && a < c
b < c < a b < c && c < a
c < a < b c < a && a < b
c < b < a c < b && b < a
最坏情况要做
8个关系运算和 3个逻辑运算
最好情况要做
2个关系运算和 1个逻辑运算
程序如下:
# include <iostream>
using namespace std ;
int main()
{ int a, b, c ;
cout << " Please input three integer numbers: " ;
cin >> a >> b >> c ;
if ( a < b )
if ( b < c ) cout << a << b << c << endl ;
else if ( a< c ) cout << a << c << b << endl ;
else cout << c << a << b << endl;
else if ( a < c ) cout << b << a << c << endl ;
else if ( b < c ) cout << b << c << a << endl ;
else cout << c << b << a << endl ;
}
例3:经典问题,求一元二次方程ax^2 + bx + c = 0的根。
#include <iostream>
#include <cmath>
using namespace std ;
int main()
{ double a, b, c, d, x1, x2, rp, ip ;
cout << "a, b, c = " ; cin >> a >> b >> c ;
if ( fabs( a ) <= 1e-8 )
cout << " It is not quadratic." << endl ;
else { d = b * b - 4 * a * c ;
if ( fabs( d ) <= 1e-8 )
cout << "It has two equal real roots: " << -b / ( 2*a ) << endl ;
else if ( d > 1e-8 )
{ x1 = ( -b + sqrt( d ) ) / ( 2*a ) ; x2 = ( -b - sqrt( d ) ) / ( 2*a ) ;
cout <<"It has two distinct real roots: "<<x1<<" and "<<x2<<endl ;
}
else { rp = -b / ( 2*a ) ; ip = sqrt( -d ) / ( 2*a ) ;
cout << "It has two complex roots: " << endl ;
cout << rp << " + " << ip << "i" << endl ;
cout << rp << " - " << ip << "i" << endl ;
}
}
}
结果如下:
2.1.2 switch语句
一般形式 :
switch ( 表达式 )
{ case 常量表达式 1 : 语句 1
case 常量表达式 2 : 语句 2 …
case 常量表达式 n : 语句 n
default : 语句 n+1
}
注:
-
表达式类型为非浮点型
-
各常量表达式类型要与之匹配
-
各常量表达式要求各不相等
-
default 子句可选。缺省时,没有
-
匹配值 switch 语句为空
例1:
根据考试成绩的等级打印出百分制分数段。
# include <iostream>
using namespace std ;
int main ()
{ char grade ;
cout << " Input grade of score (a_d) : " << endl ;
cin >> grade ;
switch ( grade )
{ case 'a' : cout << " 85__100 \n " ;
case 'b' : cout << " 70__84 \n " ;
case 'c' : cout << " 60__69 \n " ;
case 'd' : cout << " < 60 \n " ;
default : cout << " error \n " ;
}
}
我们会发现如果输入的是a的话,输出会是:
为什么是这样呢?
因为没有加跳出switch语句的break语句。
# include <iostream>
using namespace std ;
int main ()
{ char grade ;
cout << " Input grade of score (a_d) : " << endl ;
cin >> grade ;
switch ( grade )
{ case 'a' : cout << " 85__100 \n " ;break;
case 'b' : cout << " 70__84 \n " ;break;
case 'c' : cout << " 60__69 \n " ;break;
case 'd' : cout << " < 60 \n " ;break;
default : cout << " error \n " ;
}
}
加上就能正确的进行选择啦!
接下来让我们看看switch的另外的使用形式。
例2:
根据考试成绩的等级打印出百分制分数,允许输入大写或小写字母。
# include <iostream>
using namespace std ;
int main ()
{ char grade ;
cout << " Input grade of score (a_d or A__D) : " << endl ;
cin >> grade ;
switch ( grade )
{ case 'a' :
case 'A' : cout << " 85__100 \n " ; break ;
case 'b' :
case 'B' : cout << " 70__84 \n " ; break ;
case 'c' :
case 'C' : cout << " 60__69 \n " ; break ;
case 'd' :
case 'D' : cout << " <60 \n " ; break ;
default : cout << " error \n " ;
}
}
这就是switch的case共用。
这里给一个以switch语句写的计算器。
#include <iostream>
using namespace std;
int main(){
double operand1,operandl,result;
char oper;
cout<<"输入算式:"<<;
cin>>operand1>>oper>>operand2;
switch(oper){
case '+':result=operand1+operand2;break;
case '-':result=operand1-operand2;break;
case '*':result=operand1*operand2;break;
case '/':result=operand1/operand2;break;
default:cout<<"input error!"<<endl;
goto L;
}
cout<<operand1<<oper<<operand2<<"="<<result<<endl;
L:;
}
switch 结构嵌套
嵌套结构的 case 标号与外层无关
switch ( i )
{ case 1 : ......
case 2 :
switch ( j )
{ case 1 : ......
case 2 : ......
......
}
case 3 : ......
}
这里有一个if语句和switch语句的比较。其实很容易。
if 语句 switch 语句
形成分支控制流程 不形成程序控制流程
用于复杂条件判断 表达式的值为数值集合时作多分支控制,可读性较好
2.2 循环控制
循环概念
为解决某一问题,或求取某一计算结果,特定的条件下,程序中反复地按某一模式进行操作。
最典型的就是求2的n次方。
2.2.1 while语句
语句形式:
while( 表达式 )循环体 ;
表达式为逻辑表达式,不管表达式形式如何,结果都作为逻辑值。
例:一个简单的求和问题
# include <iostream>
using namespace std ;
int main ()
{ int i = 1 , sum = 0 ;
while ( i <= 100 )
{
//sum+=i++;//可以写成这样,俩句和一句
sum = sum + i ;
i ++ ;
}
cout << " sum = " << sum << endl ;
}
这里给一个经典问题和一个经典解法。
例:求两个正整数 m 和 n 的最大公约数
辗转相除法:
- 当 m > n,m 与 n 的最大公约数等于 n 和 m%n 的最大公约数;
- 当 n = 0,m 和 n 的最大公约数等于 m 。
例如: - m = 24,n = 9
- 24 和 9 的最大公约数等于 ( 24 % 9 ) = 6 和 9 的最大公约数;
- 9 和 6 的最大公约数等于 ( 9 % 6 ) = 3 和 6 的最大公约数;
- 6 和 3 的最大公约数等于 ( 6 % 3 ) = 0 和 3 的最大公约数;
- 所以, 24 和 9 的最大公约数等于 3。
用伪代码表达一下:
a = m , b = n , r = b ;
while ( r != 0 )
{ 把 a%b 的值赋给 r ;
用 b 的值替换 a 的值 ;
用 r 的值替换 b 的值 ;
}
a 是最大公约数
真正的代码表示
#include <iostream>
using namespace std ;
int main()
{ int m , n , a , b , r ;
cout << "input two integers :\n" ;
cout << "? " ; cin >> m ;
cout << "? " ; cin >> n ;
if ( m > n) { a = m ; b = n ; }
else { a = n ; b = m ; }
r = b ;
while ( r != 0 )
{ r = a % b ;
a = b ;
b = r ;
}
cout << m << " and " << n << " maximal common divisor is : " << a << endl ;
}
这里给一个字符型的while控制。
例:
输入一串字符,以?结束,输出其中字母个数和数字个数。
#include<iostream>
using namespace std;
int main(){
int letters=0,nums=0;
char ch;
cin.get(ch);
while(ch!='?')
{
if(ch>='a' && ch<='z'|| ch>='A' && ch<='Z')++letters;
else if(ch>='0'&& ch<='9')++nums;
cin.get(ch);
}
cout<<"字母有:"<<letters<<"个"<<'\n';
cout<<"数字有:"<<nums<<"个"<<endl;
}
cin.get(ch)的作用是获取一个当前输入字符并写入变量ch中。iostream的get函数能够接收任何字符,包括空格、回车等。这与采用cin>>不同。cin>>会自动把空格和控制符作为输入界符,结束一个变量的输入。
2.2.2 do_while语句
语句形式:
do 循环体 while( 表达式 );
例:还是那个求和问题。这回是用do-while使用。
# include <iostream>
using namespace std ;
int main ()
{ int i = 1 , sum = 0 ;
do
{ sum += i ;
i ++ ;
} while ( i <= 100 ) ;
cout << " sum = " << sum << endl ;
}
在一般情况下,while语句和do-while语句可以互相交换使用。
例:
#include<iostream>
#include<cmath>
using namespace std ;
int main()
{ double s = 0, x = 1, pi ; long k = 1; int sign = 1 ;
do
{ s += x ;//累加当前项
k += 2 ;//后项分母
sign = -sign ;//变号
x = sign / double(k);//求后项
} while ( fabs (x) >1e-8 ) ; //精度判断
pi = s * 4 ; //求π
cout << " pi = " << pi << endl ;
}
其实do里面的函数内容可以利用通项描述叠加:
s += x ;
k ++ ;
sign = -sign ;
x = double( sign ) / ( 2 * k-1 ) ;
2.2.3 for语句
语句形式
for ( 表达式1; 表达式2 ; 表达式3 )
循环体 ;
还是求和问题。
# include <iostream>
using namespace std ;
int main ()
{ int i , sum = 0 ;
for ( i =1 ; i <= 100 ; i ++ )
sum + = i ;
cout << " sum = " << sum << endl ;
}
对于求和的for循环来说有这么几种表达方法:
不同形式的 for 语句结构
-
(1) i =1 ; //缺省表达式1 for ( ; i <= n ; i ++ ) { sum = sum + i ; }
-
(2) for ( i =1; ; i ++ ) { sum = sum + i ; if (i > n) break ;//缺省表达式2 }
-
(3) for ( i =1; i <= n ; ) { sum = sum + i ; i + + ; //缺省表达式3 }
-
(4) for( i =1; i <= n ; sum + = i + + ) ; //缺省循环体
-
(5) for( i =1; sum + = i + + , i <= n ; ) ; //缺省表达式3和循环体
-
(6) i = 1; for ( ; ; ) { sum + = i + + ; if ( i > n ) break ; } //缺省全部 for 的表达式
这里给一个经典问题:求菲波那契数列的前 n 项 .
Fibonacci 数列:0,1,1,2,3,5,8,13,21,34,……
f0 = 0 f1 = 1 fn = fn-1 +
fn-2 ( n >= 2 )
#include <iostream>
using namespace std ;
int main()
{ int n, i, a0, a1 ;
cout << "n = " ;
cin >> n ;
a0 = 0 ; a1 = 1 ;
cout << a0 << " "<< a1 << " ";
for ( i = 2; i <= n/2 ; i ++ )
{ a0 = a0 + a1 ;
a1 = a1 + a0 ;
cout << a0 << " "<< a1 << " ";
if ( i % 5 == 0 ) cout << endl ;
}
if ( n > (i-1)*2 ) cout << a0+a1 << endl ;
}
2.2.4 循环的嵌套
- 一个循环语句的循环体内又包含循环语句,称为嵌套循环
- 各种循环语句都可以互相嵌套
这里给一个经典问题:判定素数。
#include <iostream>
#include <cmath>
using namespace std ;
int main()
{ int i ;
long m;
cout <<"Please input a number:\n";
cin >> m ;
double sqrtm = sqrt( m ) ; //函数sqrt是double类型
for ( i =2; i <= sqrtm ; i ++ )
if ( m% i == 0 ) break ;
if ( sqrtm < i )
cout <<m<<" is prime."<<endl ;
else
cout << m << " is not prime." <<endl ;
}
根据上面这个我们再给出求范围内的素数问题。
#include< iostream >
#include< cmath >
using namespace std ;
int main()
{ long m ; int i, k = 0 ;
for( m = 101; m <= 200 ; m += 2 )
{ double sqrtm = sqrt( double(m) ) ;
for( i = 2 ; i <= sqrtm ; i ++ )
if( m % i == 0 ) break ;
if( sqrtm < i )
{ cout << m << " " ;
k ++ ;
if( k%10 == 0 ) cout << endl ; // 每行输出个数据
}
}
cout << endl ;
}
2.3 判断表达式的使用
- C++没有逻辑数据类型
- 表达式的值等于非0,是逻辑真;表达式的值等于0,是逻辑假
- 所有的表达式都可以作为判断(逻辑)表达式
所以-
算术表达式用于判断
if(expression != 0) ==>if(ecpression) if(expression = 0) ==>if(!expression)
-
赋值表达式用于判断
if ( c = a - b )==> c=a-b; if(c!=0)
-
对输入作判断
while ( cin >> x )//输入CTRL+Z结束 n ++ , s += x ; cout << "n = " << n << endl << "sum = " << s << endl ;
-
2.4 转向语句
-
break语句
无条件地结束switch语句,或循环语句,转向执行语句块的后续语句
-
continue语句
用于循环体中,终止当前一次循环
-
goto语句
无条件转向语句,与标号语句配合使用,一般形式为: goto 标号 ; 标号 : 语句 ;
break和continue比较如下:
小结
- C++构成选择结构的条件语句有if语句和switch语句。
- if 语句适用于条件判断比较复杂的分支结构。嵌套if语句采用就近匹配的原则。
- 用括号{ }改变复合语句结构,可以改变if与else的匹配关系。
- switch语句根据一个表达式的不同可能值决定选择执行,适用于条件判断比 较简单的多路选择。
- 循环结构有whlie语句、do_while 语句和 for 语句。
- while语句和do_while语句主要用于条件循环。
- for语句是C++中很灵活的循环语句,既可以用于控制次数循环,也可以用于条件循环。
- 转向语句是程序的流程控制的补充机制。
- C++的转向语句主要有:break、
continue和goto语句。
- C++的转向语句主要有:break、