1、2019/6/26,第3章 程序结构,C 语言程序设计,2019/6/26,3.4 顺序结构程序设计,3.4.1 顺序结构程序的一般算法描述,可用: 变量初始化 赋值语句 输入函数调用语句,注意各个语句的顺序,2019/6/26,3.4.2 顺序结构程序设计举例,【例3.3】数据交换。从键盘输入a、b的值,输出交换以后的值。 思路:在计算机中交换变量a和b的值,不能只写下面两个赋值语句 a=b ; b=a ;,?,正确的交换方法: c=a ; a=b ; b=c; 或者 a=ab; b=ba; a=ab;,2019/6/26,程序:,main( ) int a,b,c;printf(“ninp
2、ut a, b: “);scanf(“%d,%d“, ,程序运行情况如下: input a, b: 32, 57 before exchange: a=32 b=57 after exchange: a=57 b=32,2019/6/26,举例:,【例3.4】已知三条边a、b、c,求三角形面积。计算三角形面积的海伦公式:,其中:,设定义: 整型变量 a、b、c 实型变量 s 、 area,2019/6/26,程序如下:,#include “math.h“ main( ) int a,b,c;float s,area ;scanf(“%d, %d, %d“, ,程序运行情况如下: 3,4,5 a
3、rea = 6.000,实际上还需要判断a、b、c是否能构成三角形,即应该进行选择判断处理,2019/6/26,3.5.1简单分支语句,语句一般格式if (表达式) 语句,功能: 计算表达式的值,如果是一个非0值(即逻辑真),就执行内嵌语句,否则(即逻辑假)跳过内嵌语句,顺序执行后续语句。,3.5 分支结构程序设计,2019/6/26,简单分支语句的算法:,例如: if (x0) m+; if ( ab ) c=a; a=b; b=c; ,2019/6/26,双重分支语句,语句一般格式 if (表达式) 语句1 else 语句2 功能: 计算表达式的值,如果它的值是一个非0值(逻辑真),就执行
4、内嵌语句1,之后跳过内嵌语句2,执行后续语句;否则跳过内嵌语句1,执行内嵌语句2,之后执行后续语句。,2019/6/26,双重分支语句的算法:,例如: if (x0) m+; else m-; if ( ch= a ,2019/6/26,多重分支语句,语句一般格式 if (表达式1) 语句1 else if (表达式2) 语句2 else if (表达式m) 语句m else 语句 n 功能: 依次计算并判断表达式i,为非0时执行后面的语句,都为0时,执行语句n 无论执行完那个语句分支,都转到后续语句,2019/6/26,多重分支语句的算法,流程图,表达式m ?,2019/6/26,多重分支语
5、句的算法,N-S结构图,例如: if (a0) x= -1 ; else if (a=0 ) x= 0 ; else x=1 ;,2019/6/26,if语句的简单应用,【例5】输入一个字符,如果是大写字母,则将其转换为小写字母输出,否则直接输出。,输入:用 getchar 或 scanf 函数 ch是否为大写字母: ch=A & ch=65 & ch = 90) 大写字母转换为小写字母: ch=ch+32 输出:用 putchar 或 printf 函数,思路:,2019/6/26,程序:,#include “stdio.h“ main( ) char ch;ch=getchar( );if
6、 (ch=A ,程序运行情况如下: G g,可使用条件表达式代替,putchar(ch=A putchar ( n),2019/6/26,3.5.2 if语句的嵌套,如果if的内嵌语句中又使用了一个if语句,则构成if语句的嵌套。,【例6】比较两个整数的关系。 #include main( ) int x, y;printf (“Enter integer X and Y:“);scanf (“%d%d“, ,应该正确判断: if的内嵌语句 if和else的配对,提倡缩格书写 有利于阅读程序,2019/6/26,if语句嵌套的形式,简单if语句的嵌套形式 if (表达式) if 语句 双重(或
7、多重)分支if语句的嵌套形式 if (表达式) if 语句 else if 语句,可以是各种形式的if语句,可以是各种形式的if语句,如果是简单if语句, 必须用“ ”括起,2019/6/26,例如:, if (c=50) printf(“50=50) printf(“50150n“); if (c=50) printf(“50=c=100n“); else printf(“c50n“),与哪个if 配对?,2019/6/26,再例如:,if(ab) if(ac) if(ad) m=1; else m=2; else m=3;,问题:哪一个 else 和哪一个 if 相匹配?,规则:在嵌套的i
8、felse语句中,else总是与上面的离它最近的尚未配对的if 配对。,2019/6/26,举例,【例7】输入一个数,判断它是奇数还是偶数,如果是奇数则进一步判断它是否为5的倍数。,2019/6/26,程序:,main( ) int x;scanf (“%d“,2019/6/26,学习if语句的难点,if else 语句的配对 正确用表达式描述条件 例如:当x大于5小于10时令x自增if ( 5x10 ) x+;,正确判断内嵌语句 例如:if(xy)x=x+3; y=y-2;elsex=x-3; y=y+2;,if (x5 , , ,2019/6/26,熟悉常用的if 表达式形式,例如有定义:
9、int a,b=0; a等于什么值时,执行b=2 ;语句? if (a=0) b=2; if (a=1) b=2; if (a!=0) b=2; if (a=1) b=2; if (a=0) b=2; if (a) b=2; if (!a) b=2;,等价于,等价于,2019/6/26,3.5.3 switch语句,switch语句的一般形式 switch (表达式) case 常量表达式1: 语句序列1case 常量表达式2: 语句序列2case 常量表达式n: 语句序列ndefault : 语句序列n+1 功能: 计算表达式的值,与常量表达式的值比较,等于第i个值时,顺序执行语句序列i、i
10、+1、 、 n+1 若与所有常量表达式值都不相等,执行语句序列n+1。,2019/6/26,switch语句的算法描述,N-S结构图,例如: switch (a) case 5: printf(“,当a等于5,输出:$ 当a等于2,输出:#$ 当a是其他值,输出:$,2019/6/26,说明:,“case 常量表达式i:”等价于语句标号,计算出的表达式值等于哪个语句标号,就从哪个位置开始顺序向下执行语句序列。 语句位置影响运行结果,例如: switch (a) case 2: printf(“#“);default: printf(“$“);case 5: printf(“ ,switch
11、与break语句结合才能实现 程序的分支,break; break; break;,2019/6/26,switch语句的简单应用,【例8】已知x=100,y=15,要求输入一个算术运算符(+、-、* 或 / ),并对x和y进行指定的算术运算。,思路: 设x和y为float型变量并赋初值; 输入的运算符op为char型变量; 根据op的值(为+、-、*、/)进行x和y的相加、相减、相乘、相除运算(选择分支); 还要考虑到输入字符不是+、-、* 或 / 时的情况,2019/6/26,程序:,#include “stdio.h“ main( ) float x=100,y=15,z; char o
12、p;op=getchar( );switch (op) case +: z=x+y; break;case -: z=x-y; break;case *: z=x*y; break;case /: z=x/y; break;default: z=0;if(int)z!=0) printf(“%f%c%f=%fn“,x,op,y,z);else printf (“%c is not an operatorn“,op); ,实型数通常不使用z=0或z!=0的比较 可用if(int)z) 代替,2019/6/26,注意:,switch语句的书写格式:语句体本身必须用花括号括起;case和defaul
13、t后面如果有多条语句,则可以不必使用花括号;case和常量表达式之间必须有空格;default可以写在语句体的任何位置,也可以省略不写 break语句可以改变case的语句标号作用,终止后续case语句序列的执行。 switch语句和break语句结合,可以实现程序的选择控制(break语句还可以在循环语句中使用) 允许switch嵌套使用,但同一个switch语句中,任意两个case的常量表达式值不能相同。,2019/6/26,3.5.4 分支结构程序设计举例,【例9】求一元二次方程ax2+bx+c=0的根。,思路:一元二次方程的根取决于系数a,b,c求根公式:,判别式d = b2- 4ac
14、 当 d = 0时,方程有两个相等的实根: x1=x2=-b/(2*a) 当d 0时,方程有两个不相等的实根: x1=(-b+sqrt(d)/(2*a) x2=(-b-sqrt(d)/(2*a) 当d 0时,方程有两个虚根: x1=jp+ipi x2=jp-ipi,实部 jp=-b/(2*a) 虚部 ip=sqrt(-d)/(2*a),2019/6/26,算法:,2019/6/26,程序:,#include “math.h“ main( ) float a,b,c,d,x1,x2,lp,ip;scanf(“%f%f%f“, ,2019/6/26,程序(续):,else if (d1e-6) /
15、* 不相等的实根 */ x1=(-b+sqrt(d)/(2*a); x2=(-b-sqrt(d)/(2*a);printf(“has two real roots:n“) ;printf(“x1=%8.4f, x2=%8.4fn“,x1,x2);else /* 虚根 */ lp=-b/(2*a);ip=sqrt(-d)/(2*a);printf(“has two complex roots: n“);printf(“x1=%8.4f+%8.4fin“,lp,ip);printf(“x2=%8.4f-%8.4fin“,lp,ip);,2019/6/26,举例(续):,【例10】输入年份,判别该年
16、是否为闰年。,思路:年份year为闰年的条件为 能够被4整除,但不能被100整除的年份; 能够被400整除的年份。 只要满足任意一个就可以确定它是闰年。 例如: 1996年、2000年是闰年 1998年、1900年不是闰年,设定标志变量leap,只要符合其中一个条件的就是闰年,令 leap =1;否则令 leap=0,2019/6/26,算法:,year%4=0 & year%100 !=0,2019/6/26,程序:,main( ) int year, leap ;scanf(“%d“, ,2019/6/26,循环结构中涉及到的三个基本概念,循环条件:控制循环开始或结束的条件for(n=1;
17、n=100;n+)s=s+n; 循环变量:用来确定循环条件的变量 循环体:程序中需要重复执行的语句,3.6 循环结构程序设计,2019/6/26,3.6.1 while循环控制,语句一般格式 while (表达式) 循环体语句,一般为关系表达式或逻辑表达式,也可以是C语言其他类型的合法表达式 用来控制循环体是否执行,称为内嵌语句,可以是基本语句、控制语句,也可以是复合语句 是循环重复执行的部分,2019/6/26,功能:,计算表达式的值,为非0(逻辑真)时,重复执行内嵌语句,每执行一次,就判断一次表达式的值,直到表达式的值为0 时结束循环,转去执行while后面的语句。,循环控制条件,循环体,
18、2019/6/26,例如:,【例11】编写程序,求100个自然数的和 即: s=1+2+3+ +100,思路:寻找加数与求和的规律,加数i从1变到100,每循环一次,使i增1,直到i的值超过100。i的初值设为1。 求和设变量 sum 存放和,循环求sum=sum+i,直至i超过100。,2019/6/26,算法和程序:,main( ) int i,sum;i=1; sum=0; while (i=100) sum=sum+i;i+; printf(“sum=%dn“,sum); ,程序输出结果: sum=5050,i: 循环控制变量 sum: 累加器,2019/6/26,注意:,如果whil
19、e的 (表达式) 值为0,则循环体一次也不执行 (例如当i的初值=101) 。 在循环体中必须有使循环趋向结束的操作,否则循环将无限进行(死循环)。 在循环体中,语句的先后位置必须符合逻辑,否则会影响运算结果。,思考程序段的输出?while (i=100) i+; sum=sum+i; ,运行后,输出: sum=5150 原因是什么?,2019/6/26,注意(续):,为了保证循环正常运行,应该特别注意:循环控制条件的描述:可以是关系表达式(i=100)或逻辑表达式(ab&xy)或任意合法的表达式控制条件的初始状态(要有初始值)循环体内部对控制条件的影响:要有改变循环变量的语句,能结束循环,2
20、019/6/26,while循环举例:,利用while语句实现:从键盘输入n(n0)个数,求其和,2019/6/26,while循环举例(续),main() int i, n, k, sum; i=1; sum=0; printf(“Input n: “); scanf(“%d“, ,运行结果: Input n: 6 12 34 2 11 9 5 sum is: 73,2019/6/26,3.6.2 do-while语句,语句一般格式 do 循环体语句 while (表达式); 功能: 先执行内嵌语句(循环体),之后计算表达式的值,不为0(逻辑真)时,再执行循环体并判断条件,直到表达式的值为
21、0 结束循环,转去执行while下面的语句。,2019/6/26,do-while循环的算法,N-S结构图,main( ) int i=1,sum=0;do sum=sum+i;i+; while (i=100);printf(“%dn“,sum); ,用do-while语句 求100个自然数的和,2019/6/26,说明:,while和do-while都能实现循环控制,while结构程序通常都可以转换成do-while结构,区别: do- while 语句先执行循环体再判断条件,循环体至少执行一次; while 语句先判断条件再执行循环体,循环体有可能一次也不执行 dowhile循环体中一定
22、要有能使表达式值趋于0的操作(如i+),否则会出现死循环。,2019/6/26,while与do while举例:求解1100的累计和,while(i=100)sum+=i;i+;,do sum+=i;i+; while(i=100),注意:当i=10、i=11时查看结果,2019/6/26,do-while语句的简单应用,【例12】用辗转相除法求m和n的最大公约数,2019/6/26,算法和程序:,main( ) int m,n,r;scanf(“%d, %d“,程序运行情况如下: 24, 60 12,2019/6/26,do-while举例,例 利用dowhile语句重做前例。,2019/
23、6/26,3.6.3 for语句,语句一般格式for (表达式1;表达式2;表达式3) 语句,功能: 计算表达式1的值,再判断表达式2,如果其值为非0(逻辑真),则执行内嵌语句(循环体),并计算表达式3;之后再去判断表达式2,一直到其值为0时结束循环,执行后续语句。,循环初始条件,循环控制条件,循环体,2019/6/26,for语句的算法,例如: main( ) int i,sum;sum=0; for ( i=1; i=100; i+) sum=sum+i; printf(“sum=%dn“,sum); ,可部分或全部省略,但“;”不可省略,2019/6/26,省略for语句的表达式, 表达
24、式1、2、3全省略,即:for ( ; ; )就等同于:while (1),会无限循环(死循环),注意:在省略某个表达式时,应在适当位置进行循环控制的必要操作,以保证循环的正确执行, 省略表达式1和表达式3,即:for(;表达式2;)就等同于:while( 表达式2 ) 省略表达式2,即:for(表达式1; ;表达式3)就等同于:表达式1; while(1)表达式3;,2019/6/26,例如:, i=1;for ( ; i100) for (i=1; i100) i+; ,2019/6/26,说明:,所有用 while 语句实现的循环都可以用for 语句实现。,等价于:,for(表达式1;表
25、达式2 ;表达式3)语句;,表达式1; while (表达式2) 语句;表达式3;,2019/6/26,for语句的简单应用,【例13】求n! ,即计算p=123n的值。,思路:求阶乘与求累加的运算处理过程类似,只要将“+”变为“*”。,设置: 乘数i ,初值为1,终值为n(n是循环控制终值,需要从键盘输入) 累乘器 p ,每次循环令p = p*i,2019/6/26,程序:,main( ) int i, n; long p; p=1; printf(“Enter n:“);scanf(“%d“, ,思考: 如何输出1!, 2!, , n! ? 如何求s =1!+ 2!+ + n! ?,201
26、9/6/26,熟悉几个循环语句,while (!x) x+; 当 x=0 时,执行循环体x+;,while (c=getchar( ) != n) n=n+1; n 称为计数器,作用是统计输入字符的个数 while (num+5); 先执行循环体x*=-3,再判断条件(x5) for (n=0; n26; n+) printf(“%c “, n+A); 作用是输出26个大写字母 for (sum=0, i=1; i=100; sum=sum+i, i+=2) ; 作用是计算100以内的奇数和,2019/6/26,for循环举例1,例 计算1至50中是7的倍数的数值之和,main() int i
27、, sum=0; for (i=1; i=50; i+)if (i%7=0) sum+=i; printf(“sum=%dn“, sum); 运行结果: sum=196,2019/6/26,for循环举例2,#include“stdio.h“ main() int n=0;printf(“input a string:n“);for(;getchar()!=n;n+); /*空语句*/printf(“您共输入了%d个字符n“,n); 说明:只要不是回车符就统计,2019/6/26,几种循环语句的比较(包括结构的设计),while和do-while语句的表达式只有一个,for语句有三个。 whi
28、le 和for先判断循环条件后执行循环体,do-while语句先执行循环体后判断循环条件。,while语句多用于循环次数不定的情况 do-while语句多用于至少要运行一次的情况 for语句多用于要赋初值或循环次数固定的情况,2019/6/26,3.6.4 用goto语句实现循环,有兴趣的同学自学 不提倡使用goto语句,注意: goto语句能实现程序无条件转移,为编程提供了便利。但是无限制地使用,会破坏程序的结构化程度。因此应限制使用。,2019/6/26,3.6.5 循环结构中的跳转语句,有如下三种语句实现跳转: continue语句 break语句 goto语句 在循环语句的循环体中使用
29、,可以进行循环的流程控制,2019/6/26,(1) continue语句及应用,功能: 中断循环体的本次执行(即跳过循环体中尚未执行的语句),立即开始执行下一次循环。,while语句,do-while语句,for语句,2019/6/26,例如:, int x,n=0,s=0; while (n10) scanf(“%d“, int x,n=0,s=0; do scanf(“%d“, for (n=0,s=0; n10; n+) scanf(“%d“, ,2019/6/26,应用举例,【例14】把100200之间能被7整除的数,以十个数为一行的形式输出,最后输出一共有多少个这样的数。,2019
30、/6/26,算法和程序,main( ) int n,j=0;for(n=100;n=200;n+) if (n%7!=0) continue; /不能被7整除,继续下一个数printf(“%6d“,n);j+;if (j%10=0) printf(“n“); printf(“ n j=%dn“,j);,2019/6/26,运行结果,2019/6/26,continue举例,例 把100到150之间的不能被3整除的数输出,要求一行输出10 个数。,main() int n, i=0; for (n=100; n=150; n+) if (n%3=0) continue; printf(“%4d“
31、, n); i+; if (i%10=0) printf (“n“); ,2019/6/26,(2) 循环中break的应用,功能: 利用break语句能够强迫终止本层循环,转到后续语句执行。,while语句,do-while语句,for语句,2019/6/26,例如:, int x,n=0,s=0; while (n10) scanf(“%d“, int x,n=0,s=0; do scanf(“%d“, for (n=0,s=0; n10; n+ ) scanf(“%d“, ,2019/6/26,break举例,例 计算r=1到r=10时的圆面积,直到面积area大于100为止。,#def
32、ine PI 3.1415926main() int r; float area;for (r=1; r100) break; printf(“r: %d area is: %fn“, r, area); ,2019/6/26,运行结果,2019/6/26,break举例续,运行结果: r: 1 area is: 3.1415930 r: 2 area is: 12.566370 r: 3 area is: 28.274334 r: 4 area is: 50.265480 r: 5 area is: 78.539818,2019/6/26,3.6.6 循环的嵌套,如果循环语句的循环体内又包含
33、了另一条循环语句,则称为循环的嵌套 例如: /乘法表 #include main( ) int i, j;for ( i=1; i10; i+ )for ( j=1; j=i; j+ )printf (j=i)?“%4dn“:“%4d“,i*j);,外循环语句,内循环语句,2019/6/26,运行结果,2019/6/26,注意:,while、do-while、for循环语句可以并列,也可以相互嵌套,但要层次清楚,不能出现交叉。 多重循环程序执行时,外层循环每执行一次,内层循环都需要循环执行多次。 例如:,for(a=1;a=10;a+) for (b=0;b=5;b+) ,外循环执行了10次,
34、内循环执行6次 循环正常结束时,内循环执行了106=60次,2019/6/26,3.6.7 循环结构程序设计,【例15】按每行输出5个数的形式输出Fibonacci数列的前20项 。,思路:Fibonacci数列的前几项是:1、1、2、3、5、8、13、21、34、。此数列的变化规律是:,设变量f1、f2和f3,并为f1和f2赋初值1,令f3=f1+f2得到第3项; 将f1f2, f2f3,再求f3=f1+f2得到第4项; 依此类推求第5项、第6项,这是一种递推算法 应采用循环实现,2019/6/26,算法和程序,#define N 20 main( ) int i,f1,f2,f3;f1=f
35、2=1;printf(“n%8d%8d“,f1,f2);for (i=3; i=N; i+) f3=f1+f2;f1=f2; f2=f3;printf(“%8d“,f3);if (i%5=0) printf(“n“); ,2019/6/26,运行结果,2019/6/26,举例,【例16】判断输入的某个数m是否为素数。若是素数,输出“YES”,若不是,输出“NO”。,思路:素数是指只能被1和它本身整除的数,如5、7、11、17、等。,分别用2、3、,m-1尝试能否整除整数m。如果m能被某个数整除,则m就不是素数。,这是一种穷举算法 设除数为j,从2循环到m-1,2019/6/26,算法和程序:,
36、#include “math.h“ main( ) int j,m,k;printf(“Enter an integer number: “);scanf(“%d“, ,2019/6/26,运行结果,2019/6/26,程序的优化,对于穷举法来说,为了提高程序的效率,就要减少尝试次数。,#include “math.h“ main( ) int j,m,k;printf(“Enter an integer number: “);scanf(“%d“, ,思考:如何输出100200中所有的素数,2019/6/26,举例,【例17】用牛顿迭代法求方程2x3+4x2-7x-6=0在x=1.5附近的根
37、。,思路:设xn为一个接近xa的近似根,过(xn, f(xn) 点做切线,切线方程为:,即:,牛顿迭代公式,2019/6/26,算法基本步骤:, 先设一个方程近似根x0,求出方程f的值和方程导数f1的值; f=2x03+4x02-7x0-6 f1=6x02+8x0-7 用迭代公式x=x0-f/f1进行迭代,求出x比x0要接近方程真实的根; 当|x-x0|大于某个很小的数时(如10-6),认为未找到,此时将xx0,再次求f、f1,并迭代,又求出一个新的更接近方程根的x; 一直到 |x-x0|10-6时得到方程近似根:x或x0。,这是一种迭代算法 用循环实现,2019/6/26,算法和程序:,#i
38、nclude “math.h“ main( ) float x,x0,f,f1;x=1.5;do x0=x;f=2*x0*x0*x0+4*x0*x0-7*x0-6;f1=6*x0*x0+8*x0-7;x=x0-f/f1; while(fabs(x-x0)1e-6);printf(“%fn“,x); ,运行jc5_13,2019/6/26,举例,【例17】编程序求210000以内的完全数。,完全数:一个数的因子(除了这个数本身)之和等于该数本身。,思路: 设定i从2变到10000,对每个i找到其因子和s; 判定 is?若相等,则i为完全数,否则不是。,例如:6的因子是1、2、3,因子和 1+2+
39、36 因此 6 是完全数,使用穷举算法 用双层循环实现,2019/6/26,算法和程序:,main( ) int i,j,s;for (i=2; i=10000; i+) s=0;for (j=1; ji; j+)if (i%j=0)s+=j;if (i=s)printf(“%6dn“,s); ,2019/6/26,运行结果,2019/6/26,举例,【例18】编程序,输出以下图形。,*,一共有4 行,每行由空格和星号组成:空格数按行增加,星号按行减少 变量 i 控制输出行数, 从1变化到4 变量 j 控制输出每行的空格和星号: j 从1变化到 i,每次输出一个空格 j 从1变化到 8-(2*i-1),每次输出一个星号,使用双重循环实现,思路:,2019/6/26,算法和程序:,main( ) int i,j;for (i=1; i=4; i+) for (j=1; j=i; j+)printf(“ “);for (j=1;j=8-(2*i-1);j+)printf(“*“);printf(“n“);,思考: 如何输出10行图形? 输出图形向右平移20个字符位置,应如何修改程序?,2019/6/26,运行结果,