




版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
C语言程序设计〔第2版〕第五章本章要点循环的根本概念不同形式的循环控制多重循环问题5.1 程序中需要用循环结构5.2 用while语句和do-while语句实现循环5.3 用for语句实现循环5.4 循环的嵌套5.5 用break语句和continue语句改变循环状态5.6 几种循环的比较5.7 程序举例5.8 提高局部主要内容
5.1程序中需要用循环结构什么是循环?为什么要使用循环?问题1:问题2:求学生平均成绩
分数相加后除以课数在许多问题中需要用到循环控制。循环结构就是用来处理需要重复处理的问题的,所以又称重复结构。它和顺序结构、选择结构共同作为各种复杂程序的根本构造单元。循环分为两种:无休止循环和有终止循环构成有效循环的条件:循环体和循环结束条件5.2用while语句和do-while语句实现循环
5.2.1用while语句实现循环while语句用来实现“当型〞循环结构一般形式:while(表达式)语句当表达式为非0值时,执行while语句中的内嵌语句。其特点是:先判断表达式,后执行循环体,即内嵌语句。例题5.1求1+2+3+…+100的和解题思路(1)开始时使sum的值为0,被加数i第一次取值为1。开始进入循环结构。(2)判别“i≤100〞条件是否满足,由于i小于100,因此“i≤100〞的值为真。所以应当执行其下面矩形框中的操作。(3)执行sum=sum+i,此时sum的值变为1了,然后使i的值加1,i的值变为2了,这是为下一次加2作准备。流程返回菱形框。(4)再次检查“i≤100〞条件是否满足,由于i的值为2,小于100,因此“i≤100〞的值仍为真,所以应执行其下面矩形框中的操作。(5)执行sum=sum+i,由于sum的值已变为1,i的值已变为2,因此执行sum=sum+i后sum的值变为3。再使i的值加1,i的值变为3。流程再返回菱形框。(6)再次检查“i≤100〞条件是否满足……,如此反复执行矩形框中的操作,直到i的值变成了100,把i加到sum中,然后i又加1变成101了。当再次返回菱形框检查“i≤100〞条件时,由于I已是101,大于100,“i≤100〞的值为假,不再执行矩形框中的操作,循环结构结束。5.2用while语句和do-while语句实现循环#include<stdio.h>
voidmain()
{inti,sum=0; /*sum是用来存放累加和的变量*/
/*初值为0*/
i=1;
while(i<=100) /*当I小于或等于100时*/
/*执行下面花括号中的复合语句*/
{sum=sum+i; /*将i的当前值累加到变量sum中*/
i++; /*使i的值加1*/
}
printf(″%d\\n″,sum);
}说明:(1)循环体如果包含一个以上的语句,应该用花括号括起来,以复合语句形式出现.(2)在循环体中应有使循环趋向于结束的语句。运行结果:5050编写程序5.2用while语句和do-while语句实现循环5.2用while语句和do-while语句实现循环
5.2.2用do-while语句实现循环do-while语句的特点:先执行循环体,然后判断循环条件是否成立。执行过程:先执行一次指定的循环体语句,然后判别“表达式〞,当表达式的值为非0(“真〞)时,返回重新执行循环体语句,如此反复,直到表达式的值等于0(“假〞)为止,此时循环结束。while语句和do-while语句的关系:同一个问题既可以用while循环处理,也可以用do-while循环来处理。二者是可以互相转换的。一般形式:
do循环体语句while(表达式);例题5.2求1+2+3+…+100的和
#include<stdio.h>
voidmain()
{inti,sum=0;
i=1;
do/*在循环开始时不检查条件,先执行一次循环体*/
{sum=sum+i;
i++;
}
while(i<=100);
printf("%d\\n″,sum);
}运行结果:5050说明:可以看到,结果和例5.1完全相同。编写程序5.2用while语句和do-while语句实现循环例题5.3募集慈善基金10000元,有假设干人捐款,每输入一个人的捐款数后,计算机就输出当时的捐款总和。当某一次输入捐款数后,总和到达或超过10000元时,即宣告结束,输出最后的累加值。解题思路解此题的思路是设计一个循环结构,在其中输入捐款数,求出累加值,然后检查此时的累加值是否达到或超过预定值,如果到达了,就结束循环操作。5.2用while语句和do-while语句实现循环#include<stdio.h>
voidmain()
{floatamount,sum=0;/*变量sum用来存放累加和*/
do
{scanf("%f",&amount);/*输入一个捐款金额*/
sum=sum+amount;/*求出当前的累加和*/
}while(sum<10000);/*如未达10000元继续循环*/
printf("sum=%9.2f\n",sum);
}运行结果:1000↙(输入捐款额)1850↙1500↙2600↙2500↙1200↙sun=10650.00说明:设计循环结构,要考虑两个问题:一是循环体,二是循环结束条件。注意while循环中判断的条件是循环继续的条件,而不是结束条件。5.2用while语句和do-while语句实现循环编写程序5.3用for语句实现循环
5.3.1for语句的一般形式和执行过程C语言中的for语句使用最为灵活,不仅可以用于循环次数已经确定的情况,而且可以用于循环次数不确定而只给出循环结束条件的情况,它完全可以代替while语句。一般形式:
for(表达式1;表达式2;表达式3)语句5.3用for语句实现循环
5.3.1for语句的一般形式和执行过程for语句的执行过程:(1)先求解表达式1。(2)求解表达式2,假设其值为真(值为非0),那么执行for语句中指定的内嵌语句,然后执行下面第(3)步。假设为假(值为0),那么结束循环,转到第(5)步。(3)求解表达式3。(4)转回上面第(2)步骤继续执行。(5)循环结束,执行for语句下面的一个语句。for语句最简单的形式:for(循环变量赋初值;循环条件;循环变量增值)
例如:for(i=1;i<=100;i++)sum=sum+i;相当于:i=1;while(i<=100){ sum=sum+i; i++; }5.3用for语句实现循环
5.3.1for语句的一般形式和执行过程5.3用for语句实现循环
5.3.2for循环程序举例国王的小麦。相传古代印度国王舍罕要褒赏他的聪明能干的宰相达依尔(国际象棋的创造者),国王问他要什么?达依尔答复说:“国王只要在国际象棋的棋盘第1个格子中放1粒麦子,第2个格子中放2粒麦子,第3个格子中放4粒麦子,以后按此比例每一格加一倍,一直放到第64格(国际象棋的棋盘8*8=64格),我感恩不尽,其他什么都不要了。〞国王想,这有多少!还不容易!让人扛来一袋小麦,但不到一会儿全用没了,再来一袋很快又用完了。结果全印度的粮食全部用完还不够。国王纳闷,怎样也算不清这笔账。现在我们用计算机来算一下。例题5.4解题思路麦子的总粒数是:分别计算出每一格的麦子粒数,把它们加起来,就得到总粒数。据估算,1小麦约有1.42粒,可以计算出小麦的体积。可以用for语句实现循环。5.3用for语句实现循环#include<stdio.h>
voidmain()
{
doublep=1,t=1,v;
inti;
for(i=1;i<64;i++)/*执行63次循环*/
{
p=p*2; /*p是当前一个格子中的麦子粒数*/
t=t+p;/*t是当前麦子总粒数*/
}
v=t/1.42e8;/*v是总体积*/
printf("total=%e\n",t);/*用指数形式输出麦子总粒数*/
printf("volume=%e\n",v);/*用指数形式输出麦子总体积*/
}运行结果:total=1.844674e+019volnme=1.299066e+011编写程序5.3用for语句实现循环说明:变量i用来控制循环的次数,开始时i=1,在完成第1次循环后,i的值加1变为2,由于2<64,所以执行第2次循环,依此类推,当i变到63时,执行最后一次循环,i再变为64,由于i不再小于64了,不再执行循环。接着计算体积,输出结果。5.3用for语句实现循环5.3用for语句实现循环人口增长预测。据2005年末统计,我国人口为130756万人,如果人口的年增长率为1%,请计算到哪一年中国总人口超过15亿。例题5.5解题思路计算人口增长和计算存款利息的公式是相同的。假设原来人口为,那么一年后的人口:其中r是年增长率。用此公式依次计算出每年的人口,每算出一年的人口后就检查一下是否到达或超过15亿?如果未到达或超过15亿,就再计算下一年的人口,直到某一年的人口到达或超过15亿为止。编写程序5.3用for语句实现循环 #include<stdio.h>
voidmain()
{
doublep=1.30756e9,r=0.01;
inty;
for(y=2006;p<1.5e9;y++)
{/*赋值号两侧的变量p代表不同含义*/
p=p*(1+r);
}
printf("year=%d,p=%e\n",y-1,p);
}运行结果:year=2021,p=1.503007e+009说明:注意区分变量p在不同阶段中的不同含义。y代表年份。循环体中只有一个语句,用来计算从2006年开始的各年的人口数。在for语句中设定的循环条件是p<15亿,当某一年的p到达或超过15亿,就停止循环,输出年份和当年的人口数。由于在最后结束循环前y又加了1,因此在输出年份时应输出y-1的值而不是y的值。5.3用for语句实现循环5.3用for语句实现循环
5.3.2for循环程序举例一个变量开始时有一初值,通过一定的运算,可以推算出一个新的值,再从这个新值又推出下一个新值,即不断用计算出的新值去取代原有的值,这种方法称为迭代。上面的计算公式p*(1+r)称为迭代公式。迭代算法一般是用循环来实现的。迭代是一种常用的算法,用人工实现很麻烦,而用计算机实现却十分方便。5.4循环的嵌套一个循环体内又包含另一个完整的循环结构称为循环的嵌套。内嵌的循环中还可以嵌套循环,这就是多层循环。三种循环(while循环、do-while循环和for循环)可以互相嵌套。5.4循环的嵌套下面几种都是合法的形式:(1)
while()(2)do(3)for(;;){…{…{while()dofor(;;){…}{…}{…}}while();}}while();5.4循环的嵌套(4)while()(5)for(;;)(6)do{…{…{…do{…}while()for(;;){}while(){}…{…}…}}}while()
5.5提前结束循环
5.5.1用break语句提前退出循环
break语句可以用来从循环体内跳出循环体,即提前结束循环,接着执行循环下面的语句。一般形式:
break;说明:
break语句不能用于循环语句和switch语句之外的任何其他语句中。
统计各班级的学生的平均成绩。各班人数不等,但都不超过30人。编一个程序能处理人数不等的各班学生的平均成绩。例题5.6解题思路如果各班人数相同,问题比较简单,只需用一个for语句控制即可:for(i=1;i<31;i++)但是现在有的班缺乏30人,应当设法告诉计算机本班的人数,使程序也能统计出该班的平均成绩。可以约定,当输入的成绩是负数时,就表示本班数据已结束(一般情况下成绩不会是负数)。在程序接收到一个负的分数时就提前结束循环,计算出本班平均成绩。用break语句可以用来实现提前结束循环。5.5提前结束循环编写程序5.5提前结束循环#include<stdio.h>
voidmain()
{
floatscore,sum=0,average;
inti,n;
for(i=1;i<31;i++)
{
scanf("%f",&score);/*输入一个学生的成绩*/
if(score<0)break;/*如果输入负值,那么跳出循环*/
sum=sum+score;/*把该成绩累加到sum*/
}
n=i-1;/*学生数应是i-1*/
average=sum/n;/*计算平均成绩*/
/*输出学生数和平均成绩*/
printf("n=%d,average=%7.2f\n",n,average);}运行结果:100↙(输入一个学生成绩)80↙70↙-1↙(输入负数,表示本班数据结束)n=3,average=90.00说明:如果一个班有30人,那么输入完30人的成绩后累计总分后自动结束循环,不必再输入负数作为结束标志。在结束循环后i的值等于31(因为执行完30次循环后,i再加1,变成31,此时才终止循环),因此学生数n应该等于i-1。如果一个班人数少于30人,那么在输入完全班学生的成绩后,输入一个负数,此时程序就跳过循环体其余的语句,也不再继续执行其余的几次循环。直接跳到循环下面的语句(n=i-1;)继续执行。刚输入的数不进行累加(不执行sum=sum+score;)。注意此时i的值,假设已输入了25个有效分数,在第26次循环时输入一个负数,此时i的值是26,而学生数n应是i-1。5.5提前结束循环5.5提前结束循环
5.5.2用continue语句提前结束本次循环continue语句作用为结束本次循环,即跳过循环体中下面尚未执行的语句,接着进行下一次是否执行循环的判定.一般形式:
continue;5.5提前结束循环
5.5.2用continue语句提前结束本次循环continue语句和break语句的区别:
continue语句只结束本次循环,而不是终止整个循环的执行。while(表达式1)
{…
if(表达式2)continue;
…}continue语句和break语句的区别:break语句那么是结束整个循环过程,不再判断执行循环的条件是否成立。
while(表达式1)
{…if(表达式2)break;…}5.5提前结束循环
5.5.2用continue语句提前结束本次循环输入一个班全体学生的成绩,把不及格的学生成绩输出,并求及格学生的平均成绩。例题5.7解题思路在进行循环中,检查学生的成绩,把其中不及格的成绩输出,然后跳过后面总成绩的累加和求平均成绩的语句。用continu语句即可处理此问题。5.5提前结束循环#include<stdio.h>
voidmain()
{
floatscore,sum=0,average;
inti,n=0;
for(i=1;i<6;i++)/*假设有5个学生*/
{
printf("pleaseenterscore:");
scanf("%f",&score);/*输入学生成绩*/
if(score<60)/*如不及格*/
{/*输出不及格的成绩*/
printf("Fail:%7.2f\n",score);
continu;}/*跳过下面的语句,结束本次循环*/
sum=sum+score;
n=n+1;/*n是用来统计及格学生人数*/
}
average=sum/n;/*及格学生平均分数*/
);/*输出及格学生人数和平均分数*/
printf("\nn=%d,average=%7.2f\n",n,average}运行结果:pleaseenterscore:89↙pleaseenterscore:56↙Fail:56pleaseenterscore:76↙pleaseenterscore:58↙Fail:58pleaseenterscore:98↙n=3average=87.675.5提前结束循环编写程序说明:为减少输入量,本程序只按5个学生处理。在输入不及格学生成绩后,输出该成绩,然后跳过循环体中未执行的语句,即不参加累计总分sum,也不累计合格学生数n。但是,继续执行后面的几次循环。5.5提前结束循环5.6几种循环的比较(1)三种循环都可以用来处理同一问题,一般情况下它们可以互相代替。(2)在while循环和do-while循环中,只在while后面的括号内指定循环条件,因此为了使循环能正常结束,应在循环体中包含使循环趋于结束的语句(如i++,或i=i+1等)。5.6几种循环的比较for循环可以在表达式3中包含使循环趋于结束的操作,甚至可以将循环体中的操作全部放到表达式3中。因此for语句的功能更强,凡用while循环能完成的,用for循环都能实现。(3)用while和do-while循环时,循环变量初始化的操作应在while和do-while语句之前完成。而for语句可以在表达式1中实现循环变量的初始化。5.6几种循环的比较(4)while循环、do…while循环和for循环,都可以用break语句跳出循环,用continue语句结束本次循环。
有一对兔子,出生后第3个月起每个月都生一对兔子。小兔子长到第3个月后每个月又生一对兔子。假设所有兔子都不死,问40个月的兔子总数为多少?例题5.8解题思路5.7程序举例
第几个月小兔子对数中兔子对数老兔子对数兔子总数110012010131012411135212563238753513┆┆┆┆┆可以看到每个月的兔子总数依次为1,1,2,3,5,8,13…这就是有名的费波那西(Fibonacci)数列。
5.7程序举例
编写程序5.7程序举例
#include<stdio.h>
voidmain()
{
longintf1,f2;
inti;
f1=1;f2=1;
for(i=1;i<=20;i++)
{
printf("%12ld%12ld",f1,f2);
if(i%2==0)printf("\n");
f1=f1+f2;
f2=f2+f1;
}
}运行结果:
11235813213455891442333776109871597258441816765109461771128657463687502512139319641831781151422983204013462692178309352457857022887922746514930352241578173908816963245986102334155说明:(1)变量f1和f2用长整型,在printf函数中输出格式符用“%12ld〞,而不是用“%12d〞,这是由于在第23个数后,整数值已超过整数最大值32767,因此必须用长整型变量才能容纳,并用“%ld〞格式输出。(2)if语句的作用是使输出4个数后换行。i是循环变量,当i为偶数时换行,而i每增值1,就要计算和输出2个数(f1,f2),因此i每隔2换一次行相当于每输出4个数后换行输出。5.7程序举例
给一个整数m,判断它是否素数。例题5.9解题思路5.7程序举例
让m被i(i由2变到k=)除,如果m能被某一个i(2~k之间的任何一个整数)整除,那么m必然不是素数,不必再进行下去。此时的i必然小于或等于k;如果m不能被2-k之间的任一整数整除,那么m应是素数,此肘在完成最后一次循环后,使i再加1,因此i的值就等于k+1,这时才终止循环。在循环结束之后判别i的值是否大于或等于k+1,假设是,那么说明未曾被2-k之间任一整数整除过,因此输出“是素数〞。#include<stdio.h>
#include<math.h>
voidmain()
{intm,i,k;
printf(“pleaseenteraintegernumber:〞);
scanf(“%d〞,&m);/*输入一个整数m*/
k=(int)sqrt(m);/*对m求平方根,再取整*/
for(i=2;i<=k;i++)/*i作为除数*/
/*如果m被i整除,m肯定不是素数*/
if(m%i==0)break;
if(i>k)printf("%disaprimenumber.\n",m);
elseprintf("%disnotaprimenumber.\n",m);
}编写程序5.7程序举例
运行结果:
pleaseenteraintegernumber:17↙17isaprimenumber.译密码。为使电文保密,往往按一定规律将其转换成密码,收报人再按约定的规律将其译回原文。例题5.10解题思路5.7程序举例
可以按以下规律将电文变成密码:将字母A变成字母E,a变成e,即变成其后的第4个字母,W变成A,X变成B,Y变成C,Z变成D。#include<stdio.h>
voidmain()
{charc;
while((c=getchar())!=‘\n’)
{/*判定c是否字母*/
if((c>=‘a'&&c<='z')||(c>='A'&&c<='Z'))
{c=c+4;/*是字母就加4*/
/*如在字母范围外就减26*/
if(c>'Z'&&c<='Z'+4||c>'z')c=c-26;
}
printf("%c",c);
}
printf("\n");
}编写程序5.7程序举例
运行结果:
China!↙Glmre!
说明:内嵌的if语句不能写成:if(c>’Z’||c>’z’)/*请和程序笫7行比较*/c=c-26;因为如果所有小写字毋都满足“c>′Z′〞的条件,从而也都执行“c=c-26;〞语句,这就会出错。因此必须限制其范围为“c>′Z′&&c<=′Z′+4〞,即原字母为W到Z。只有符合此条件才减26,否那么,不应按此规律转换。5.7程序举例
5.8提高局部
5.8.1while和do-while循环的比较但凡能用while循环处理,都能用do…while循环处理。do…while循环结构可以转换成while循环结构。在一般情况下,用while语句和用do-while语句处理同一问题时,假设二者的循环体局部是一样的,它们的结果也一样。但是如果while后面的表达式一开始就为假(0值)时,两种循环的结果是不同的。例5.11while和do-while循环的比较
(1)(2)
#include<stdio.h>#include<stdio.h>
voidmain()voidmain()
{intsum=0,i;{intsum=0,i;
scanf(“%d″,&i);scanf(〞%d″,&i);
while(i<=10)do
{sum=sum+I;{sum=sum+i;
i++;i++;
}}while(i<=10);
printf(“sum=%d\\n〞,printf(“sum=%d\\n〞,
sum);sum);
}}运行结果:1↙sum=55再运行一次:11↙sum=0运行结果:1↙sum=55再运行一次:11↙sum=11说明:当while后面的表达式的第一次的值为“真〞时,两种循环得到的结果相同。否那么,二者结果不相同。5.8提高局部5.8提高局部
5.8.2for语句的各种形式for语句相当灵活,形式变化多样:(1)for语句的一般形式中的“表达式1〞可以省略,此时应在for语句之前给循环变量赋初值。注意省略表达式1时,其后的分号不能省略。如:for(;i<=100;i++)sum=sum+i;执行时,跳过“求解表达式1〞这一步,其他不变。(2)如果表达式2省略,即不判断循环条件,循环无终止地进行下去。也就是认为表达式2始终为真。如:for(i=1;;i++)sum=sum+i;表达式1是一个赋值表达式,表达式2空缺。它相当于:
i=1;while(1){sum=sum+1;i++;}5.8提高局部
5.8.2for语句的各种形式(3)表达式3也可以省略,但此时程序设计者应另外设法保证循环能正常结束。如:for(i=1;i<=100;){sum=sum+i;i++;}在上面的for语句中只有表达式1和表达式2,而没有表达式3。i++的操作不放在for语句的表达式3的位置处,而作为循环体的一局部,效果是一样的,都能使循环正常结束。5.8提高局部
5.8.2for语句的各种形式(4)可以省略表达式1和表达式3,只有表达式2,即只给循环条件。如:
for(;i<=100;)while(i<=100){sum=sum+i;相当于
{sum=sum+i;i++;}i++;}
在这种情况下,完全等同于while语句。可见for语句比while语句功能强,除了可以给出循环条件外,还可以赋初值,使循环变量自动增值等。5.8提高局部
5.8.2for语句的各种形式(5)3个表达式都可省略,如:
for(;;)语句相当于
while(1)语句
即不设初值,不判断条件(认为表达式2为真值),循环变量不增值。无终止地执行循环体。5.8提高局部
5.8.2for语句的各种形式(6)表达式1可以是设置循环变量初值的赋值表达式,也可以是与循环变量无关的其他表达式。如:for(sum=0;i<=100;i++)sum=sum+i;表达式3也可以是与循环控制无关的任意表达式。5.8提高局部
5.8.2for语句的各种形式表达式1和表达式3可以是一个简单的表达式,也可以是逗号表达式,即包含一个以上的简单表达式,中间用逗号间隔。如:
for(sum=0,i=1;i<=100;i++)sum=sum+i;或for(i=0,j=100;i<=j;i++,j--)k=i+j;表达式1和表达式3都是逗号表达式,各包含两个赋值表达式,即同时设两个初值,使两个变量增值。
5.8提高局部
5.8.2for语句的各种形式
在逗号表达式内按自左至右顺序求解,整个逗号表达式的值为其中最右边的表达式的值。如:
for(i=1;i<=100;i++,i++)sum=sum+i;相当于
for(i=1;i<=100;i=i+2)sum=sum+i;5.8提高局部
5.8.2for语句的各种形式(7)表达式一般是关系表达式(如i<=100)或逻辑表达式(如a<b&&x<y),但也可以是数值表达式或字符表达式,只要其值为非零,就执行循环体。5.8提高局部
5.8.2for语句的各种形式①for(i=0;(c=getchar())!=′\n′;i+=c);在表达式2中先从终端接收一个字符赋给c,然后判断此赋值表达式的值是否不等于′\n′(换行符),如果不等于′\n′,就执行循环体。注意:此for语句的循环体为空语句,把本来要在循环体内处理的内容放在表达式3中,作用是一样的。可见for语句功能强,可以在表达式中完本钱来应在循环体内完成的操作。5.8提高局部
5.8.2for语句的各种形式②for(;(c=getchar())!=′\n′;)printf(″%c″,c);for语句中只有表达式2,而无表达式1和表达式3。其作用是每读入一个字符后立即输出该字符,直到输入一个“换行〞为止。请注意,从终端键盘向计算机输入时,是在按Enter键以后才将一批数据一起送到内存缓冲区中去的。运行情况:Computer↙(输入)Computer(输出)而不是Ccoommppuutteerr5.8提高局部
5.8.2for语句的各种形式注意:C语言中的for语句比其他语言(如BASIC,PASCAL)中的FOR语句功能强得多。可以把循环体和一些与循环控制无关的操作也作为表达式1或表达式3出现,这样程序可以短小简洁。但过分地利用这一特点会使for语句显得杂乱,可读性降低,最好不要把与循环控制无关的内容放到for语句中。5.8提高局部
5.8.2for语句的各种形式第六章问题:给一组数排序,这组数该如何存放呢???这些数据如何存放才便于排序82945637617188888888881111111111111118888888888?这便是本章所要解决的问题
本章要点掌握一维、二维数组的定义和引用方法、存储结构和初始化方法。掌握有关一维数组的有关算法掌握数组的运算。主要内容6.1为什么要用数组6.2定义和引用一维数组6.3二维数组的定义和引用6.4字符数组6.5提高局部6.1为什么要用数组
C语言为这些数据,提供了一种构造数据类型:数组。所谓数组就是一组具有相同数据类型的数据的有序集合。一个班学生的学习成绩一行文字一个矩阵这些数据的特点是:1、具有相同的数据类型2、使用过程中需要保存原始数据1.一维数组的定义格式为:类型说明符数组名[常量表达式];例如:inta[10];它表示定义了一个整形数组,数组名为a,此数组有10个元素。6.2定义和引用一维数组6.2.1定义一维数组说明:1.数组名定名规那么和变量名相同,遵循标识符定名规那么。2.在定义数组时,需要指定数组中元素的个数,方括弧中的常量表达式用来表示元素的个数,即数组长度。3.常量表达式中可以包括常量和符号常量,但不能包含变量。也就是说,C语言不允许对数组的大小作动态定义,即数组的大小不依赖于程序运行过程中变量的值。例如:
intn;scanf(“%d″,&n);/*在程序中临时输入数组的大小*/inta[n];数组说明中其他常见的错误:①floata[0]; /*数组大小为0没有意义*/②intb(2)(3);
/*不能使用圆括号*/③intk,a[k];
/*不能用变量说明数组大小*/
注意:定义数组时用到的“数组名[常量表达式]〞和引用数组元素时用到的“数组名[下标]〞是有区别的。例如∶inta[10];t=a[6];6.2一维数组的定义和引用6.2.2引用一维数组元素1.数组元素的引用方式:数组名[下标]下标可以是整型常量或整型表达式。例如:a[0]=a[5]+a[7]-a[2*3]2.一维数组元素引用的程序实例例题6.1引用数组元素。利用循环给数组元素a[0]~a[9]赋值为0~9,然后按逆序输出各元素的值解题思路循环给数组元素a[0]~a[9]赋值0~9,这样,然后按a[9]到a[0]的顺序输出各元素的值。2.一维数组元素引用的程序实例#include<stdio.h>voidmain()
{inti,a[10];for(i=0;i<=9;i++)a[i]=i;for(i=9;i>=0;i--)printf("%d″,a[i]);printf("\n″);}
运行结果如下:9876543210
说明:1、第一个for循环的作用是给a数组中的元素赋值。2、第2个for循环的作用是所按逆序输出a数组中的10个元素编写程序对数组元素初始化的实现方法:
1.在定义数组时对数组元素赋以初值。例如:inta[10]={0,1,2,3,4,5,6,7,8,9};将数组元素的初值依次放在一对花括弧内。经过上面的定义和初始化之后,a[0]=0,a[1]=1,a[2]=2,a[3]=3,a[4]=4,a[5]=5,a[6]=6,a[7]=7,a[8]=8,a[9]=9。
6.2一维数组的定义和引用6.2.3一维数组的初始化
3.如果想使一个数组中全部元素值为0,可以写成:
inta[10]={0,0,0,0,0,0,0,0,0,0};或
inta[10]={0};2.可以只给一局部元素赋值。例如:inta[10]={0,1,2,3,4};定义a数组有10个元素,但花括弧内只提供5个初值,这表示只给前面5个元素赋初值,后5个元素值为0。4.在对全部数组元素赋初值时,由于数据的个数已经确定,因此可以不指定数组长度。
例如:inta[5]={1,2,3,4,5};也可以写成
inta[]={1,2,3,4,5};
inta[10]={1,2,3,4,5};只初始化前5个元素,后5个元素为0。Fibonacci数列公式::a1=a2=1,an=an-1+an-2即:1,1,2,3,5,8,13建立一个数组,将数列中第1个数放在数组第1个的元素中,数列第2个数放在数组第2个的元素中,……。6.2一维数组的定义和引用6.2.4一维数组程序举例例题6.2
用数组来处理求Fibonacci数列问题。
解题思路程序实例:#include<stdio.h>voidmain(){inti;intf[20]={1,1};6.2一维数组的定义和引用6.2.4一维数组程序举例编写程序for(i=2;i<20;i++)f[i]=f[i-2]+f[i-1];for(i=0;i<20;i++){if(i%5==0)printf(″\n″);printf(″%12d″,f[i])}/*For循环结束*/}/*程序结束*/运行结果如下:
11235813213455891442333776109871597258441816765if语句用来控制换行,每行输出5个数据。例题6.3假设有n个人,各人年龄不同,希望按年龄将他们从小到大排列。解题思路这种问题称为数的排序(sort)。排序的原那么有两类,一类是“升序〞,从小到大;一类是“降序〞,从大到小。我们可以把这个题目抽象为一般形式:对n个数按升序排列对一组数据进行排序的方法很多,本例介绍用“起泡法〞排序。“起泡法〞的思路是如下第一趟比较经过第一趟(共5次比较与交换)后,最大的数9已“沉底〞。然后进行对余下的前面5个数第二趟比较,第二趟比较如果有n个数,那么要进行n-1趟比较。在第1趟比较中要进行n-1次两两比较,在第j趟比较中要进行n-j次两两比较。程序流程图如下:#include<stdio.h>voidmain(){inta[10];inti,j,t;printf(″input10numbers:\n″);
for(i=0;i<10;i++)scanf("%d",&a[i]);printf("\n");
编写程序for(j=0;j<9;j++)for(i=0;i<9-j;i++)if(a[i]>a[i+1]){t=a[i];a[i]=a[i+1];a[i+1]=t;}printf(″thesortednumbers:\n″);for(i=0;i<10;i++)printf(″%d″,a[i]);printf(″\n″);}/*程序结束*/程序运行结果如下:input10numbers:10481265-76100-45123↙thesortednumbers:-76-4501481265100123说明:1、程序中实现起泡法排序算法的主要是10~13行。2、仔细分析嵌套的for语句。
6.3
二维数组的定义和引用
6.3.1定义二维数组二维数组定义的一般形式为类型说明符数组名[常量表达式][常量表达式];例如:定义a为3×4(3行4列)的数组,b为5×10(5行10列)的数组。如下:floata[3][4],b[5][10];不能写成
floata[3,4],b[5,10];C语言中,二维数组中元素排列的顺序是按行存放的,即在内存中先顺序存放第一行的元素,再存放第二行的元素。以下图表示对a[3][4]数组存放的顺序。a00a01a02a03
a10a11a12a13a20a21a22a23
6.3
二维数组的定义和引用
6.3.1定义二维数组二维数组元素的表示形式为:数组名[下标][下标]例如:a[2][3]下标可以是整型表达式,如a[2-1][2*2-1]数组元素可以出现在表达式中,也可以被赋值例如:b[1][2]=a[2][3]/2不要写成a[2,3],a[2-1,2*2-1]形式6.3二维数组的定义和引用
6.3.2引用二维数组的元素常出现的错误有:
inta[3][4];
/*定义a为3×4的数组*/
┆a[3][4]=3;
在使用数组元素时,应该注意下标值应在已定义的数组大小的范围内。6.3二维数组的定义和引用
6.3.2引用二维数组的元素可以用下面4种方法对二维数组初始化:1.分行给二维数组赋初值。例如:
inta[3][4]={{1,2,3,4},{5,6,7,8},{9,10,11,12}};2.可以将所有数据写在一个花括弧内,按数组排列的顺序对各元素赋初值。例如:inta[3][4]={1,2,3,4,5,6,7,8,9,10,11,12};
6.3二维数组的定义和引用
6.3.3二维数组的初始化3.可以对局部元素赋初值。例如:inta[3][4]={{1},{5},{9}};100050009000也可以对各行中的某一元素赋初值,如inta[3][4]={{1},{0,6},{0,0,11}};
100006000
0011
100056000000也可以只对某几行元素赋初值。如:inta[3][4]={{1},{5,6}};
4.如果对全部元素都赋初值,那么定义数组时对第一维的长度可以不指定,但第二维的长度不能省。例如:inta[3][4]={1,2,3,4,5,6,7,8,9,10,11,12};它等价于:inta[][4]={1,2,3,4,5,6,7,8,9,10,11,12};在定义时也可以只对局部元素赋初值而省略第一维的长度,但应分行赋初值。例如:inta[][4]={{0,0,3},{},{0,10}};0030000001000
6.3二维数组的定义和引用
6.3.4二维数组程序举例例如:a=12314456b=2536例题6.4将一个二维数组a的行和列的元素互换(即行列转置),存到另一个二维数组b中。
解题思路将a数组中第i行j列元素赋给b数组中j行i列元素,例如a[0][0]赋给b[0][0],a[0][1]赋给b[1][0],a[0][2]赋给b[2][0],……。可以用双层循环来处理,用外循环控制行的变化,内循环控制列的变化。
6.3二维数组的定义和引用
6.3.4二维数组程序举例#include<stdio.h>voidmain(){inta[2][3]={{1,2,3},{4,5,6}};intb[3][2],i,j;printf(″arraya:\n″);for(i=0;i<=1;i++){for(j=0;j<=2;j++){
编写程序
printf(″%5d″,a[i][j]);b[j][i]=a[i][j];}printf(″\n″);}printf(″arrayb:\n″);for(i=0;i<=2;i++){for(j=0;j<=1;j++)printf("%5d″,b[i][j]);printf(″\n″);}}/*程序结束*/运行结果如下:arraya:123456arrayb:1425
3
6
说明:如果把第7行:“for(i=0;i<2;i++)〞改为“for(i=0;i<=2;i++)〞,意味着什么?结果会怎样?例题6.5
有一个班30个学生,己知每个学生有5门课的成绩,要求输出平均成绩最高的学生的成绩以及该学生的序号。
解题思路对此题而言,宜用二维数组,用一行中的各元素存放一个学生的成绩,即行代表学生,列代表一门课的成绩。要存放30个学生5门课的成绩,要用一个30*5的二维数组。另外,由于要比较各人的平均成绩,因此,对每个学生来说,应该存放6个数据,每人平均成绩要计算出来,并存放在数组中。这样,数组的大小就应该是30*6。设计算法:(1)求每人平均成绩,放在数组每一行的最后一列中;(2)找出最高的平均分,和该学生的序号;(3)输出最高的平均分,和该学生的序号。程序如下:
#include<stdio.h>voidmain(){inti,j,max_i;floatsum,max=0;floats[6][6]={{78,82,93,74,65},{91,82,72,76,67},{100,90,85,72,98},{67,89,90,65,78},{77,88,99,45,89},{78,89,76,99.97}};for(i=0;i<5;i++){sum=0;/*使sum初值为0*/for(j=0;j<5;j++)sum=sum+s[i][j];/*累加序号为j的学生各门课的成绩*
s[i][5]=sum/5;}/*求序号为j的学生各门课的的平均分*/
编写程序for(i=0;i<5;i++)if(s[i][5]>max)/*逐个将5个学生的平均分与max比较*/{max=s[i][5];max_i=i;}/*如果比max大,就用序号为i的学生的平均分取代max的原值,将i的当前值保存在max_I中*/printf("stu_order=%d\nmax=%7.2f\n",max_i,max);/*输出最高平均分和该生的序号i*/}运行结果如下:max=10,row=2,colum=1
说明:1、在对数组初始化时,只对各行的前5列赋初值,第6列默认为0。2、注意第一个for语句的范围。请思考能否不要“sum=0;〞这一行?或者把这一句改放到for语句的前面?3、第三个for语句内嵌了一个if语句,用来将5个学生的平均分逐个与max比较6.4
字符数组
6.4.1定义字符数组及对其初始化定义方法与前面介绍的类似。例如:charc[10];c[0]=′I′;c[1]=′′;c[2]=′a′;c[3]=′m′;c[4]=′′;c[5]=′h′;c[6]=′a′;c[7]=′p′;c[8]=′p′;c[9]=′y′;对字符数组初始化,可逐个字符赋给数组中各元素。例如:charc[10]={‘I’,’a’,’m’,’h’,’a’,’p’,’p’,’y’}6.4字符数组
6.4.1定义字符数组及对其初始化如果初值个数小于数组长度,那么只将这些字符赋给数组中前面那些元素,其余的元素自动定为空字符。charc[10]={′c′,′′,′p′,′r′,′o′,′g′,′r′,′a′,′m′};如果提供的初值个数与预定的数组长度相同,在定义时可以省略数组长度,系统会自动根据初值个数确定数组长度。charc[]={′I′,′′,′a′,′m′,′′,′h′,′a′,′p′,′p′,′y′};数组c的长度自动定为10。
chardiamond[5][5]={{′′,′′,*′},{′′,′*′,′′,′*′},{′*′,′′,′′,′′,′*′},{′′,′*′,′′,′*′},{′′,′′,′*′}}定义和初始化一个二维字符数组
6.4字符数组
6.4.2引用字符数组例题6.6输出一个菱形图解题思路先画出准备输出的菱形字符图案,它应当是5行5列,然后逐行写出其中的字符,如第1行应由2个空格字符、一个‘*’和2个空格字符组成。第2行由1个空格字符、‘*’、2个空格字符、‘*’和2个空格字符组成。依此类推。把这些字符作为初值赋给c数组。
#include<stdio.h>voidmain(){chardiamond[][5]={{′′,′′,′*′},{′′,′*′,′′,′*′},{′*′,′′,′′,′′,′*′},{′′,′*′,′′,′*′},{′′,′′,′*′}};inti,j;for(i=0;i<5;i++){for(j=0;j<5;j++)printf(″%c″,diamond[i][j]);printf(″\n″);}}运行结果
********编写程序说明:请注意怎样构成一个菱形字符数组6.4字符数组
字符串和字符串结束标志为了测定字符串的实际长度,C语言规定了一个“字符串结束标志〞——‘\0’。字符数组并不要求它的最后一个字符为′\0′,甚至可以不包含′\0′。例如:charc[5]={′C′,′h′,′i′,′n′,′a′};但是由于系统对字符串常量自动加一个′\0′。因此,为了使处理方法一致,在字符数组中也常人为地加上一个′\0′。例如:charc[6]={′C′,′h′,′i′,′n′,′a′,′\0′};6.4字符数组
字符串和字符串结束标志例如:定义了如下的字符数组∶charc[]={“Pascalprogram〞};现在,想用一个新的字符串代替原有的字符串〞Pascalprogram〞,从键盘向字符数组输入∶Hello如果不加′\0′的话,字符数组中的字符如下∶Hellolprogram6.4字符数组
字符串和字符串结束标志6.4字符数组
6.4.4字符数组的输入输出
字符数组的输入输出可以有两种方法:逐个字符输入输出。用格式符“%c〞输入或输出一个字符。将整个字符串一次输入或输出。用“%s〞格式符,意思是对字符串的输入输出。charc[]={″China″};printf(″%s″,c);
例如在内存中数组c的状态说明:1.输出字符不包括结束符′\0′。2.用“%s〞格式符输出字符串时,printf函数中的输出项是字符数组名,而不是数组元素名。3.如果数组长度大于字符串实际长度,也只输出到遇′\0′结束。4.如果一个字符数组中包含一个以上′\0′,那么遇第一个′\0′时输出就结束。5.可以用scanf函数输入一个字符串。如果利用一个scanf函数输入多个字符串,那么在输入时以空格分隔。例如:charstrl[5],str2[5],str3[5];scanf(″%s%s%s″,str1,str2,str3);输入数据:Howareyou?数组中未被赋值的元素的值自动置′\0′。分析图中所示的字符数组用8进制形式输出数组c的起始地址printf(″%o″,c);
printf(″%s″,c);6.scanf函数中的输入项如果字符数组名。不要再加地址符&,因为在C语言中数组名代表该数组的起始地址。下面写法不对:scanf(″%s″,&str);在程序中往往需要对字符串作某些操作处理,如把两个字符串连接起来、将两个字符串进行比较等,在C函数库中提供了一些字符串处理函数,用来实现以上功能,使用很方便。下表列出几种常用的函数。6.4字符数组字符串处理函数
函数形式功能gets(字符数组)从终端输入一个字符串到字符数组puts(字符数组)将一个字符串(以′\0′结束的字符序列)输出到终端strcat(字符数组1,字符数组2)连接两个字符数组中的字符串把字符串2接到字符串1的后面strcpy(字符数组1,字符串2)将字符串2复制到字符数组1中去strcmp(字符串1,字符串2)比较字符串1和字符串2。如果字符串1=字符串2,则函数值为0。(2)如果字符串1>字符串2,则函数值为一个正整数。(3)如果字符串1<字符串2,则函数值为一个负整数。strlen(字符数组)测试字符串长度strlwr(字符串)将字符串中大写字母换成小写字母strupr(字符串)将字符串中小写字母换成大写字母6.4字符数组6.4.6字符数组应用举例
例题6.7有3个字符串,要求找出其中最大者解题思路在字符串比较中,所谓“大〞者是指按英文字典的排列,在后面出现的为大。把str[0]、str[1]、str[2]看作3个一维字符数组,如同一维数组那样进行处理。今用gets函数分别读入3个字符串。经过两次比较,就可得到值最大者,把它放在一维字符数组string中。程序如下:#include<stdio.h>#include<string.h>voidmain(){charstring[20];charstr[3][20];inti;for(i=0;i<3;i++)gets(str[i]);编写程序if(strcmp(str[0],str[1])>0)strcpy(string,str[0])elsestrcpy(string,str[1]);if(strcmp(str[2],string)>0)strcpy(string,str[2]);printf(″\nthelargeststringis∶\n%s\n″,string);}编写程序运行结果如下:CHINA↙HOLLAND↙AMERICA↙
thelargeststringis∶HOLLAND说明:
1、在使用字符串函数时要在本程序的开头要用#include<string.h>将头文件<string.h>包含进来。2、在输入以上国名字符串时,字母前不加空格3、这个题目也可以不采用二维数组,而设3个一维字符数组来处理。
6.4字符数组6.4.6字符数组应用举例
例题6.8输入一行字符,统计其中有多少个单词,单词之间用空格分隔开。
6.4字符数组6.4.6字符数组应用举例
解题思路程序如下:
#in
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 关于打假合同标准文本
- 产品采购合作合同标准文本
- 个人提供保证合同标准文本
- 保温打包合同标准文本
- 产品定金供货合同标准文本
- 感恩父母的心理健康教育
- 保本保息理财合同标准文本
- 学习心得体会(3篇)
- 休闲食品分销合同标准文本
- 兑店合同标准文本版
- GB/T 45083-2024再生资源分拣中心建设和管理规范
- 2024年3月天津高考英语第一次高考真题(原卷版)
- 有趣的汉字《甲骨文》课件
- 九三学社申请入社人员简历表
- 大型设备的吊装技术课件
- 各种网络安全设备巡检报告汇总
- 爱美的小公鸡(共22张)课件
- 碳酸丙烯酯法脱碳工艺工程设计
- 丽声北极星分级绘本第三级下 A Long Wait课件
- 沥青路面工程施工监理细则
- 不稳定性心绞痛和非ST段抬高心肌梗死诊断与治疗指南(全文)
评论
0/150
提交评论