选择控制结构

来源:互联网 发布:l-sql语句like约束 编辑:程序博客网 时间:2024/04/29 01:14

                        第五章 选择控制结构

1.沃思提出“数据结构+算法=程序”只在面向过程的语言(如C语言)成立

2.算法的正确性衡量方法:

 1)有穷性 2)确定性 3)有效性 4)允许没有输入或者有多个输入 5)必须有一个或者多个输出

3.算法的描述方法:

 1)自然语言描述 2)流程图描述 3)NS结构化流程图描述 4)伪码描述

4.关系表达式:用作判断条件,结果只有真和假,(n%2!=0)等价于(n%2),0表示假,非0表示真

5.分支结构:当条件P成立时,执行A操作,否则执行B操作;如果B操作为空,即为单分支结构;

如果B操作不为空,即为双分支结构;如果B操作中又包含另一选择结构,则构成多分支选择结构;

6.单分支例题:计算输出两整数最大值

单分支(一般形式)if(表达式P) 语句A

#include<stdio.h>

void main()

{

int a,b,max;

printf("Enter a,b:");

scanf("%d%d",&a,&b);

if(a>b)           //单分支:if(表达式P) 语句A

max=a;        

if(a<=b)          //单分支:if(表达式P) 语句A

max=b;

printf("max=%d\n",max);

}

7.双分支例题:计算输出两整数最大值

双分支(一般形式):if(表达式P) 语句1

                 else 语句2

#include<stdio.h>

void main()

{

int a,b,max;

printf("Enter a,b:");

scanf("%d%d",&a,&b);

if(a>b)         

max=a;        

else              

max=b;

printf("max=%d\n",max);

}

8.条件运算符是C语言中唯一的三元运算符,需要三个操作数

9.条件运算符例题:计算输出两整数最大值

条件运算符(一般形式):表达式1?表达式2:表达式3

含义:若表达式1为非0,则结果为表达式2的值,否则是表达式3的值

#include<stdio.h>

void main()

{

int a,b,max;

printf("Enter a,b:");

scanf("%d%d",&a,&b);

max=a>b?a:b;  

printf("max=%d\n",max);

}

10.多分支控制条件语句(一般形式)

    if(表达式1) 语句

else if(表达式2) 语句2

...

else if(表达式m) 语句m

else  语句m+1

11.条件语句在语法上只允许每个条件分支中带一条语句,而要在分支里处理多条语句

就要使用花括号,构成复合语句

12.随机数的使用方法:

   1) 符号常量RAND_MAX在头文件#include<stdlib.h>中定义,标准C规定RAND_MAX不大于双字节整数的最大值32767

   2)随机函数rand()产生的是一个在0~RAND_MAX之间的整数,[0,32767]之间的整数

   3) 利用求余运算rand()%b可将函数rand()生成的随机数变化到[0,b-1]

   4) 利用rand()%b+a可将随机数的取值范围平移到[a,a+b-1]

   例:产生1~100的随机数: rand()%100+1

13.例题:猜数游戏:计算机想一个数,人猜对了提示Right!,否则提示Wrong!,并告诉大小

#include<stdio.h>

#include<stdlib.h>

void main()

{

int magic,guess;

magic=rand();                    //随机数

printf("Please guess a number:");

scanf("%d",&guess);

if(guess>magic)                  //多分支 

{

printf("Wrong!Too big!\n");  //复合语句

}

else if(guess<magic)

{

printf("Wrong!Too small!\n");

}

else{

printf("Right!\n");

    printf("The number is:%d\n",magic);

}

}

14.switch语句:用于多路选择,一般情况大于三种,用开关语句代替条件语句

   1) switch语句(一般形式)

      switch(表达式)

      {

         case 常量1

            可执行语句序列1   //注意:语句序列不使用花括号

     case 常量2:

            可执行语句序列2

     ........

     case 常量n:

            可执行语句序列

     default:

            可执行语句序列n+1

   }

2) switch语句相当于一系列的if-else语句

3switch后圆括号内的表达式只能是char型或int

4)关键字case后接常量,类型与表达式类型一致,常量的值必须互不相同

5)常量与case中间至少有一个空格,常量后面是冒号

6case本身并没有条件判断的功能,若case后面的语句省略不写,则表示它与后续case执行相同的语句

7switch语句的执行过程:

       第一步,计算switch后表达式的值

   第二步,将表达式的值依次与case后的常量比较

   第三步,如果相等,执行case后的代码段,执行完毕,可使用break语句跳出switch语句

   如果没有break语句,不会再比较,程序将依次执行下面的case后的语句,直到遇到break或者switch}为止

15.例题:编程实现简单计算器功能

#include<stdio.h>

void main()

{

int data1,data2;

char op;

printf("Enter your expression:");

scanf("%d%c%d",&data1,&op,&data2);

switch(op)

{

case '+':

printf("%d+%d=%d\n",data1,data2,data1+data2);

break;

case '-':

printf("%d-%d=%d\n",data1,data2,data1-data2);

break;

case '*':

case 'x':

case 'X':

printf("%d*%d=%d\n",data1,data2,data1*data2);

break;

case '/':

if(0==data2)//也可写成data2==0,0==data2的好处:

{ //因为赋值表达式左值必须是变量,如果把==误写成=,会提示错误

printf("Division by zero!\n");

}

else{

printf("%d/%d=%d\n",data1,data2,data1/data2);

}

break;

default:

printf("Invalid operator!\n");

  //break;这句一般不需要,因为没有break就会依次执行下面的步骤直到break或者switch}

} //这里已经是switch}

}

16.例题:编程实现简单计算器功能,能进行浮点数运算,操作数与运算符之间可加入任意多个空格

#include<stdio.h>

#include<math.h>

void main()

{

float data1,data2;

char op;

printf("Enter your expression:");

scanf("%f %c%f",&data1,&op,&data2);

switch(op)

{

case '+':

printf("%f+%f=%f\n",data1,data2,data1+data2);

break;

case '-':

printf("%f-%f=%f\n",data1,data2,data1-data2);

break;

case '*':

case 'x':

case 'X':

printf("%f*%f=%f\n",data1,data2,data1*data2);

break;

case '/':

if(fabs(data2)<=1e-7)

printf("Division by zero!\n");

}

else{

printf("%f/%f=%f\n",data1,data2,data1/data2);

}

break;

default:

printf("Invalid operator!\n");

}

//内存中的浮点数所表示的精度是有限的,所以比较实型变量data20是否相等时,

不能像整型变量与0比较那样直接用相等关系运算符与0比较,而应使用如下方式判断

实型变量data2的值是否位于0附近的一个很小的区间内,即:if(fabs(data2)<=1e-7)

17.逻辑运算符和逻辑表达式

逻辑非:!,单目运算符,右结合优先级最高

逻辑与:&&,双目运算符,左结合,优先级较高

逻辑或:||,双目运算符,左结合,优先级较低

例:判断某一年year是否是闰年的条件:

    1) 能被4整除,但不能被100整除;

1)能被400整除

逻辑表达式:((year%4==0)&&(year%100!=0))||(year%400==0)

或:(year%4==0)&&(year%100!=0)||(year%400==0)

18.特别注意:在计算含有逻辑运算符(&&||)的表达式时,通常尽量使用最少的操作数来

确定表达式的值,这就意味着表达式中的某些操作数可能不会被计算。

例:if(a>1&&b++>2&&c--!=0)中,仅在条件表达式a>1为真时,才会计算后面的值

19.程序测试:

  1)程序测试只能证明程序有错,不能证明程序无错

  2)例:编程输入三角形三边长a,b,c,判断他们能否构成三角形,能构成什么三角形

#include<stdio.h>

#include<math.h>

#define EPS 1e-1

void main()

{

float a,b,c;

int flag=1;

printf("Enter a,b,c:");

scanf("%f,%f,%f",&a,&b,&c);

if(a+b>c&&b+c>a&&a+c>b)

{

if(fabs(a-b)<=EPS&&fabs(b-c)<=EPS&&fabs(c-a)<=EPS)

{

printf("等边");

flag=0;

}

else if(fabs(a-b)<=EPS||fabs(b-c)<=EPS||fabs(c-a)<=EPS)

{

printf("等腰");

flag=0;

}

if(fabs(a*a+b*b-c*c)<=EPS||fabs(b*b+c*c-a*a)<=EPS||fabs(a*a+c*c-b*b)<=EPS)

{

printf("直角");

flag=0;

}

if(flag)

{

printf("一般");

}

printf("三角形\n");

}

else{

printf("不是三角形\n");

}

}

  3)例:编程将输入的百分制成绩转换为五分制成绩输出

#include<stdio.h>

void main()

{

int score,mark;

printf("Enter score:");

scanf("%d",&score);

if(score<0||score>100)

{

mark=-1;//这个if语句很重要,如果去掉,边界测试101~109-1~-9会出错

}

else{

mark=score/10;

}

switch(mark)

{

case 10:

case 9:

printf("%d-!\n",score);

break;

case 8:

printf("%d-!\n",score);

break;

case 7:

printf("%d-!\n",score);

break;

case 6:

printf("%d-及格!\n",score);

case 5:

case 4:

case 3:

case 2:

case 1:

case 0:

printf("%d-不及格!\n",score);

break;

default:

printf("Input error!\n");

}

20.对输入非法字符的检查与处理

  1)例:输入两个整型数,计算并输出两个整数的最大值

#include<stdio.h>

void main()

{

int a,b,max;

printf("Enter a,b:");

scanf("%d,%d",&a,&b);

max=a>b?a:b;

printf("max=%d\n",max);

}

//隐含问题:在Visual C++

1.如果输入3.2,1则输出3

2.如果输入1,3.2则输出3

3.如果输入q则输出-858993460

//解决办法:

#include<stdio.h>

void main()

{

int a,b,max,ret;

do{

printf("Enter a,b:");

ret=scanf("%d,%d",&a,&b);

if(ret!=2)//返回在遇到非法字符前已成功读入的数据项数

{

//但是scanf()函数不做类型检查,所以输入1,3.2会输出3

printf("Input error!\n");

while(getchar()!='\n');

}

else{

max=a>b?a:b;

printf("max=%d\n",max);

}

}while(ret!=2);

}

21.位运算符的使用

  1)位运算是对字节或字内的二进制数位进行测试、抽取、设置或移位等操作

  2) 位运算的操作对象只能是charint类型

  3) C语言中共有6种位运算符,只有按位取反是单目运算符,其他都是双目运算符

  4)关系运算和逻辑运算的结果要么是0,要么是1,而位运算结果可为任意值,但每一位都只能是01

  56种位运算符:

       按位取反  ~      用于加密处理,一次求反加密,二次求反解密

   左移位    <<

   右移位    >>

   按位与    &      用于对字节中某位清零

   按位异或  ^      

   按位或    |      用于对字节中某位置1

  6)按位取反  ~1=0~0=1  

  例:~5=-6

  ~  00000101

  ———————

     11111010  -6的补码

  7)按位与    0&0=0,0&1=0,1&1=1

  例:将15的最低位不变,其余位清零  15&1=1

     00001111

  &  00000001

  ——————

     00000001

  8)按位或    0|0=0,0|1=1,1|1=1 

  例:将15的最高位不变,其余位均置1  15|127=127

     00001111

  |  01111111

  ——————

     01111111 127的补码

  9)按位异或  0^0=0,0^1=1,1^1=0

  例:3^5=6

     00000011

  ^  00000101

   ——————

     00000110 6的补码

  10)左移位

      x<<n 表示把x的每一位向左平移n位,右边空位补0

  例:将15左移123位的二进制补码如下

     初始字节内容    00001111     对应十进制15

 左移1位字节内容 00011110     对应十进制30

 左移2位字节内容 00111100     对应十进制60

 左移3位字节内容 01111000     对应十进制120

  11)右移位

      x>>n 表示把x的每一位向右移n位,当x为有符号数时,左边空位补符号位值—算术移位

  当x为无符号位时,左边空位补0—逻辑移位

  例1:将15右移123位的二进制补码如下

     初始字节内容      00001111     对应十进制15

 右移1位字节内容   00000111     对应十进制7

 右左移2位字节内容 00000011     对应十进制3

 右移3位字节内容   00000001     对应十进制1

  例2:将-15右移123位的二进制补码如下

     初始字节内容      11110001     对应十进制-15

 右移1位字节内容   11111000     对应十进制-8

 右左移2位字节内容 11111100     对应十进制-4

 右移3位字节内容   11111110     对应十进制-2

  12) 无论左移位还是右移位,从一端移走的位不移入另一端,移走的位的信息就丢失了

  13)左移位和右移位可以分表代替整数的乘法和除法,左移n位相当于乘以2^n,右移n为相当于除以2^n

  14) 例:写出运行结果

#include<stdio.h>                            x  0000 0000 0000 1100

void main()                                 ~x  1111 1111 1111 0011

{                                         ~x反码1000 0000 0000 1100

int x=12,y=8;                     ~x反码加一1000 0000 0000 1101   -13

printf("%5d%5d%5d\n",!x,x||y,x&&y);

printf("%5u%5d%5d\n",~x,x|y,x&y);

printf("%5d%5d%5d\n",~x,x|y,x&y);

}

输出:    0   1   1 

        4294967283  12  8

        -13  12   8

 

  

    

0 0