循环控制结构

时间:2022-09-08 18:30:15

                      第六章  循环控制结构

1.循环:包括计数控制的循环和条件控制的循环

2.结构化程序设计的三种基本结构:顺序结构、选择结构、循环结构

3.循环结构的类型:

   1)当型循环结构:for语句(适合循环次数已知,计数控制的循环)

   2)直到型循环结构:while语句、do-while语句(适合循环次数未知,条件控制的循环)

4.while语句

   1)一般形式为:

while(循环控制表达式)

{               |

语句系列    |循环体

}               |

   2)循环控制表达式在执行循环体之前测试

   3)执行过程:

     计算循环控制表达式的值

 如果循环控制表达式的值为真,那么执行循环体中的语句,并返回步骤1

 如果循环控制表达式的值为假,就退出循环,执行循环体后面的语句

5.do-while语句

   1)一般形式为:

do

{               |

语句系列    |循环体

}while(循环控制表达式);              

   2)循环控制表达式在执行循环体之后测试

   3)执行过程:

     执行循环体中的语句

     计算循环控制表达式的值

 如果循环控制表达式的值为真,那么返回步骤1

 如果循环控制表达式的值为假,就退出循环,执行循环体后面的语句

6.for语句

   1)一般形式为:

for(初始化表达式;循环控制表达式;增值表达式)

{               |

语句系列    |循环体

}               |

   2) 在每次循环体被执行之前,都要对循环控制条件测试一次,每次循环体执行完以后都要执行一次增值表达式

   3)初始化表达式作用:循环变量初始化,即赋初值

   4)循环控制表达式:是控制继续执行的条件,当表达式的值为非0时重复执行循环

   5)增值表达式作用:每执行一次循环,循环控制变量增值

   6for语句三个表达式之间用分号分隔,有且只能有两个分号

   7)循环控制表达式若省略,表示循环条件为永真

   8)初始化表达式和增值表达式都可省略,但是必须有其他语句反应其作用

7.例:从键盘输入n,然后计算输出1+2+3+……n的值

  1while语句编程实现

#include<stdio.h>

void main()

{

int i=1,n,sum=0;//sum一定要初始化,不然会是随机值

printf("Enter n:");

scanf("%d",&n);

while(i<=n)

{

sum+=i;

i++;

}

printf("1+2+3+……+%d=%d\n",n,sum);

}

  2do-while语句编程实现

#include<stdio.h>

void main()

{

int i=0,n,sum=0;

printf("Enter n:");

scanf("%d",&n);

do

{

sum+=i;

i++;

}while(i<=n);

printf("1+2+3+……+%d=%d\n",n,sum);

}

  3for语句编程实现

#include<stdio.h>

void main()

{

int i=1,n,sum=0;

printf("Enter n:");

scanf("%d",&n);

for(i=1;i<=n;i++)

{

sum+=i;

}

printf("1+2+3+……+%d=%d\n",n,sum);

}

8.逗号运算符

  1)所有运算符中优先级最低,左结合

  2)作用:可实现对各个表达式的顺序求值

  3)结果:将最后一个表达式的值作为整个逗号表达式的值

  4)例:从键盘输入n,然后计算输出1+2+3+……n的值

#include<stdio.h>

void main()

{

int i,j,n,sum=0;

printf("Enter n:");

scanf("%d",&n);

for(i=1,j=n;i<=j;i++,j--)

{

sum+=i+j;

}

printf("1+2+3+……+%d=%d\n",n,sum);

}

9.空语句

  1)仅由一个分号构成的语句

  2)作用:什么也不做,只起延时作用

  3)例:for(i=1;i<50000000;i++)

{   

;                           

}

for(i=1;i<50000000;i++)

{

    

}

for(i=1;i<50000000;i++)

 

for(i=1;i<=n;i++);

{

sum+=i;

}

等价于

for(i=1;i<=n;i++)

{

;

}

sum+=i;

   4) 例:从键盘输入n,然后计算输出1+2+3+……n的值

#include<stdio.h>

void main()

{

int i,j,n,sum=0;

printf("Enter n:");

scanf("%d",&n);

for(i=1,j=n;i<=j;i++,j--);

{

sum+=i+j;

}

printf("1+2+3+……+%d=%d\n",n,sum);

}//输出结果:101

10.死循环

   1while语句行末加分号将导致死循环

   2)例:i=1;

 

         while(i<=n);//行末加分号导致死循环

 {           

 sum+=i;

 i++;

 }

  相当于

 i=1;

     while(i<=n)//当输入大于1n值,循环体中没有语句可以改变控制变量i

 {          //使得循环条件为永真,导致死循环

 ;

 }

 sum+=i;

 i++;

11.while语句和do-while语句的区别

   1while先判断后执行,有可能一次都不执行,do-while先执行后判断,至少执行一次

   2)例:n=101;                       n=101;

          while(n<100)                 do

  {                            {

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

  n++;                         n++;

  }                             }while(n<100);

      //循环一次也不执行           //结果:输出n=101,循环执行一次

   3)例:分别用whiledo-while语句编程,输入一组数据,然后显示每次输入数据进行累加运算的结果,输入0结束

do-while语句实现:

#include<stdio.h>

void main()

{

int num,sum=0;

do{

printf("Enter num:");

scanf("%d",&num);

sum+=num;

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

}while(num!=0);

}

while语句实现

#include<stdio.h>

void main()

{

int num=1,sum=0;//num赋任意非0值都可以

while(num!=0)

{

printf("Enter num:");

scanf("%d",&num);

sum+=num;

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

}

}

12.计数控制的循环:循环次数事先已知的循环

  1)例1:编写一个程序,从键盘输入n,计算输出n!

#include<stdio.h>

void main()

{

int i,n,sum=1;

printf("Enter n:");

scanf("%d",&n);

for(i=1;i<=n;i++)

{

sum*=i;

}

printf("%d!=%ld\n",n,sum);

}

  2)例2:编写一个程序,从键盘输入n,计算输出1!,2!……n!

#include<stdio.h>

void main()

{

int i,n,sum=1;

printf("Enter n:");

scanf("%d",&n)

for(i=1;i<=n;i++)

{

sum*=i;

printf("%2d!=%ld\n",i,sum);

}

}

  3)例:键盘输入n,编程计算1!+2!+3!+……+n!

#include<stdio.h>

void main()

{

int term=1,sum=0,i,n;

printf("Enter n:");

scanf("%d",&n);

for(i=1;i<=n;i++)

{

term*=i;

sum+=term;

}

printf("1!+2!+3!+……+%d!=%ld\n",n,sum);

}

13.条件控制的循环:循环次数事先未知,由条件控制

  1)例1:输入两个整型数,计算并输出两个整型数的最大值,如若输入非法字符,提示错误并重新输入

 //解释:非法字符,需要输入数字时,字符相对它来说就是非法字符,而需要输入字符型,数字对它不是非法字符,所有都是合法

#include<stdio.h>

void main()

{

int a,b,max,ret;

printf("Enter a,b:");

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

while(ret!=2)//判断数据个数或格式是否错误

{

while(getchar()!='\n');//清除缓冲区中的错误数据

printf("Enter a,b:");

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

}

max=a>b?a:b;

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

}

//注意:scanf()函数不做参数类型匹配检查,当输入1 3.2时,scanf返回2,不会导致重新输入

但是,此后的小数点仍留在缓冲区,如果此后还需输入内容,就要先清除缓冲区内容

  2)例2:先由计算机想一个1-100之间的数请人猜,若猜对,则计算机提示Right!结束

游戏,否则提示Wrong!,并告诉人是大是小,直到猜对为止,记录人猜的次数,反应猜数的水平

#include<stdio.h>

#include<stdlib.h>

void main()

{

int magic;

int guess;

int counter=0;

magic=rand()%100+1;

do{

printf("Please guess a magic number:");

scanf("%d",&guess);

counter++;

if(guess>magic)

{

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

}

else if(guess<magic)

{

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

}

else{

printf("Right!\n");

}

}while(guess!=magic);

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

}

14.随机数的使用

   a.随机数的产生:  rand()

 

   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]

 

   b.随机数的产生:  srand(time(NULL))

 

   1)用rand()直接产生的随机数只是一个伪随机数,反复调用产生的随机数序列是一样的,而且每次都只用第一个

   2)随机化:使程序每次运行时产生不同的随机数序列的过程

   3)随机化的实现:通过调用标准库函数srand()为函数rand()设置随机数种子来实现

   4)随机数种子的设置:

    法1:每次通过用户输入来完成随机化,srand(1),srand(2),srand(seed),输入seed

    法2:的通过函数time()读取计算机的时钟值,并把该值设置为随机数种子srand(time(NULL))

   5)函数time()返回以秒计算的当前时间值,即一个代表时间的字符串,使用NULL作为time()的参数时,

     time(NULL)的返回值被转换成一个无符号整数,可作为随机数发生器的种子

   6)使用time()函数时,必须在程序开头将头文件<time.h>包含到程序中

 

15.例:先由计算机想一个1-100之间的数请人猜,若猜对,则计算机提示Right!结束

   游戏,否则提示Wrong!,并告诉人是大是小,直到猜对为止,记录人猜的次数,反应猜数的水平

#include<stdio.h>

#include<stdlib.h>

#include<time.h>

void main()

{

int magic;

int guess;

int counter=0;

srand(time(NULL));

magic=rand()%100+1;

do{

printf("Please guess a magic number:");

scanf("%d",&guess);

counter++;

if(guess>magic)

{

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

}

else if(guess<magic)

{

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

}

else{

printf("Right!\n");

}

}while(guess!=magic);

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

}

16.例:先由计算机想一个1-100之间的数请人猜,若猜对,则计算机提示Right!屏幕输出多少次成功,

结束游戏,否则提示Wrong!,并告诉人是大是小,最多猜10次,超过就结束,要避免非法字符的输入

#include<stdio.h>

#include<stdlib.h>

#include<time.h>

void main()

{

int magic;

int guess;

int counter=0;

int ret;//保存scanf()函数的返回值

srand(time(NULL));

magic=rand()%100+1;

do{

printf("Please guess a magic number:");

ret=scanf("%d",&guess);

while(ret!=1)//若存在输入错误,则重新输入

{

while(getchar()!='\n');//清楚缓冲区中的内容

printf("Please guess a magic number:");

ret=scanf("%d",&guess);

}          //若存在非法字符,则重新输入

counter++;

if(guess>magic)

{

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

}

else if(guess<magic)

{

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

}

else{

printf("Right!\n");

}

}while(guess!=magic&&counter<10);

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

}

 

延伸拓展:先由计算机想一个1-100之间的数请人猜,若猜对,则计算机提示Right!屏幕输出多少次成功,

结束游戏,否则提示Wrong!,并告诉人是大是小,最多猜10次,超过就继续猜下一个数,每次运行程序,可

反复猜多个数,直到操作者想停时结束,要注意避免非法字符输入的问题

#include<stdio.h>

#include<stdlib.h>

#include<time.h>

void main()

{

int magic;

int guess;

int counter;

char reply;//保存用户输入的答案

int ret;//保存scanf()函数的返回值

srand(time(NULL));

do{

magic=rand()%100+1;

counter=0;

do{

printf("Please guess a magic number:");

ret=scanf("%d",&guess);

while(ret!=1)//若存在输入错误,则重新输入

{

while(getchar()!='\n');//清楚缓冲区中的内容

printf("Please guess a magic number:");

ret=scanf("%d",&guess);

}     //若存在非法字符,则重新输入

counter++;

if(guess>magic)

{

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

}

else if(guess<magic)

{

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

}

else{

printf("Right!\n");

}

}while(guess!=magic&&counter<10);

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

printf("Do you want to continue(Y/N or y/n)?");

scanf(" %c",&reply);//%c前有一个空格,读取缓冲区中的回车符

}while(reply=='Y'||reply=='y');

}

 

17.设计一个简单计算器,允许连续做多次算术运算

#include<stdio.h>

#include<math.h>

void main()

{

float data1,data2;

char op;

char reply;

do{

printf("Please enter your expression:\n");

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");

}

printf("Do you want to continue(Y/y or N/n)?");

scanf(" %c",&reply);//加空格清除缓冲区中的回车符

}

while(reply=='Y'||reply=='y');

}

18.嵌套循环

       一个循环语句放在另一个循环语句中构成的循环称为嵌套循环

  1) 嵌套循环的总循环次数等于外层循环次数和内层循环次数的乘积

  2)为避免造成混乱,嵌套循环的内层和外层的循环控制变量不要同名

  3)例:键盘输入n,编程计算1!+2!+3!+……+n!

#include<stdio.h>

void main()

{

int term,sum=0,i,j,n;

printf("Enter n:");

scanf("%d",&n);

for(i=1;i<=n;i++)

{

term=1;

for(j=1;j<=i;j++)

{

term*=j;

}

sum+=term;

}

printf("1!+2!+3!+……+%d!=%ld\n",n,sum);

}

19累加求和构成规律:

   1)当累加项较为复杂或者前后项之间无关时,需要单独计算每个累加项 

   2)当累加项前项与后项之间有关时,根据前项计算后项

#include<stdio.h>

void main()

{

int i,n;

long term=1,sum=0;

printf("Enter n:");

scanf("%d",&n);

for(i=1;i<=n;i++)

{

term=term*i;

sum=sum+term;

}

printf("1!+2!+3!+……%d=%ld\n",n,sum);

}

20.goto语句

  1)功能:使程序无条件跳转到语句标号所标识的语句去执行,所跳过的语句不再执行

  2)一般形式:

   ①向前跳转              ②向后跳转

          goto 语句标号;     语句标号:……()

      ……                        ……

  语句标号:…… ()                     goto 语句标号;

  3)应用:通常情况,goto语句与if语句联合使用

            if(表达式) goto语句标号;    语句标号:……

        ……                              ……

   语句标号:……                                 if(表达式) goto语句标号

21.break语句

  1)功能:①用于退出switch结构

           ②用于退出由while,do-whilefor语句构成的循环体

  2)原理:当执行循环体遇到break语句时,循环体将立即终止,从循环语句后的第一条语句开始继续执行

  3)应用:break语句通常与if联合使用,表明在任何条件下跳转到紧接循环语句后的第一条语句

22.continue语句

  1)功能:跳过continue后面尚未执行的语句,开始下一次循环,只结束本次循环,不终止整个循环

  2)例题:

#include<stdio.h>

void main()

{

int i,n;

for(i=1;i<=5;i++)

{

printf("Please enter n:");

scanf("%d",&n);

if(n<0) continue;

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

}

printf("Program is over!\n");

}

23.函数exit()

  1) 标准库函数exit()用于控制程序的流程,调用时,需要加头文件<stdlib.h>

  2)一般形式:exit(code);

  3)功能:终止整个程序的执行,强制返回操作系统,并将int型参数code的值传给调用进程

  (一般为操作系统),code的值为0或宏常量EXIT_FAILURE,表示程序出现某种错误后退出

24.goto,break,continue,exit()的比较

  1goto,break,continue,exit()都用于控制程序的流程,前三个是流程控制语言,exit()C标准函数

  1)功能:goto语句可以向任意方向跳转,break语句只限定流程跳转到循环语句之后

     的第一条语句,continue语句结束本次循环,exit()直接终止所有程序

  2break,goto语句和exit()函数都可用于终止整个循环的执行,continue不能终止整个循环

  3)在嵌套循环下,break语句和continue语句只对包含他们的最内层循环语句起作用,

     不能用break语句跳出多重循环,只能一层一层的跳出

  4)使用goto语句的两种特定情形:

     ①快速跳出多重循环

     ②跳向共同的出口位置,进行退出前的错误处理工作

25.例题:韩信点兵:x%5==1&&x%6==5&&x%7==4&&x%11==10

①穷举法(循环条件自定义,不具实际意义)

break退出循环(循环条件省略,满足条件结束循环)

exit(0)结束程序(循环条件省略,满足条件结束整个程序)

④使用标志变量(循环条件为标识变量为0,最佳方法)

#include<stdio.h>

void main()

{

int x;

int find=0;

for(x=1;!find;x++)

{

if(x%5==1&&x%6==5&&x%7==4&&x%11==10)

{

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

find=1;

}

}

}

26.类型溢出

  1)原因:当运算的结果超出了类型所能表示的数的上界,导致进位到达了最前面的符号

           位或者更多进位的丢失,就会发生类型溢出

  2)解决办法:采用取值范围更大的数据类型来定义变量

27.结构化程序设计的基本思想

  1)采用顺序、选择和循环三种基本结构作为程序设计的基本单元,语法结构具有4个特性

     ①只有一个入口

     ②只有一个出口

     ③无不可达语句,即不存在永远执行不到的语句

     ④无死循环,即不存在永远都执行不完的循环

  2)尽量避免使用goto语句,因为它破坏了结构化设计风格,并且容易带来错误的隐患

  3)采用自顶向下、逐步求精的模块化程序设计方法进行结构化程序设计