算法与程序设计基础_第1页
算法与程序设计基础_第2页
算法与程序设计基础_第3页
算法与程序设计基础_第4页
算法与程序设计基础_第5页
已阅读5页,还剩133页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

C语言程序设计(第3版)中国铁道出版社ChinaRailwayPublishingHouse普通高等教育“十一五”国家级规划教材主教材:C语言程序设计(第三版)

书号:ISBN978-7-113-09512-3

中国铁道出版社2009年2月第3版

配套教材:C语言程序设计实验教程

书号:ISBN978-7-113-09513-0

中国铁道出版社2009年2月第1版

作者电子邮箱:

Luojian116@126.com

wsjwhz@126.com3.1算法概述3.3结构化程序设计方法3.2算法的常用表示方法3.4C语句概述3.6循环结构程序设计

3.7综合程序应用举例3.5选择结构程序设计第3章算法与程序设计基础结束放映3.1算法概述程序(program)是计算机可以执行的指令或语句序列。它是用计算机解决现实生活中的一个实际问题而编制的。设计、编制、调试程序的过程称为程序设计。编写程序所用的语言即为程序设计语言,它为程序设计提供了一定的语法和语义,所编写出的程序必须严格遵守它的语法规则,这样编写出来的程序才能被计算机所接受、运行,并产生预期的结果。3.1.1算法的概念解决一个实际问题而采取的方法和步骤,称之为“算法”。对于同一个问题,可能有不同的方法和步骤,即有不同的算法。

【例3.1】求1+2+3+4+…+100=?算法1步骤1:1+2=3步骤2:3+3=6步骤3:6+4=10…步骤99:4950+100=5050算法2步骤1:0+100=100步骤2:1+99=100步骤3:2+98=100…步骤50:49+51=100步骤51:100*50=5000步骤52:5000+50=5050算法3步骤1:k=1,s=0步骤2:如果k>100,则算法结束,s即为所求的和,输出s;否则转向步骤3步骤3:s=s+k,k=k+1步骤4:转向步骤2当然,算法也有优劣之分,有的算法较简练,而有的算法较烦琐。上面三个算法中,算法2比算法1步骤少,算法3比算法2步骤少,算法3的质量最优。一般地说,希望采用方法简单、运算步骤少的方法。3.1.2算法的特性一个算法应具有如下五个特点:1.有穷性2.确定性3.可行性4.有零个或多个输入5.有一个或多个输出3.2算法的常用表示方法3.2.1自然语言表示法

所谓自然语言,就是人们日常使用的语言,可以是汉语、英语或其他语言。3.2.2流程图流程图是用图形的方式来表示算法,用一些几何图形来代表各种不同性质的操作。ANSI(美国国家标准化协会)规定的一些常用流程图符号(见图3-1)已被大多数国家接受。

1.顺序结构顺序结构的程序是按语句的书写顺序执行的,用图3-2表示2.选择结构选择结构或称分支结构、条件结构,用图3-3表示

3.循环结构循环结构又称重复结构,有两种方式:一种是先判断条件,若条件成立再进入循环体,可用图3-4表示;另一种是先进入循环体执行,再判断条件是否成立。可用图3-5表示。3.2.3N-S结构流程图1973年美国的计算机科学家I.Nassi和B.Shneiderman提出了一种新的流程图形式。在这种流程图中把流程线完全去掉了,全部算法写在一个矩形框内,在框内还可以包含其他框,即由一些基本的框组成一个较大的框。这种流程图称为N-S结构流程图(以两人名字的头一个字母组成)。3.2.4伪代码表示法伪代码(pseudocode)是用介于自然语言和计算机语言之间的文字和符号来表示算法,即计算机程序设计语言中具有的语句关键字用英文表示,其他的可用汉字,也可用英文,只要便于书写和阅读就可。3.2.5用计算机语言表示算法用计算机语言描述算法必须严格遵循所用语言的语法规则#include<stdio.h>voidmain(){

int

sign,i,n;floatsum;

printf("\nPleaseinputanintegerton:");

scanf("%d",&n);sign=1;sum=1;i=1;

while(i<=n){sign=(-1)*sign;sum=sum+sign/(3.0*i);i=i+1;}

printf("\nsum=%f",sum);}程序运行结果如下:

Pleaseinputanintegerton:5sum=0.7388893.3结构化程序设计方法在拿到一个需要求解的实际问题之后,怎样才能编写出程序呢?以数值计算问题为例,一般应按图3-12所示的步骤进行。要设计出结构化的程序,可采取以下的方法: ◆自顶向下 ◆逐步细化 ◆模块化 ◆结构化编码【例3.5】输入10个整数(每个数都≥3),打印出其中的素数。分析:素数又称质数,是指只能被1和它本身整除的整数。本题采用自顶向下、逐步细化方法来处理这个问题。先把这个问题分为三部分(如图3-14所示):①输入10个数给x1~x10;②把其中的素数找出来(或者把非素数除去)③打印出全部素数。对【例3.5】求解步骤进行细化后得到的分步骤流程图。【例3.5】的完整流程图3.4C语句概述1.说明语句说明语句用来定义变量的数据类型。例如:

int

sign,i,n;/*说明sign,i,n是整型变量*/2.函数调用语句 由一个函数调用加一个分号构成函数调用语句。如上例中的:printf("\nPleaseinputanintegerton:");scanf("%d",&n);3.表达式语句 在C语言中,由一个表达式加上一个分号就构成了一条表达式语句。最典型的是,由赋值表达式加上分号构成赋值语句。例如:sign=1;sum=1;i=1;sign=(-1)*sign;sum=sum+sign/(3.0*i);i=i+1;表达式能构成语句是C语言的一重要特色。其实函数调用语句也是表达式语句,因为函数调用也属于表达式的一种。4.空语句仅由一个分号构成的语句就是空语句。例如:

;5.复合语句

复合语句是由大括号括起来的,在逻辑上相关的一组语句。如上例中的:{sign=(-1)*sign;sum=sum+sign/(3.0*i);i=i+1;}6.控制语句 控制语句用来规定语句执行的顺序,C语言共有9种控制语句。(1)if(条件){…}else{…}(条件语句)(2)for(条件){…}(循环语句)(3)while(条件){…}(循环语句)(4)do{…}while(条件);(循环语句)(5)continue;(结束本次循环语句)(6)break;(结束循环语句或结束switch语句)(7)switch(表达式){…}(多分支选择语句)(8)goto

标号;(转向语句)(9)return(表达式);(从函数返回语句)3.5选择结构程序设计3.5.1关系运算符和关系表达式关系表达式用关系运算符连接起来的表达式称为关系表达式,关系表达式的结果为逻辑值真(用“1”表示)或假(用“0”表示)。例如:

c>a+b

若a=3,b=4,c=9则结果为1a==b<c 若a=3,b=4,c=9则结果为0a=b>c 若b=4,c=9 则a的值为0

两个数值进行比较,是比较其数值的大小,两个字符进行比较,是比较其ASCII码值的大小。3.5.2逻辑运算符和逻辑表达式

1.逻辑运算符及优先次序逻辑运算符与其他运算符的运算优先顺序如下图所示:例如:原式可写为(a>b)&&(x>y) a>b&&x>y(a==b)||(x==y) a==b||x==y(!a)||(a>b) !a||a>b2.逻辑表达式用逻辑运算符将关系表达式或逻辑表达式连接起来的式子称逻辑表达式。例如,若a=4,b=2,x=6,y=7,则:a>b&&x>y表达式的结果为0a==b||x==y表达式的结果为0!a||a>b 表达式的结果为1注意:(1)在C语言中规定:非零为“真”,“真”用1表示;零为“假”,“假”用0表示。例如:

'a'&&'b' 其结果为1!5.34 其结果为0(2)对逻辑表达式的求解,并不是所有的逻辑运算符都被执行,只是在必须执行下一个逻辑运算符才能求出表达式的解时,才执行该运算符。【例3.6】运行下面的程序四次,若分别输入000,101,123,100,分别写出其对应的输出结果。#include<stdio.h>voidmain(){

int

a,b,c;

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

printf("e=%d,a=%d,b=%d,c=%d\n", ++a&&b--&&++c,a,b,c);

printf("a=%d,b=%d,c=%d,e=%d,\n",

a,b,c,++a&&b--&&++c);c=a||((a=c)>b);

printf("a=%d,b=%d,c=%d\n",a,b,c);

printf("e=%d,a=%d,b=%d,c=%d\n", --c||b--||++a,a,b,c);

printf("a=%d,b=%d,c=%d,e=%d\n",

a,b,c,--c||b--||++a);}在VisualC++6.0环境下运行,若输入000↙其输出为:e=0,a=1,b=-1,c=0a=2,b=-2,c=1,e=1,a=2,b=-2,c=1e=1,a=2,b=-3,c=0a=2,b=-3,c=-1,e=1在TurboC2.0环境下运行,若输入000↙其输出为:e=0,a=0,b=0,c=0a=2,b=-2,c=1,e=1,a=2,b=-2,c=1e=1,a=2,b=-2,c=1a=2,b=-3,c=-1,e=13.5.3if语句C语言提供了两种格式:格式1:if(表达式)语句;该语句的功能是:首先计算表达式的值,然后判断表达式的值是否为非零(真),若为非零(真),则执行语句。其执行过程见图3-22所示【例3.7】输入一个字符c,若c是字母,则输出“Yes!”。#include<stdio.h>voidmain(){charc;c=getchar();

if(c>='a'&&c<='z'||c>='A'&&c<='Z')printf("Yes!");}运行情况如下:x↙Yes!程序如下:#include<math.h>#include<stdio.h>voidmain(){floatx;doublez;

printf("\nx=");

scanf("%f",&x);

if(x<0)z=-1;

if(x==0)z=0;

if(x>0)z=log(x);

printf("z=%f\n",z);}格式2:

if(表达式)语句1;else语句2;该语句的功能是:首先计算表达式的值,然后判断表达式的值是否为非零(真),若非零(真),则执行语句1,否则执行语句2。其执行过程下图【例3.9】输入两个数并判断两数是否相等。程序清单如下:#include<stdio.h>voidmain(){

int

a,b;

printf("Enterintegera:");

scanf("%d",&a);

printf("Enterintegerb:");

scanf("%d",&b);

if(a==b)printf("a==b\n");elseprintf("a!=b\n");}【例3.10】输入一个整数,若该数不为零,则输出。#include<stdio.h>voidmain(){intx;

scanf("%d",&x);

if(x)printf("\nx=%d",x);}程序运行结果如下:-5↙

{输入}x=-5 {输出}说明:if后面的表达式可以为任何类型的表达式,只要表达式的结果为非零,则表示条件成立,否则表示条件不成立。总结:1.if后面的表达式可以为任何类型的表达式,只要表达式的结果为非零,则表示条件成立,否则表示条件不成立。2.if语句中的语句1,语句2可以是一条语句,也可以是由{}构成的一个复合语句,如果在该语句处需要写多条语句才能完成所必要的功能时,就使用复合语句的形式。3.在格式2中的else前面的语句必须要有一个分号,整个语句结束处有一个分号。如例3.9中的if语句。3.5.4if语句的嵌套在一个if语句中,如果又完全包含了另一个(或者多个)if语句,则称为if语句的嵌套。

if嵌套的一般形式如下:

if(表达式1)if(表达式2)语句1;

else语句2;elseif(表达式3)语句3;else语句4;if语句的嵌套既可以嵌套在if后面,也可以嵌套在else后面,具体嵌套的位置要根据实际需要而定。【例3.11】编写程序,求下列分段函数的值。【例3.11】的程序清单如下:#include<math.h>#include<stdio.h>voidmain(){floatx;doublez;

printf("\nx=");

scanf("%f",&x);

if(x<0)z=-1;elseif(x>0)z=log(x);elsez=0;

printf("z=%f\n",z);}对【例3.11】程序的另一种修改:#include<math.h>#include<stdio.h>voidmain(){floatx;doublez;

printf("\nx=");

scanf("%f",&x);

if(x<=0)

if(x<0)z=-1;elsez=0;elsez=log(x);

printf("z=%f\n",z);}else的最近配对原则:C语言规定:else总是与它上面最近的且又没有配对的if语句进行配对。在下面这条嵌套的if语句中

if(表达式1)if(表达式2)语句1;

else语句2;elseif(表达式3)语句3;else语句4;若把else语句2去掉,变成:

if(表达式1)if(表达式2)语句1;

elseif(表达式3)语句3;else语句4;

第一个else将和哪个if配对?根据else的最近配对原则,第一个else将与第2个if(表达式2)语句1;配对,如图3-27所示。在下面的if嵌套语句中if(表达式1)if(表达式2)语句1;elseif(表达式3)语句3;else语句4;

如果用户希望else只能和if(表达式1)配对,而不是与现在的if(表达式2)语句1;配对,则应该在if(表达式2)语句1;的两端加上花括号,从而确定了新的配对关系,修改后的结果:if(表达式1){if(表达式2)语句1;}elseif(表达式3)语句3;else语句4;【例3.12】写出下面程序的运行结果。#include<stdio.h>voidmain(){int

a,b,c;a=5;b=3;c=0;

if(c)

if(a>b)

printf("\nmax=%d",a);else

printf("\nmax=%d",b);else

printf("\nc=%d",c);}运行结果如下:c=03.5.5条件运算符和条件表达式

条件运算符(?:)是C语言中唯一的一个三目运算符,其格式如下:

表达式1?表达式2:表达式3功能:如果表达式1的值为真,则该条件表达式的结果取表达式2的值,否则取表达式3的值。例如:下述的if语句

if(a>b)max=a;elsemax=b;可以用条件表达式来改写:

max=a>b?a:b;条件表达式说明:1.条件表达式的执行顺序:先计算表达式1的值,若表达式1的值为真,则计算表达式2的值,并把该值作为整个条件表达式的结果,表达式3不会计算;否则计算表达式3的值,并把表达式3的值作为整个条件表达式的结果,此时表达式2不会计算。2.运算优先级:高于赋值运算符,低于算术运算符和关系运算符。例:max=(a>b)?a:b相当于max=((a>b)?a:b)a>b?a:b+1相当于a>b?a:(b+1)3.条件运算符的结合方向为“自右至左”。如:a>b?a:c>d?c:d相当于a>b?a:(c>d?c:d)【例3.13】阅读下面的程序,若输入为59,则输出结果是什么?#include<stdio.h>voidmain(){

intscore;chargrade;

printf("pleaseinputascore:\n");

scanf("%d",&score);grade=score>=90?'A':(score>=60?'B':'C');

printf("%dbelongsto%c",score,grade);}运行结果如下:pleaseinputascore:59↙59belongstoC3.5.6switch语句

switch语句属于多分支结构语句,通常用于描述有多种情况的选择,其格式如下:

switch(表达式) { case常量表达式1: 语句1; case常量表达式2: 语句2; … case常量表达式n:

语句n; default:

语句(n+1); }上式中的default:和语句(n+1);可以省略不写。

switch语句的执行过程如下:首先计算表达式的值,然后用此值来查找各个case后面的常量表达式,直到找到一个等于表达式值的常量表达式,则转向该case后面的语句去执行;若表达式的值与下面任何一个case常量表达式的值都不相等,则自动转去执行default部分的语句;如果没有default部分,退出该switch语句,执行switch语句后面的那条语句。

【例3.14】

编写一个程序,要求输入学生的分数,输出其成绩的分数段,用A、B、C、D、E分别表示90分以上、80~89分、70~79分、60~69分和不及格(0~59分)5个分数段。【例3.14】的程序清单。#include<stdio.h>voidmain(){int

score,grade;

printf("\nInputascore(0~100):");

scanf("%d",&score);grade=score/10;

switch(grade){case0:case1:case2:case3:case4:case5:printf("grade=E!\n");break;case6:printf("grade=D!\n");break;case7:printf("grade=C!\n");break;case8:printf("grade=B!\n");break;case9:case10:printf("grade=A!\n");break;default:printf("Thescoreisoutofrange!\n");}}【例3.14】程序的运行结果:Inputascore(0~100):50↙{输入分数}grade=E! {输出结果}再运行一次:Inputascore(0~100):90↙grade=A! {输出结果}switch语句的补充说明:(1)switch后的表达式,可以是整型或字符型,也可以是枚举类型,不能是除这三种类型以外的其它类型;(2)每个case后的常量表达式只能是常量组成的表达式,当switch后的表达式的值与某一个常量表达式的值一致时,程序就转到此case后的语句开始执行;如果没有一个常量表达式的值与switch后的值一致,就执行default部分的语句;(3)每个case后的常量表达式的值必须互不相同,否则程序就无法判断应该执行哪个语句;(4)case的摆放顺序并不影响执行结果,但通常情况下是将出现频率较高(即较常使用的case部分,尽量往前摆放;另外,default部分也不一定非要放在最后;(5)在执行完一个case后面的语句后,程序流程转到下一个case后的语句开始执行,直至整个switch语句结束,别误解为执行完一个case语句之后,程序就会转到switch后的语句去执行。(6)如果希望在执行完某个case语句之后,转到执行switch下面的那条语句,则应该在该case语句的最后补上break语句(即跳转语句)。在执行完break语句之后,会跳出switch语句,转去执行switch后面的语句。【例3.21】从键盘输入一个日期,判断这一天是这一年的第几天?#include<stdio.h>voidmain(){intday,month,year,sum,leap;

printf("\nPleaseinputyear,month,day\n");

scanf("%d,%d,%d",&year,&month,&day);

switch(month)/*先计算某个月之前总天数*/{

case1:sum=0;break;

case2:sum=31;break;

case3:sum=59;break;

case4:sum=90;break;

case5:sum=120;break;

case6:sum=151;break;

case7:sum=181;break;

case8:sum=212;break;

case9:sum=243;break;

case10:sum=273;break;

case11:sum=304;break;

case12:sum=334;break;

default:printf("dataerror");}sum+=day;/*总天数再加上输入的几号*/

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

leap=1; /*判断出是闰年*/

elseleap=0;

if(leap==1&&month>2)sum++;

/*如果是闰年且月份大于2,则总天数应再加1天*/

printf("Itisthe%dth

day.",sum);}【例3.15】程序分析:以2008年7月19日为例,首先应该把7月份之前共六个月的总天数加起来,然后再加上本月的19天就得到本年度的第几天。特殊情况下,若该年是闰年且输入月份值大于二月份时,需要考虑多加一天。程序运行结果如下:Pleaseinputyear,month,day

2008,7,19↙{输入年月日}Itisthe201thday.{输出}3.5.7选择结构程序设计举例【例3.16】求一元二次方程ax2+bx+c=0的实数解,并显示结果,这里假设a≠0。图3-29用嵌套的if语句求一元二次方程的解#include<stdio.h>#include<math.h>voidmain(){floata,b,c,d;

printf("\na=");

scanf("%f",&a);

printf("b=");

scanf("%f",&b);

printf("c=");

scanf("%f",&c);d=b*b-4*a*c;

if(d>0){printf("\nx1=%f",(-b+sqrt(d))/(a*2));printf("\nx2=%f",(-b-sqrt(d))/(a*2));}else

if(d==0)printf("\nx1=x2=%f",(-b)/(a*2));elseprintf("\nTheequationhasnorealroot!");}【例3.16】的程序清单【例3.16】程序的运行结果:第一次运行:572↙ {输入a,b,c}x1=-0.400000{输出}x2=-1.000000第二次运行:441↙

x1=x2=-0.500000第三次运行:414↙Theequationhasnorealroot!【例3.17】输入两个正整数a和b,其中a不大于31,b最大不超过三位数。使a在左,b在右,拼成一个新的数c。例如a=23,b=30,则c为2330。若a=1,b=15,则c为115。分析:根据以上问题,可以从中抽象分析出以下数学模型,决定c的值的计算公式如下:当b为一位数时,c=a*10+b;

当b为二位数时,c=a*100+b;当b为三位数时,c=a*1000+b;因此,求c的公式为c=a*k+b(k的取值可以为10、100或1000)。【例3.17】的流程图。#include<stdio.h>voidmain(){int

a,b,c,k;

printf("\nInputtwopositiveintegernumber:");

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

if(a<0||b<0||a>31||b>999){c=-1; /*出错标志,代表输入数据有误*/

printf("Inputdataerror!");}else{if(b<10)k=10;elseif(b<100)k=100; elseif(b<1000)k=1000;c=a*k+b;}

printf("\na=%2d,b=%3d,c=%5d",a,b,c);}【例3.17】的程序清单【例3.17】程序运行结果:第一次运行:Inputtwopositiveintegernumber:23,30↙a=23,b=30,c=2330 {有效的结果}第二次运行:(2)Inputtwopositiveintegernumber:44,19↙Inputdataerror!a=44,b=19,c=-1{无效的结果,因为a>31}例3.18:假设个人所得税的计征办法是月收入低于1000元者,不计税,高于1000元低于2000元者,高出部分征收5%;高于2000元低于5000元者,高出部分征收10%;高于5000元低于是10000元,高出部分征收15%,高于10000元的征收35%。输入一个人的月收入,求出其应交的个人所得税。#include<stdio.h>voidmain(){longintr;floatf;

printf("Inputanintegertor:");

scanf(“%ld”,&r); {输入月收入}if(r>0){switch(r/1000){case0:f=0;break;case1:f=(r-1000)*0.05;break;case2:case3:

case4:f=1000*0.05+(r-2000)*0.1;break;【例3.18】的程序清单

case5:case6:case7:case8:case9:f=1000*0.05+3000*0.1+(r-5000)*0.15;break;default:f=1000*0.05+3000*0.1+5000*0.15+(r-10000)*0.35;}

printf(“f=%f”,f); {输出所得税}}else

printf(“Inputadataerror!”); {输入数据有误}}【例3.19】输入两个实数a,b,再输入一个运算符(可以是+,-,*或/),根据运算符计算并输出a,b两个数的和、差、积和商。#include<stdio.h>voidmain(){floata,b;charc;

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

switch(c){case'+':printf("%f+%f=%f\n",a,b,a+b);break;case'-':printf("%f-%f=%f\n",a,b,a-b);break;case'*':printf("%f*%f=%f\n",a,b,a*b);break;case'/':if(b)printf("%f/%f=%f\n",a,b,a/b);break;default:printf("Can'tcompute!");}}【例3.19】运行结果如下:第一次运行:58+↙ {输入}5.000000+8.000000=13.000000 {输出}第二次运行:56/↙{输入}5.000000/6.000000=0.833333 {输出}【例3.20】给一个不多于5位的正整数,编程求:①它是几位数,②逆序打印出各位数字,③若为两位以上的数,则判断该数是否为回文数。分析:分解出该数每一个数位上的数字。若万位数大于零,则为5位数;否则,若千位数大于零,则为4位数;否则,若百位数大于零,则为3位数;否则,若十位数大于零,则为两位数;否则,若个位数大于零,则为1位数,否则提示输入错误。所谓回文数,是指左右对称的数,即从左往右读与从右往左读得到的结果一样,譬如161就是回文数。若为5位数,只需判断该数的个位数与万位数是否相同,十位数与千位数是否相同,若两者均相同,则为回文数。对于其他位数的判断,请读者自已归纳。【例3.20】程序清单如下:#include<stdio.h>voidmain(){

int

a,b,c,d,e;longx;do{printf("\nPleaseinputapositiveintegernumbertox:");

scanf("%ld",&x);}while(x<=0||x>=100000);/*上述循环能够确保输入的x值一定是一个不超过5位的正整数*/a=x/10000; /*分解出万位数字*/b=x%10000/1000; /*千位数字*/c=x%1000/100; /*百位数字*/d=x%100/10; /*十位数字*/e=x%10; /*个位数字*/if(a>0)/*万位数字*/{printf("thereare5,%d%d

%d

%d%d\n",e,d,c,b,a);

if(e==a&&d==b)printf("thisnumberisahuiwen\n");elseprintf("thisnumberisnotahuiwen\n");}else

if(b>0)/*千位数字*/{printf("thereare4,%d%d%d%d\n",e,d,c,b);

if(e==b&&d==c)printf("thisnumberisahuiwen\n");elseprintf("thisnumberisnotahuiwen\n");}else

if(c>0)/*百位数字*/{printf("thereare3,%d%d%d\n",e,d,c);

if(e==c)printf("thisnumberisahuiwen\n");elseprintf("thisnumberisnotahuiwen\n");}

else

if(d>0)/*十位数字*/{printf("thereare2,%d%d\n",e,d);

if(e==d)printf("thisnumberisahuiwen\n");elseprintf("thisnumberisnotahuiwen\n");}else/*个位数字*/

if(e>0)printf("thereare1,%d\n",e);}【例3.20】程序运行结果:Pleaseinputapositiveintegernumbertox:543↙thereare3,345thisnumberisnotahuiwen再运行一次:Pleaseinputapositiveintegernumbertox:121↙thereare3,121thisnumberisahuiwen3.6循环结构程序设计在C语言中提供了四种实现循环结构的方法:(1)goto语句以及用goto语句构成的循环(2)用while语句(3)用do-while语句(4)用for语句3.6.1goto语句以及用goto语句

构成的循环goto语句为无条件转向语句,其格式为

goto

语句标号;通常在两种情况下使用goto语句:(1)与if语句一起构成循环结构;(2)从循环体中跳转到循环体外,但在C语言中可以用break语句和continue语句跳出本层循环和结束本次循环。【例3.21】用if语句和goto语句构成循环,求

#include<stdio.h>voidmain(){

inti=1;

intsum=0;loop:if(i<=100){sum+=i; i++;

gotoloop;}printf("\n1+2+3+…+100=%d",sum);}运行结果如下:1+2+3+…+100=5050说明:处于loop语句标识符和gotoloop之间的语句序列构成该程序的循环体,语句标识符loop后面要加冒号(:)。3.6.2while语句while语句又称当循环语句,其一般的形式如下:

while(表达式)循环体语句;while语句的执行过程:第1步:计算表达式的值,若表达式的值为真(非0),则执行第二步,若表达式的值为假(值为0),则转到第四步执行。第2步:执行循环体语句,循环体语句可以是简单的一条语句,也可以是由多条语句构成的复合语句。第3步:转到第一步执行。第4步:结束循环,执行while语句后的第一条语句。

【例3.22】用while语句来求100以内偶数的和。#include<stdio.h>voidmain(){

intsum=0,i=2;

while(i<=100){sum=sum+i;i=i+2;}printf("2+4+…+100=%d",sum);}有关while循环的说明:(1)while循环的次数可以事先不清楚,因为在循环执行时,能够根据条件来判定循环是否终止;(2)循环体语句可以是简单的语句,也可以是复合语句;若为复合语句,则需要用花括号括起来;(3)在循环体语句中,一定要有改变循环条件的语句,使循环最终能够终止。例如:【例3.22】中的i=i+2;就是控制循环变量i不断地加2,朝着循环的终止条件(i<=100)逼近;此处若删除循环控制语句i=i+2;,即i值永远不变,则循环条件(i<=100)即2<=100永真,此时的无限循环称为死循环,编程时应杜绝死循环的出现。【例3.23】阅读下面的程序,写出运行结果。#include<stdio.h>voidmain(){

inti=1,s=1;

while(i<7)s*=i;

printf("\ns=%d\n",s);}

显然,本例在循环体中缺少用来控制循环变量的值变化的语句,因此导致程序中出现死循环。若上述程序在VisualC++6.0环境下运行,由于死循环,因此不会出现运行结果,此时应该按下组合键【Ctrl+Break】,或者单击运行窗口上的“关闭”按钮来终止程序的运行,返回到编辑状态对程序进行修改。3.6.3do-while语句do-while循环语句又称直到型循环语句,但是与Pascal语言中的repeat-until语句又有所不同。C语言中do-while语句的格式:do

循环体语句;while(表达式);

do-while语句的执行过程如下:(1)执行循环体语句,循环体语句可以是简单的一条语句,也可以是由多条语句构成的复合语句;(2)计算表达式的值,如果表达式的值为真(非0),则执行第(1)步,若表达式的值为假(值为0),则转到第(3)步执行;(3)循环结束之后,将执行do-while语句下面的那条语句。【例3.24】用do-while语句来实现求100以内的奇数和。

N-S流程图如下图所示。【例3.24】的程序清单如下:#include<stdio.h>voidmain(){

intsum=0,i=1;do{sum+=i;i=i+2;}while(i<=100);

printf("\n1+3+…+99=%d\n",sum);}运行结果如下:1+3+…+99=2500说明:(1)do…while语句一般也是用于事先不知道循环次数的情况下,在循环执行的过程中,根据条件来决定循环是否结束。(2)在循环体语句中可以是一条简单的语句,也可以是复合语句,若为复合语句则要用花括号括起来。(3)在循环体语句中,一定要有改变循环条件的语句,使循环能终止。如上例中的i=i+2;语句就是使循环变量i增加2,改变循环条件的语句,若没有该语句,则i的值永远不会改变,循环就是一个死循环。(4)在while(表达式)的后面一定要有一个分号,它用来表示do-while语句的结束。(5)do…while语句和while语句最大的差别就是do-while语句至少要执行一次循环体语句,而while语句可以一次都不执行。请看例3.25。【例3.25】while循环和do…while循环的比较。程序如下:

voidmain() voidmain(){{

int

m,n=1; int

m,n=1;

scanf("%d",&m);scanf("%d",&m);dowhile(m<=10){{n+=m;n+=m;m++;m++;}while(m<=10);}

printf(“n=%d,m=%d”,n,m);printf("n=%d,m=%d",n,m);}}程序运行结果如下:程序运行结果如下:5↙ 5↙n=46,m=11n=46,m=11再运行一次:再运行一次:11↙ 11↙n=12,m=12n=1,m=113.6.4for语句for语句的一般形式为:

for(表达式1;表达式2;表达式3)循环体语句其执行过程如下:(1)先求解表达式1;(2)求解表达式2,若为真(表达式2的值为非0),则执行for语句中指定的内嵌循环体语句,然后执行第(3)步,若为假(表达式2的值为0),则结束循环,转到第(5)步;(3)求解表达式3;(4)返回第(2)步继续执行;(5)循环结束,执行for语句后面的第一条语句。图3-35for语句的执行图解for语句执行过程的图解形式如图3-35所示。说明:

(1)可以把for循环的格式

for(表达式1;表达式2;表达式3)循环体语句改写为以下容易理解的形式

for(循环变量赋初值;循环条件;循环变量增值)循环体语句

(2)for语句中的表达式1可以省略,但其后面的分号不能省略,此时应在执行for语句之前,给循环变量赋初值,即

表达式1;

for(;表达式2;表达式3)循环体语句(3)表达式2也可省略,但其后的分号不能省略,即

for(表达式1;;表达式3)循环体语句此时等于没有循环条件,执行for语句时,就不要判断循环条件,也就认为

表达式2始终为真。此时循环体中一定要有一条语句能够跳出循环,否则将是一个死循环。(4)表达式3也可以省略,但它前面的分号不能省略,即

for(表达式1;表达式2;)循环体语句此时应在循环体中要有用于改变循环变量值的语句,否则循环也会变成死循环;(5)表达式1、表达式2、表达式3可以省略一个或者两个,也可同时全部省略,但对应的分号不能省略,譬如:

for(表达式1;;)循环体语句

for(;表达式2;)循环体语句

for(;;表达式3)循环体语句

for(;;)循环体语句(6)表达式1、表达式2、表达式3可以是任何类型的表达式,包括逗号表达式。既可以是与循环变量有关的表达式,也可以是与循环变量无关的表达式。【例3.26】求1000以内的奇数和。程序清单如下#include<stdio.h>voidmain(){

inti;longintsum=0;

for(i=1;i<1000;i+=2)sum+=i;

printf("\nsum=%ld\n",sum);}运行结果如下:sum=250000【例3.27】从键盘接收字符并显示字符的个数。#include<stdio.h>voidmain(){

inti;charc;

for(i=0;(c=getchar())!='\n';i++);

printf("Thesumis%d\n",i);}运行结果如下:Iamachinese!{输入的字符序列,最后以敲回车结束}Thesumis15

请注意:该例中循环体语句为空语句,即什么都不做,其实程序把循环体要执行的工作,全部移到for后面的表达式了。【例3.28】中国剩余定理:“有物不知几何,三三数余一,五五数余二,七七数余三,问物有几何?”。编程求1000以内的所有解。#include<stdio.h>voidmain(){int

m,count=0;

for(m=1;m<=1000;m++)if(m%3==1&&m%5==2&&m%7==3){printf(“%5d”,m);count++;if(count%5==0)printf(“\n”);}}程序运行结果如下:

521572623674725776827878929973.6.5多重循环如果在循环结构中又包含另外一个循环结构,称为多重循环,也叫循环的嵌套。【例3.29】打印如图3-36所示的“九-九”乘法表。

【例3.29】的程序清单。#include<stdio.h>voidmain(){

int

i,j;

for(i=1;i<=9;i++) /*外循环,控制行*/{

for(j=1;j<=9;j++) /*内循环,控制列*/

printf("%d*%d=%d\t",i,j,i*j);

printf("\n");}}本例的N-S流程图如图3-37所示。

如果想打印出以下4种形状的“九九”乘法表,请问该如何编程?第1种图形:

如果想打印出以下4种形状的“九九”乘法表,请问该如何编程?第2种图形:

如果想打印出以下4种形状的“九九”乘法表,请问该如何编程?第3种图形:

如果想打印出以下4种形状的“九九”乘法表,请问该如何编程?第4种图形:【例3.30】

问用1、2、3、4个这四个数字,能够组成多少个互不相同且无重复数字的三位数?它们分别是多少?#include<stdio.h>voidmain(){

int

i,j,k,count=0;

for(i=1;i<5;i++)/*判断百位数字i*/

for(j=1;j<5;j++)/*判断十位数字j*/for(k=1;k<5;k++)/*判断个位数字k*/{if(i!=k&&i!=j&&j!=k)/*确保i、j、k互不相同*/{count++;

printf("%d%d%d",i,j,k);if(count%5==0)printf("\n");}}

printf(“\ncount=%d\n”,count);}【例3.30】程序的运行结果如下:123124132134142143213214231234241243312314321324341342412413421423431432count=24{输出符合条件的总数}3.6.6循环结构中的break语句break语句格式:

break;

break语句的作用是从最内层的switch、for、while或do…while语句中跳出,终止这些语句的执行,把控制流程转移到被中断的循环语句(或者switch语句)后去执行。通过使用break语句,可以不必等到循环或switch语句执行结束,而是根据情况,提前结束这些语句的执行。【例3.31】求当半径r为何值时,圆的面积第一次开始大于100?#include<stdio.h>voidmain(){

intr;floatarea,pi=3.1415927;

for(r=1;;r++){area=pi*r*r;

if(area>100)break;{面积开始大于100了}

printf("%f\n",area);}

printf("r=%d\n",r);}【例3.31】程序运行结果如下:3.14159312.56637128.27433450.26548478.539818r=6

本程序运行后,for循环运行了5次,当运行第6次(r=6)时,area=113.097336>100,这时程序不输出area的值,同时中断了for循环语句的继续运行,转到for循环的下一条语句输出r的值。3.6.7continue语句continue语句的形式:continue;其作用是提前结束本次循环,即跳过循环体中那些尚未执行的语句,紧接着进行下一次是否执行循环的判断。【例3.32】从键盘输入整数,显示出其中的正整数,若输入的是0,则退出。#include<stdio.h>voidmain(){

intx;do{scanf("%d",&x);

if(x<0)continue;

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

while(x!=0);}【例3.33】下面程序的作用是求连续的奇数和,当奇数和刚好超过1000时停止计算,并按运行结果输出。程序中有两空,请补充完整,使之能实现上述功能。#include<stdio.h>voidmain(){

int

i,sum=0;

for(i=1;;i++){if(i%2==0)continue;sum+=i;

if(sum>1000)break;}printf("1+3+5+…+%d=%d\n",i,sum);}【例3.33】程序分析:在程序中,第一空前面的条件表示i为偶数时要执行的情况,由于本题偶数不符合题目累加的条件,故不应执行累加语句。因此,第一空应填continue。第二个空前面的条件表示累加和大于1000,按题目要求应退出循环,因此,第二空应填break。答案:(1)continue

(2)break

程序运行结果:

1+3+5+…+63=10243.6.8循环程序设计举例【例3.34】从键盘输入一个整数n,判断n是否为素数。

素数又叫质数,是指只能被1和它本身整除的自然数。在编程时,可以根据素数的定义来进行判断,不过循环次数太多,效率较低。这里介绍一种效率更高的求素数的方法:引入一个整型变量k=。让变量j位于区间[2,k]内,从j=2开始循环,直至j=k结束,判断变量n能否被变量j整除。如果在区间[2,k]内有变量n能被变量j整除,则j值必然小于或等于k值,表明n不是素数,应该提前结束循环。如果变量n不能被[2,k]之间的任何一个整数整除,则表明n是素数。【例3.34】的流程图#include<stdio.h>#include<math.h>voidmain(){intn,j,k;

printf("\nInputanintegerton:");

scanf("%d",&n);k=sqrt(n);j=2;

while(j<=k){

if(n%j==0)break;j++;}

if(j>=k+1)printf(“\n%disaprimenumber!\n”,n);{是素数}elseprintf(“\n%disnotaprimenumber!\n”,n);{不是素数}

}【例3.34】的程序清单【例3.34】程序运行结果如下:Inputanintegerton:235↙235isnotaprime!再运行一次:Inputaintegerton:29↙29isaprime!【例3.35】某人想将手中一张100元的人民币兑换成5元、1元和5角这三种面值的零钞,同时要求所兑换的零钞总数为100张,而且每种零钞的数目不少于1张。问有哪几种兑换方法?假设兑换后5元面值的钞票有i张,1元的钞票有j张,5角的钞票有k张,则有以下方程组成立:不过三个变量只能列出两个方程式,这是一个不定方程组的求解。其实题目中还隐含了如下的条件:1<=i<20且1<=j<95且1<=k<=98

在i、j、k的取值范围内尝试各种可能的情况,从中判断哪种可能是符合要求的解,这就是穷举法的思想。【例3.35】的程序清单。#include<stdio.h>voidmain(){

int

i,j,k;

printf("\nijk\n");

for(i=1;i<20;i++){5元面值}

for(j=1;j<95;j++){1元面值}

for(k=1;k<=98;k++){5角面值} if((i+j+k==100)&&(10*i+2*j+k==200)) printf("%7d%7d%7d\n",i,j,k);}【例3.35】运行结果如下(有11组解)

ijk191828216373

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论