C++程序设计基础之(第2章)程序控制结构

语句是程序的基本语法成分。程序设计语言的语句按功能可以分成三类:
  • 声明语句 指示编译器分配内存,或者提供程序连接信息
  • 操作语句 描述对数据的处理
  • 控制语句 用于控制程序的执行流程。

所有程序都只能包含三种控制结构:
顺序结构、选择结构和循环结构

本章讨论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语句。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值