C语言典例.docx
C语言典例C语言必会典例 一:for循环与break语句if语句的应用 例子1: /* 从键盘输入一个大于1的正整数,判断其是否是素数 */ #include<stdio.h> void main int i,x; int flag=1; printf("请输入一个正整数x="); scanf("%d",&x); for(i=2;i<x;i+)/注意循环条件千万不能写i<=x if(x%i=0)/注意是x%i,这个数是被除数 flag=0; break; if(flag=0)/如果不定义flag,就是if(x=i);则是素数,否则不是 printf("%d不是素数n",x); else printf("%d是素数n",x); /* 总结:如果是素数,i就一直加i=x(此时x%i!=0)从而不满足i<x而跳出循环 */ 如果不是素数,i会加到总有一个值满足if语句中的条件后执行break而跳出 例子2: /*输出100以内的素数*/ #include<stdio.h> void main int i,j; int flag;/第5行 for(i=2;i<=100;i+) flag=1;/注意只能在此地初始化保证每判断一次重新给flag置1,千万不能在第 5行初始化 for(j=2;j<i;j+)/判断是否是素数,注意循环条件不能取等号 if(i%j=0) flag=0; break;/跳出的是隔它最近的循环,而不是if语句,只不过常与if连用 if(flag=1)/如果是素数就输出,进而再进入大for语句寻在下一个素数 printf("%-3d",i); printf("n");/换行 例子3 /*输出500以内的最大的10个素数及其和*/ #include<stdio.h> void main int i,j,flag,counter=0,sum=0;/counter一定要给初值 for(i=500;i>=2;i-)/注意倒过来输出 flag=1;/注意只能在此地初始化保证每判断一次重新给flag置1,千万不能在第 5行初始化 for(j=2;j<i;j+) if(i%j=0) flag=0;/不是素数flag一定记0 break; if(flag=1) counter+;/如果是素数,进来counter加一次 if(counter<=10)/判断输出前十个 sum=sum+i; printf("%-4d",i); printf("n");/换行 printf("sum=%4dn",sum); 例子4 参考上机实验第二题 /* 分析:其实程序把500以内的每个数都判断了一遍,但在屏幕上置只输出后10个,这与上机实验的方法二思维方式不同,具体的几种方法请参考它。 */ 二:for循环与一维数组的应用 例子1 /*从键盘输入10(适用人数不确定)个同学的成绩,输出高于平均成绩的人数*/ #include<stdio.h> #define LEN 100 void main int dataLEN,i,len;/定义一个长度为LEN的数组 int sum=0,counter=0;/两者一定要给初始化,因为不是静态变量默认值不是0,而是 垃圾值 float ave; printf("请输入学生人数:");/这两句可以不要,成绩个数直接用LEN表示和改 scanf("%dn",&len);/取地址符千万不能掉 for(i=0;i<len;i+) scanf("%d",&datai);/取地址符千万不能掉 sum=sum+datai;/有时在输入数据时就对数据进行相关的处理较好 /ave=sum*1.0/len;/可以把平均成绩输出来检查结果 /printf("%.2fn",ave); for(i=0;i<len;i+) if(datai>ave) counter+; printf("高于平均成绩的人数为:%d个n",counter); 例子2 /* 从键盘输入若干个学生成绩,当输入负数时结 束,计平均成绩,并输出低于平均分的学生成绩 */ #include <stdio.h> #define LEN 1000 void main int i,len,scoreLEN; float average=0,sum=0;/一定要初始化 printf("请输入学生的人数:"); scanf("%d",&len);/ &符号不要掉 for(i=0;i<len;i+) scanf("%d",&scorei);/&符号不要掉 sum=sum+scorei; average=sum/len; for(i=0;i<len;i+) if(scorei<0) printf("有无效成绩,程序结束,请重新输入n"); break;/巧妙之处 if(scorei<average) printf("低于平均分学生的成绩为:%dn",scorei); for循环与二维数组的应用 例子1 /*将一个二维数组的行和列的元素互换,存到另一个二维数组中(求转置矩阵)*/ #include<stdio.h> void main int a23=1,2,3,4,5,6; int b32,i,j; printf("array a:n"); for(i=0;i<2;i+)/输出数组a for(j=0;j<3;j+) printf("%3d",aij); printf("n");/每输出一行就换行 for(i=0;i<2;i+)/转置 for(j=0;j<3;j+) bji=aij; printf("array b:n"); for(j=0;j<3;j+)/输出转置后的数组b for(i=0;i<2;i+)/注意这里可以用别的变量如j上面用i,也可以用其他定义除 a,b的变量 printf("%3d",bji); printf("n"); 例子2 /*从键盘输入5个学生的3门课程的成绩,并计算出学生3门课程的平均成绩*/ #include<stdio.h> void main int data54,i,j; int sum; float ave5; for(i=0;i<5;i+) sum=0; printf("请输入第%d个同学的三门课程的成绩:",i+1);/注意是i+1,不能在外面 for(j=0;j<3;j+) scanf("%d",&dataij);/注意“&” sum=sum+dataij;/本例是在输入数据时就对数据进行相关的处理,包括 下一句 avei=sum*1.0/3;/注意是float型 for(i=0;i<5;i+) printf("第%d个同学的平均成绩为%.2fn",i+1,avei); 例子3 /*从键盘输入5个学生的3门课程的成绩,并计算出学生3门课程的平均成绩*/ #include<stdio.h> void main int data54,i,j; float ave5=0;/初始化,全给0 for(i=0;i<5;i+) printf("请输入第%d个同学的三门课程的成绩:",i+1);/注意i+1,不能在外面 for(j=0;j<3;j+) scanf("%d",&dataij);/注意"&" for(i=0;i<5;i+)/输出时专门用于计算的双重循环 for(j=0;j<3;j+) avei=avei+dataij; avei=avei/3;/不能在大for语句的外面 for(i=0;i<5;i+)/专门的输出循环 printf("第%d个同学的平均成绩为%.2fn",i+1,avei); 例子4 参考上机实验的第二题 /* 总结:与上例1相比显然要复杂些,但我们应该注意以下3点: 有时在输入数据时就对数据进行相关的处理的话要方便。 有时要在输出数据才对数据进行相关的处理就比较好。 具体考虑那种,要视情况而定,一种不行就换另一种。 */ 三:数组的越界问题未考虑下标的变化范围 例子1 /*从键盘输入10个成绩,并将最低分存放到最后一个数组元素中*/ #include<stdio.h> void main int data10,i,t;/定义一个中间变量t,相当于一个空箱子 printf("请输入10个成绩:"); for(i=0;i<10;i+) scanf("%d",&datai); for(i=0;i<9;i+)/千万注意:i<9;千万不能是i<10;因为当i=9时,datai+1的 下标是10,,超出了数组data的允许下标范围。 if(datai<datai+1) t=datai; datai=datai+1; datai+1=t; printf("%dn",data9); 附注:还有输入数据错误而造成数组的越界问题处理叫较简单,只是在输出或输入数据时用if语句判断一下,如果不符合数据要求常采用break跳出循环。 数组数据的排序问题冒泡法 冒泡法是假如有n个数,则需要 进行n-1轮的冒泡,在第一轮冒泡的比较中要进行n-1次两两比较,在第i轮冒泡中要进行n-i次两两比较。 例1中的10个数进行9轮比较,所以a<9,不能取等号,因为从0开始,而每结束一轮冒泡后就减少一个数的比较,从而得到一个新的冒泡范围。所以在第a轮冒中则要进行10-a次两两比较,所以j<9-a,注意不能取等号,也不是10-i,因为j是从0开始。 例子1 /*从键盘输入10个成绩,按从小到大的顺序输出成绩*/ #include<stdio.h> void main int a,i,j,t,data10;/也可以不定义变量a printf("请输入10个成绩:"); for(i=0;i<10;i+) scanf("%d",&datai); for(a=0;a<9;a+)/控制冒泡轮数,如果不定义a也可以用i以节省变量但不能用j for(j=0;j<9-a;j+)/控制每轮冒泡所比较的次数,这里的循环条件不能取等号 if(dataj+1<dataj)/注意方向,是从小到大还是从大到小,还有下标是j t=dataj; dataj=dataj+1; dataj+1=t; for(i=0;i<10;i+) printf("%-3d",datai); printf("n"); 例子2 /*输入十个成绩,输出最高分和最低分,如果有无效成绩就把这无效成绩输出来*/ #include<stdio.h> void main int data110,data210,i,j,k=0,t; printf("请输入十个成绩:"); for(i=0;i<10;i+) scanf("%d",&data1i);/在输入数据时不对数据进行任何的处理就显得方便些 for(i=0;i<10;i+)/控制冒泡的轮数,这里直接用的变量i作为控制轮数的变量 for(j=0;j<9-i;j+)/控制每轮冒泡所需要比较的次数 if(data1j>data1j+1) t=data1j; data1j=data1j+1; data1j+1=t; for(i=0;i<10;i+)/在要输出前清查是否有无效成绩,并输出无效成绩 if(data1i<0) while(k<=10) data2k=data1i;/把无效成绩存到另一个数组data2中 printf("有成绩无效,且无效成绩为%d,请重新输入n",data2k); k+; break;/跳出while循环,进行下一个成绩的检查 if( data10>=0&&data11>=0&&data12>=0&&data13>=0&&data14>=0&&data15>=0&&data16>=0&&data17>=0&&data18>=0&&data19>=0)/这里需要优化,想想有什么办法呢? printf("最高分是:%dn",data19); printf("最低分是:%dn",data10); 例子3 /*从键盘输入5门课程6个同学的成绩,输出每门课程的最高分*/ #include<stdio.h> void main int data56,i,j,a,t; for(i=0;i<5;i+)/5行,对应5门课程 printf("请输入第%d门课程对应的六名同学的的成绩:",i+1); for(j=0;j<6;j+)/6列,对应6个同学的成绩 scanf("%d",&dataij); for(a=0;a<5;a+)/控制五门课程,使每门课程都要比较 for(i=0;i<5;i+)/控制一门课程所要比较的轮数 for(j=0;j<5-i;j+)/控制一门课程一轮所要比较的次数 If(dataaj>dataaj+1)/注意前面的a,是代表的第几门课 t=dataaj; dataaj=dataaj+1; dataaj+1=t; for(a=0;a<5;a+)/这里是a,不是i printf("第%d门课程的最高分:%dn",a+1,dataa5); /* 分析:例3与例2的逻辑思维较强,特别是例3使用了三重循环,掌握了这种 思想或思维方式,冒泡法与数组的基本应用就差不多了。 */ 数组数据的排序问题选择排序法 思路:对于一个待排列的数列,首先从n个数据中选择一个最小的数据,并将它交换到第一个位置,然后再从剩下的n-1个数据中选择一个最小的数据,并将它交换到第二个位置,以此类推,最后从两个数据中选择一个最小的数据并将它交换到第n-1个位置为止。若有n个数,则需要进行n-1次选择操作。 例子1 /*从键盘输入10个成绩,按从小到大的顺序输出成绩*/ #include<stdio.h> void main(void) int data10,i,j,t,min; printf("请输入10个成绩:"); for(i=0;i<10;i+) scanf("%d",&datai); for(i=0;i<9;i+)/循环做9次选择 min=i;/min作为最小值的下标 for(j=i+1;j<10;j+)/找从i+1开始的最小值的下标 if(datamin>dataj) min=j; if(min!=i)/如果最小值的下标不是i就交换数据 t=datai; datai=datamin; datamin=t; printf("排序后的成绩:n"); for(i=0;i<10;i+) printf("%-3d",datai); printf("n"); 数组数据的查找问题顺序查找法 例子1 /*已知在数组中保存有10个成绩,从键盘输入一个成绩判断它是否存在*/ #include<stdio.h> void main int data10=99,87,65,77,63,96,100,85,92,80; int i,k,flag=0; printf("请输入要查找的成绩:"); scanf("%d",&k); for(i=0;i<10;i+) if(k=datai)/注意是等于符"="不是赋值符"=" flag=1; break; if(flag=1)/注意是等于符"="不是赋值符"=" printf("存在%dn",k); else printf("不存在您要查找的成绩n"); 例子2 备注:因与例子一前面的一样,这里只写不同之处 略 for(i=0;i<10;i+) if(k=datai)/注意是等于符"="不是赋值符"=" printf("存在%dn",datai);break; if(i=9)&&(k!=data9)/注意i=9中是等于符"="不是赋值符"=" printf("不存在您要查找的成绩n"); break; 分析:显然例子1的标志变量法要好得多,这种方法的思维用得较多 数组数据的查找问题折半查找法 前提:待查找的一组数据是 有序排列的 。 思路是首先选取中间位置的 数与要查找的数比较,如果两者相等则成功,否则利用数据的有序性可以决定要查找的数在哪一半。不断重复这样的查找过程直至查到或不存在为止。 例子1 /*已知在数组中保存有10个成绩,从键盘输入一个成绩判断它是否存在*/ #include<stdio.h> void main int data10=63,65,77,80,85,87,92,96,99,100;/有序 int k,lower,high,mid,flag; printf("请输入要查找的成绩:"); scanf("%d",&k);/"&"不要忘 lower=0; high=9; while(lower<=high)/当范围缩小到同一个数时取等号说明所有的范围都找了一遍, 如果还没有找到就不满足循环条件(如:high=-1;lower=0)跳出while循环 mid=(lower+high)/2; if(datamid<k) lower=mid+1; else if(datamid>k) high=mid-1; else/循环下去直到上面2种情况都不满足则找到了,如果三种情况都不满足 则不存在 flag=1; break; if(flag=1)/是"="不是"=" printf("存在%dn",k); else printf("您要查找的成绩不存在n"); 总结:有序数列用半折法速度快;无序数列用顺序法是唯一可行的方法。 四:数组作为函数的参数 例子1 /*输入任意个成绩,并输出最高分*/ #include<stdio.h> #define LEN 10/也可以不用宏定义,直接传值和给长度 void input(int data,int len);/声明函数,如果写在main函数之后就不用声明 int cal_max(int data,int len);/声明函数 void main int scoreLEN;/如果不用宏定义的话LEN都改为10 input(score,LEN); printf("最高分为%dn",cal_max(score,LEN); void input(int data,int len)/也可以用*data(指针)后续讲 int i; printf("请输入%d个成绩:",len); for(i=0;i<len;i+) scanf("%d",&datai);/可改为data+i int cal_max(int data,int len) int i,max=0; for(i=0;i<len;i+) if(datai>max)/datai可以改成*(data+i) max=datai; return max;/返回最大值,C中return只能返回一个值 /* 分析:将数组名(数组首元素的地址)作为实参,要求函数的形参是 相同类型的数组或指针,这种方式是把实参数组的起始地址 传给形参数组,形参数组的改变也是对实参数组的改变,这种 参数的传递方式为地址传递,而不是值的传递。data与score 是指针常量,指向同一位置,可以通过子函数的值的改变使主 函数的值发生改变。 */