




版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
学生成绩管理能力目标知识目标能对使用数组存储数据,并对数组进行操作能调用系统函数,并自定义函数能较熟练使用指针掌握一维数组、二维数组和字符型数组的定义掌握通过循环结构对数组进行高效处理掌握函数的定义和调用掌握函数的参数使用掌握变量的作用域与生存期掌握指针的定义掌握指针与数组的使用掌握指针与函数的使用
任务1学生成绩存储任务2学生等级成绩存储任务3学生成绩统计,求平均分和总分任务4数组作为函数的参数任务5指针型参数应用于函数项目分解任务1学生成绩存储3.1.1问题情景及其实现#include<stdio.h>intmain(){ floatscore[4]={60,70,80,90}; inti;for(i=0;i<4;i++)printf("该学生的第%d科成绩为:%5.2f\n",i+1,score[i]);return0;}
某班有1名学生参加了4门考试,已经将成绩存储在计算机中,请输出他们的成绩。具体实现代码如下:该学生的第1科成绩为:60.00该学生的第2科成绩为:70.00该学生的第3科成绩为:80.00该学生的第4科成绩为:90.00
程序运行结果如下:一个人N门课的成绩怎样存储和处理?一个班N门课的成绩怎样存储和处理?......这些数据的特点:具有相同的数据类型。为了方便地使用这些数据,C语言提供了一种构造数据类型:数组。一维数组二维数组3.1.2知识分解一、一维数组
一维数组是指只有一个下标的数组。一维数组适合用于存储一组具有相同数据类型的数据。一维数组定义后,在内存中为数组元素分配连续的内存存储空间,用于存放各数组元素的值。例如:inta[10];……a[0]a[1]a[2]a[3]a[4]a[5]a[6]a[7]a[8]a[9]1、一维数组的定义
一维数组定义的一般语法格式为:数据类型说明符数组名[常量表达式];例如:intarr[9];#defineN9intarr[N];intarr[2*(N+1)];floatarr[N];doublearr[N];chararr[N]
是数组元素的数据类型。
表示数组中有多少个元素,即数组的长度。][intn;intarr[n];=10;1、一维数组的定义
一维数组定义的一般语法格式为:数据类型说明符数组名[常量表达式];例如:intarr[9];
是数组元素的数据类型。
表示数组中有多少个元素,即数组的长度。][数组名……arr[0]arr[1]arr[2]arr[3]arr[4]arr[5]arr[6]arr[7]arr[8]arr
注意:数组一旦定义,数组元素在内存空间的位置以及空间的大小就被确定下来。2、一维数组元素的引用引用一维数组元素的语法格式为:数组名[下标表达式]例如:intarr[4];arr[0],arr[1],arr[2],arr[3]…1000H1001H1002H1003H1004H1005H1006H1007H1008H1009H100AH100BH100CH100DH100EH100FH1011H1012H1013H1014H…arr[0]arr[1]arr[2]arr[3]
注意:C语言在编译时并不检查下标越界,所以引用数组元素时应特别注意避免下标越界,即引用下标超过数组元素个数的定义范围。
arr[4]危险!危险!3、一维数组的初始化(1)一维数组初始化的概念
在定义一维数组的同时给一维数组的各个数组元素赋初值,称为一维数组的初始化。(2)对一维数组进行初始化有以下几种形式:
定义数组时对全部数组元素赋初值。inta[10]={0,1,2,3,4,5,6,7,8,9};inta[]={0,1,2,3,4,5,6,7,8,9};3、一维数组的初始化(1)一维数组初始化的概念
在定义一维数组的同时给一维数组的各个数组元素赋初值,称为一维数组的初始化。(2)对一维数组进行初始化有以下几种形式:定义数组时只对一部分数组元素赋初值,未赋初值的元素由系统自动赋初值为0。inta[10]={0,1,2,3,4}说明:(1)如果没有进行一维数组的初始化,则各个数组元素的值不确定(为随机数),直接使用会造成意想不到的错误。(2)如果进行一维数组的初始化时,提供的初值个数大于数组长度则会造成编译错误。习题:1.以下对一维整型数组a的正确说明是()。A)inta(10);B)intn=10,a[n];C)intn;D)#defineSIZE10;scanf("%",&n);inta[SIZE];inta[n];D2.以下能对一维数组a的每一位元素进行正确初始化使其值为1的语句是()。A)inta[10]=(0,0,0,0,0)B)inta[10]={1,1,1}C)inta[]={1};D)inta[10]={10*1};C3.下面程序——(每行程序前面的数字表示行号)1intmain()2{3floata[10]={0.0};4inti;5for(i=0;i<3;i++)scanf("%d",&a[i]);6for(i=0;i<10;i++)a[0]=a[0]+a[i];7printf("%d\n",a[0]);8return0;9}哪些行号的语句是错误的?%f%f习题:4.以下不正确的定义语句是().A)doublex[5]={2.0,4.0,6.0,8.0,10.0};B)inty[5]={0,1,3,5,7,9};C)charc1[]={’1’,’2’,’3’,’4’,’5’};D)charc2[]={'\x10','\xa','\x8'};B习题:
先要定义1个数组用来存放10个整数,再定义2个变量max、min,max和min分别用来记录数组中的最大数下标和最小数下标。【例3-1】键盘输入10个整数,找出并对调其中的最大数和最小数,然后将10个整数进行输出。
#include<stdio.h>intmain(){}intarry[10],max,min,i,t;for(i=0;i<10;i++)scanf("%d",&arry[i]);for(i=1;i<10;i++)max=min=0;elseif(arry[i]<arry[min])if(arry[i]>arry[max]){max=i;}{min=i;}t=arry[max];arry[max]=arry[min];arry[min]=t;printf("\n");for(i=0;i<10;i++)printf("%d\t",arry[i]);分析:return0;【例3-2】将一个10个元素的一维数组中的元素值按逆序存放,然后输出这个数组。……arr[0]arr[1]arr[2]arr[3]arr[4]arr[5]arr[6]arr[7]arr[8]arr[9]#include<stdio.h>intmain(){}intarr[10];for(i=0;i<10;i++)scanf("%d",&arr[i]);12345678910i指向数组的第一个元素;然后向右移动。j指向数组的最后一个元素;然后向左移动。分析:定义2个变量i和j;for(i=0,j=9;i<10/2;i++,j--)t=arr[i];arr[i]=arr[j];arr[k]=t;{}printf("\n");for(i=0;i<10;i++)printf("%d\t",arry[i]);,i;,j;,t;return0;【例3-2】将一个10个元素的一维数组中的元素值按逆序存放,然后输出这个数组。……arr[0]arr[1]arr[2]arr[3]arr[4]arr[5]arr[6]arr[7]arr[8]arr[9]12345678910i指向数组的第一个元素;然后向右移动。j指向数组的最后一个元素;然后向左移动。分析:定义2个变量i和j;#include<stdio.h>intmain(){}intarr[10];for(i=0;i<10;i++)scanf("%d",&arr[i]);for(i=0,j=9;i<10/2;i++,j--)t=arr[i];arr[i]=arr[j];arr[k]=t;{}printf("\n");for(i=0;i<10;i++)printf("%d\t",arry[i]);,i;,j;,t;return0;二、二维数组
二维数组是指只有两个下标的数组,其中第一个下标称为行标,第二个下标称为列标。二维数组适合于处理逻辑上具有行列结构的一批相同数据类型的数据。例如:inta[2][5];……a[0][0]a[0][1]a[0][2]a[0][3]a[0][4]a[1][0]a[1][1]a[1][2]a[1][3]a[1][4]1、二维数组的定义
二维数组定义的一般语法格式为:数据类型说明符数组名[常量表达式1][常量表达式2];例如:intarr[2][3];arr[0][0]arr[0][1]arr[0][2]arr[1][0]arr[1][1]arr[1][2]…1000H1001H1002H1003H1004H1005H1006H1007H1008H1009H100AH100BH100CH100DH100EH100FH1011H1012H1013H1014H1015H1016H1017H1018H…arr[0][0]arr[0][1]arr[0][2]arr[1][0]arr[1][1]arr[1][2]arrarrarr[0]arr[1]2、二维数组元素的引用
引用二维数组元素的语法格式为:数组名[行下标表达式][列下标表达式]例如:intarr[2][3];arr[0][0]arr[0][1]arr[0][2]arr[1][0]arr[1][1]arr[1][2]…1000H1001H1002H1003H1004H1005H1006H1007H1008H1009H100AH100BH100CH100DH100EH100FH1011H1012H1013H1014H1015H1016H1017H1018H…arr[0][0]arr[0][1]arr[0][2]arr[1][0]arr[1][1]arr[1][2]arr说明:(1)二维数组元素也是变量,可以用普通变量的地方也可以使用相同数据类型的二维数组元素。二维数组元素和普通变量一样能够进行输入、输出、运算和赋值。(2)应注意理定义语句中的下标数与引用时使用的下标数的区别。前者是定义二维数组,用于指定两维的下标上限长度;后者是对实际的二维数组元素进行引用。(3)引用二维数组元素时要注意避免下标越界的情况。3、二维数组的初始化
二维数组进行初始化有以下几种形式:
(1)按行对二维数组各元素赋初值(2)按数组元素在内存中的排列顺序对二维数组各元素赋初值。(3)仅对二维数组部分元素赋初值。(4)如果提供全部初值,则二维数组初始化时,第一维的长度可以省略,第二维的长度不能省略inta[3][4]={{0,1,2,3},{4,5,6,7},{8,9,10,11}};inta[3][4]={0,1,2,3,4,5,6,7,8,9,10,11};inta[3][4]={{1},{2},{3}};inta[][4]={0,1,2,3,4,5,6,7,8,9,10,11};33、二维数组的初始化
如果没有进行二维数组的初始化,则各个数组元素的初值不确定,可能导致程序运行结果出错。如果进行二维数组的初始化时,提供的初值个数大于数组长度(元素个数)则会造成编译错误。inta[3][4]={0,1,2,3,4,5,6,7,8,9,10,11,12};采用第4种初始化方式时,应注意在数组未赋全部初值的情况下数组的行标和列标均不能省略;在提供全部初值的情况下,只能省略行标而不能省略列标,如果这样做省略列标,则编译系统无法判断二维数组每行元素的个数。说明:2.以下对二维数组a正确初始化的是().A)inta[2][3]={{1,2},{3,4},{5,6}};B)inta[][3]={1,2,3,4,5,6};C)inta[2][]={1,2,3,4,5,6};D)inta[2][]={{1,2},{3,4}};B1.以下正确的定义语句是().A)inta[b];B)inta[3,4];C)inta[][3];D)inta[3][5];D习题:3.在定义inta[5][4];之后,对a数组的引用正确的是()A)a[2][4]B)a[5][0]C)a[0,0]D)a[0][0]D4.在定义inta[2][3];之后,对a数组的引用正确的是()
A)a(1,2)B)a[1,3]C)a[1>2][!1]D)a[2][0]C5.在定义inta[5][6];后,第10个元素是().A)a[2][5]B)a[2][4]C)a[1][3]D)a[1][5]C习题:6.若二维数组a有m列,则在a[i][j]前的元素个数为().A)j*m+iB)i*m+jC)i*m+j-1D)i*m+j+1B7.已知:inta[3][4]={0};则下面正确的叙述是().A)只有元素a[0][0]可得到初值0;B)此说明语句是错误的;C)数组a中的每一个元素都可以得到初值,但其值不一定为0;D)数组a中的每一个元素均可得到初值0;D习题:【例3-3】输入整型数据到一个4行5列的二维数组中,然后输出该二维数组本身和二维数组中值最小的元素及其行标和列标。ji#include<stdio.h>intmain(){}inta[4][5],i,j;for(i=0;i<4;i++)scanf("%d",&a[i][j]);for(j=0;j<5;j++)for(i=0;i<4;i++)m=n=0;if(a[i][j]<a[m][n]){m=i;n=j;}for(j=0;j<5;j++)printf("二维数组中值最小的元素是:a[%d][%d]=%d",m,n,a[m][n]);1234654523214416411537165676118635171828printf("%d\t",a[i][j]);{{}}printf("\n");i指向数组的行,j指向数组的列;分析:再定义2个变量i和j;定义一个4行5列的二维数组,1234654523214416411537165676118635171828↙return0;【例3-4】编程求一个4×4矩阵的两条对角线元素之和。i指向数组的行,j指向数组的列;分析:再定义2个变量i和j;定义一个4行4列的二维数组,ji#include<stdio.h>intmain(){}inta[4][4],i,j;for(i=0;i<4;i++)scanf("%d",&a[i][j]);for(j=0;j<4;j++)124376891112151316537↙i==j,sum=0;for(i=0;i<4;i++)sum=sum+a[i][i]+a[i][3-i];printf("sum=%d\n",sum);j==3-i124376891112151316537return0;【例3-4】编程求一个4×4矩阵的两条对角线元素之和。i指向数组的行,j指向数组的列;分析:再定义2个变量i和j;定义一个4行4列的二维数组,ji#include<stdio.h>intmain(){}inta[4][4],i,j;for(i=0;i<4;i++)scanf("%d",&a[i][j]);for(j=0;j<4;j++)124376891112151316537↙,sum=0;for(i=0;i<4;i++)sum=sum+a[i][i]+a[i][3-i];printf("sum=%d\n",sum);if(i%2!=0)sum=sum-a[i/2][i/2];i==jj==3-i124376891112151316537return0;3.1.3知识扩展:将n个数按从小到大进行排序
所谓排序就是将无序排列的数据转换为有序排列的数据,是程序中一种经常使用的基本算法,解决实际问题过程中也得到普遍运用。常用的排序方法是冒泡法和选择法。1、冒泡排序法冒泡法的基本算法思想:将包含n个数据的数组按升序排列,从第一个元素开始,依次将相邻的两个元素进行比较,即第1个元素和第2个元素比较,然后再第2个元素和第3个元素进行比较…,依次类推,直到第n-1个元素和第n个元素比较。。比较的原则是:相邻两个元素在比较的过程中,保证小数在前,大数在后,如果不满足这一要求,就将两个元素的值进行交换。3.1.3知识扩展:将n个数按从小到大进行排序
所谓排序就是将无序排列的数据转换为有序排列的数据,是程序中一种经常使用的基本算法,解决实际问题过程中也得到普遍运用。常用的排序方法是冒泡法和选择法。2、选择排序法
选择法的基本算法思想:
将包含n个数据的数组按升序排列,从n个元素中找出最小元素和第1个元素交换,再从后面的n-1个元素中找出最小元素和第2个元素交换,依次类推……。找最小值原则:先假定第1个元素为最小元素,用一个变量t记录下当前最小元素的下标1,然后用这个t下标对应的元素依次和后面的n-1个的元素进行比较,比较过程中保证比较过的元素中,最小元素的下标在变量t中,最后将变量t与第1个元素下标进行比较,相同则不交换,不同则进行交换,此时第1个元素是这n个元素的最小的元素。任务2学生等级成绩存储3.2.1问题情景及其实现#include<stdio.h>intmain(){chara[][10]={"优秀","良好","中等","及格","不及格"};inti=0;for(i=0;i<5;i++)printf("%s\t",a[i]);return0;}
在实际的考试中,考试的最终成绩不一定都是用一个具体的数值来表示的,例如,等级制(优秀、良好、中等、及格、不及格)的表示形式。现在我们需要用等级制来表示学生的成绩。
优秀良好中等及格不及格
程序运行结果如下:字符数组的定义字符数组的引用字符数组的初始化3.2.2知识分解
当数组中的元素都是由一个个字符组成时,便称之为字符数组。1.字符数组的定义char数组名[常量表达式][常量表达式];定义字符数组的语法格式为:char数组名[常量表达式];chara[5];例如:charb[4][5];2.字符数组的引用(1)引用字符数组元素
字符数组中存放的是若干单个字符,则只能引用字符数组中的单个数组元素。
当数组中的元素都是由一个个字符组成时,便称之为字符数组。c1[i]='A'+i;c2[i]='a'+i;【例3-5】字符数组c1赋值为'A'-'Z'的字符,字符数组c2赋值为'a'-'z'后,输出字符数组c1、c2。分析:字符数组c1和c2分别用于存储26个大写字母和26个小写字母,而字母存放是以其ASCII码值存放,其ASCII码值按字母顺序递增,可以使用for语句遍历每一字符数组元素,对各元素分别进行赋值和输出操作。本例中的字符数组用于存放若干单个字符。#include<stdio.h>intmain(){}charc1[26],c2[26];inti;for(i=0;i<26;i++){}for(i=0;i<26;i++)printf("%c",c1[i]);printf("\n");for(i=0;i<26;i++)printf("%c",c2[i]);printf("\n");ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz程序运行结果如下:return0;2.字符数组的引用(2)整体引用字符数组
当数组中的元素都是由一个个字符组成时,便称之为字符数组。
对字符数组可以引用数组元素也可以整体引用整个数组,但整体引用字符数组的前提是字符数组中存放的是一个字符串,如果字符数组中存放的是若干单个字符,则只能引用字符数组中的各个数组元素。①输入字符串并存放在字符数组中chars1[10];scanf("%s",s1);例如:……s1[0]s1[1]s1[2]s1[3]s1[4]s1[5]s1[6]s1[7]s1[8]s1[9]键盘输入:Chongqing↙Chongqing\0①输入字符串并存放在字符数组中chars1[10],s2[10],s3[10];scanf("%s%s%s",s1,s2,s3);再例如:……s1[0]s1[1]s1[2]s1[3]s1[4]s1[5]s1[6]s1[7]s1[8]s1[9]键盘输入:Class1Class2Class3
↙Class\0……s2[0]s2[1]s2[2]s2[3]s2[4]s2[5]s2[6]s2[7]s2[8]s2[9]Class\0……s3[0]s3[1]s3[2]s3[3]s3[4]s3[5]s3[6]s3[7]s3[8]s3[9]Class\0123②输出存放在字符数组中的字符串chars2[]="student";printf("%s",s2);例如:……s2[0]s2[1]s2[2]s2[3]s2[4]s2[5]s2[6]s2[7]stude\0nt83.字符数组的初始化
在定义字符数组的同时给字符数组的各数组元素赋初值称为字符数组的初始化。字符数组的初始化有多种形式。(1)使用若干个字符常量逐一给各个数组元素赋初值例如:charc[6]={'s','t','u','d','n','t'};字符数组c中存放6个字符又例如:charc[7]={'s','t','u','d','n','t','\0'};字符数组c中存放一个字符串3.字符数组的初始化
在定义字符数组的同时给字符数组的各数组元素赋初值称为字符数组的初始化。字符数组的初始化有多种形式。(2)使用字符串常量给数组赋初值例如:chars[7]={"school"};
字符数组s中,前6个数组元素依次存放字符串"school"中的各个字符,最后一个元素存放字符串结束标志'\0'。又例如:chars[3][6]={"red","green","blue"};二维字符数组s共有3行,各行依次存放一个字符串常量。red\0green\0blue\0s3.字符数组的初始化
在定义字符数组的同时给字符数组的各数组元素赋初值称为字符数组的初始化。字符数组的初始化有多种形式。(3)字符数组初始化时数组长度的省略
如果为字符数组的全部数组元素都提供了初值,则字符数组的长度可以省略。例如:chara[]={'p','r','o','g','r','a','m','\0'};又例如:chars[3][6]={"red","green","blue"};
二维字符数组初始化时,如果为字符数组的全部数组元素都提供了初值,则字符数组的第一维长度可以省略,而第二维长度则不能省略。8省略的长度由初值个数决定。3【例3-6】从键盘上输入一个字符串,要求统计并输出该字符串中各位数字、大写字母、小写字母、空格和其他字符出现的次数。分析:定义字符数组接收字符串,因为字符串中包含空格,所以使用gets函数要求用户输入字符串并存储在该字符数组中。接着使用循环语句遍历字符数组中存储的每一个字符(数组元素),对每一字符使用选择结构if判断该字符是数字、大写字母、小写字母、空格还是其他字符,并相应设置多个计数器变量分别进行统计,最后输出各种类型字符出现的次数即可。1.以下给字符数组str定义和赋值正确的是()A)charstr[6];str={"China"};B)charstr[]={"China"};C)charstr[6]={'a','b','c',‘d','e','f','g'};D)charstr[6]={"abcdefghijklmn"};B习题:2.对两个数组a和b进行如下初始化
chara[]="ABCDEF";charb[]={'A','B','C','D','E','F'};
则以下叙述正确的是().A)a与b数组完全相同B)a与b长度相同C)a和b中都存放字符串D)a数组比b数组长度长D习题:3.下面程序的运行结果是()#indude<stdio.h>intmain(){charch[7]={"12ab56"};inti,s=0;for(i=0;ch[i]>='0'&&ch[i]<='9';i+=2)s=10*s+ch[i]-'0';printf("%d\n",s);return0;}1习题:4.有字符数组a[80]和b[80],则正确的输出形式是().A)puts(a,b);B)printf("%s,%s,a[],b[]);C)putchar(a,b);D)puts(a),puts(b);D习题:5.有两个字符数组a、b,则以下正确的输入格式是().A)gets(a,b);B)scanf("%s%s",a,b);C)scanf("%s%s",&a,&b);D)gets("a"),gets("b");B#include<stdio.h>intmain(){chara1[5],a2[5],a3[5],a4[5];scanf("%s%s",a1,a2);gets(a3);gets(a4);puts(a1);puts(a2);puts(a3);puts(a4);return0;}A)aaB)aaC)aaD)aabbbbbbbbccccccddddddccdd6.当运行以下程序时,从键盘输入:aabb<CR>ccdd<CR>(<CR>表示回车),则下面程序的运行结果是()B习题:3.2.3知识扩展:编写简单密码检测程序
编程实现简单密码检测程序,对用户输入的密码进行检测,检测正确才能执行后续程序段,否则要求用户重新输入密码,输入三次错误密码后退出程序。(假定正确的用户密码为1234。)分析:定义两个字符数组分别用于存放用户预设的正确密码和用户输入的密码字符串。然后使用循环语句检测用户输入的密码,即将用户输入的密码和用户预设的正确密码进行比较。用户每次输入都会给出相应提示,如果用户在三次内未输入正确密码则退出此循环,并给出相应的提示语句。具体检测过程为:获取用户输入密码并与正确密码比较(使用strcmp函数),如果一致则终止循环,给出密码正确提示;如果不一致则输出密码错误提示,并继续进行循环,当输入三次错误密码后(使用计数器变量统计错误次数,取值为4时即表示已输入了3次错误密码),给出相应提示,终止程序运行。1、gets()函数;2、puts()函数函数功能:该函数用于实现字符串的输出。将作为参数的字符串输出到屏幕上,输出到字符串结束标志"\0"为止,并且在输出时将"\0"自动替换为"\n",即输出字符串后自动换行。常用字符串处理函数:
函数功能:该函数用于实现字符串的键盘输入。将从键盘输入的字符串存储在参数字符数组名指定的字符数组中,以回车符代表输入结束,并且在输入时将"\n"自动替换为"\0",即在输入得字符串后自动添加字符串结束标志。常用字符串处理函数:
3、strlen()函数;函数功能:该函数用于求字符串的长度,即字符串中包含的有效字符个数,应特别注意有效字符不包含字符串结束标志"\0"在内。4、strcat()函数函数功能:也称为“字符串连接函数”。该函数用于将两个字符串连接成一个字符串。5、strcpy()函数函数功能:也称为“字符串拷贝函数”。该函数用于将一个字符数组str2中存放的字符串复制到另一个字符数组str1中。6、strcmp()函数;函数功能:也称为“字符串比较函数”。该函数用于字符数组str1和符数组str2中存放的字符串进行比较;比较方法是:两个字符串从第一个字符开始自左至右逐个字符比较其AscII码值,直到出现不同字符或所有字符比较完毕。函数的返回值有三种情况:⑴为0,表示两个字符串长度相等且每个字符的AscII码值相等;⑵为一正整数,表示str1大于str2;⑶为一负整数,表示str1小于str2。7、strupr()函数和strlwr()函数函数功能:strupr()函数是将字符串中小写字母转换为大写字母,strlwr()函数是将字符串中的大写字母转换为小写字母。常用字符串处理函数:
作业编程在一个已知的字符串中查找最长单词,假定字符串中只含字母和空格,空格用来分隔不同单词。……#include<stdio.h>
intmain(){ inti,j,front,end,max=0,maxf,maxe;chars[20];printf("请输入字符串:");gets(s);for(i=0;;i++){front=i;for(j=i;a[j]!=''||a[j]!='\0';j++);end=j;i=j;if(end-front>max){max=end-front;maxe=end;maxf=front;}if(s[i]=='\0')break;}s[maxe]=0;puts(s+maxf);return0;}
i请输入字符串:最长的单词是:apple程序运行结果如下:↙This
is
an
apple\0Thisisanapple任务3学生成绩统计,求平均分和总分学生成绩统计,求平均分和总分3.3.1问题情景及其实现#include<stdio.h>
intmain(){ floatcj1=80,cj2=70;floatsum1=0,average1=0;sum1=sum(cj1,cj2);average1=average(cj1,cj2);printf("该学生的总分为:%5.2f,平均分为:5.2f\n",sum1,average1);return0;}
存储完学生的成绩后,我们常常还会对学生的成绩进行统计,本任务中要求计算学生的平均分和总分。该学生的总分为:150.00,平均分为:75.00
程序运行结果如下:floatsum(floatcj1,floatcj2){return(cj1+cj2);}floataverage(floatcj1,floatcj2){return(cj1+cj2)/2;}函数的概述函数的定义函数的调用3.3.2知识分解一、函数的概述
函数是实现特定程序功能的代码段,在C语言中函数主要分为两大类:一类是系统函数,也称为“标准库函数”,这类函数是由系统定义的函数,直接通过函数名进行调用;另一类是用户自定义函数,这类函数是用户为实现特定程序功能而自己定义的函数。1、函数的概念【例3-7】求两个整数中的较大整数intmain()#include<stdio.h>{}inta,b;printf("请输入两个整数:");scanf("%d%d",&a,&b);printf("大的一个数是:%d",max(a,b));intmax(intx,inty){}intz;z=x>y?x:y;returnz;/*函数定义*//*函数调用*/请输入两个整数:2315大的一个数是:23程序运行结果如下:↙max(a,b)2、通过函数定义和调用的简单实例认识函数return0;说明:
C语言源程序是由1个或多个函数组成的,每个函数是能够实现特定程序功能的代码段,各个函数间通过相互调用以实现整个程序功能。理解和使用函数时应注意以下几个方面:(1)一个C语言的源程序由1个或多个源程序文件组成,而一个源程序文件又由1个或多个函数组成。C语言的编译系统在对C语言的源程序进行编译时是以文件为单位的,而不是以函数为单位的。一个源文件可以被多个C程序共用。(2)一个C语言的源程序文件由1个或多个函数组成。这些函数的地位是平等且独立的,函数之间不存在隶属关系。除main函数外,函数间可以相互调用,每个函数都既可以做主调函数调用其它函数;又可以做被调函数被其它函数调用。主函数较为特殊,可以认为主函数是系统定义并调用的。(3)C程序的执行总是从main函数开始,调用其它函数后程序流程返回main函数,并在main函数中结束整个程序的运行。(4)函数不能嵌套定义,即不能在一个函数中定义另一个函数;但函数可以嵌套调用,即一个函数在调用另一个函数时,被调函数又调用了其它函数。①程序结构清晰,可读性好。②减少重复编码的工作量。③可多人共同编制一个大程序,缩短程序设计周期,提高程序设计和调试的效率。使用函数的好处……C程序源程序文件n函数1函数m……源程序文件1函数1函数n从不同的角度看,函数有不同的分类方式。⑴从函数定义者的角度来看,函数可以分为:①标准函数(系统库函数):由系统提供的数学函数、字符串函数和输入输出函数等,直接调用即可,如前面介绍过的pow函数、strcat函数和printf函数。②用户自定义函数:用户根据程序设计需要自己定义的函数,如上例的max函数。⑵从函数的定义形式来看,函数可以分为:①有参函数,调用此类函数不需要主调函数提供数据。②无参函数,调用此类函数需要主调函数提供数据。⑶从函数间的调用关系来看,函数可以分为:①主调函数,即调用其它函数的函数,如上例的main函数。②被调函数,被其他函数调用的函数,如上例的max函数。3、函数的分类二、函数的定义1、函数定义的语法格式C语言中函数定义的一般形式为:函数类型函数名(数据类型名形式参数1,数据类型名形式参数2…){
说明性语句可执行语句}例如:定义一个求矩形面积的函数areaintarea(intl,intw){ints;s=l*w;return(s);}函数类型形式参数①函数定义中的函数体是用{}括起来的语句。②在函数体中,数据说明要放在执行语句的前面。③函数体可以是空,称为空函数。④函数定义中不能包括对另一函数的定义。即函数不能嵌套定义。voidprint(){putchar('*');voidprnline(){putchar('\n');}}2、函数定义的规则①当函数定义时,参数可有可无,若有超过一个以上的参数要用逗号分隔。②函数定义时的参数称为形式参数,简称形参。③有形参的函数称为有参函数,无形参的函数称为无参函数。④形式参数是用来记录调用者实际参数的值,当函数没有形式参数时称为无参函数。3、函数的形式参数intarea(l,w)intl,w;{ints;s=l*w;return(s);}intarea(l,w){intl,y;……}或:intarea(intl,w){……}intarea(l,w)intl,w,s;{s=l*w;return(s);}形参也可以这样定义如下定义都是错误的
√三、函数的调用函数名(实参表列)1、函数调用的一般形式:其中:参数表列中,参数之间用逗号分隔,参数的个数与定义的个数、数据类型应该匹配#include<stdio.h>intsum100(){inti,t=0;for(i=1;i<=100;i++)t+=i;return(t);}intmain(){ints;s=sum100();printf("%d\n",s);return0;}程序输出结果:5050#include<stdio.h>intsum(intx){inti,t=0;for(i=1;i<=x;i++)t+=i;return(t);}intmain(){ints;s=sum(100);printf("%d\n",s);return0;
}【补充例】求1~100的累加和。思考:两个程序有何不同程序输出结果:5050分析:左边的sum100()函数是无参函数,不需要从主调函数中获取数据,该函数只能完成1到100数的求和;分析:右边的sum(intx)函数是有参函数,需要从主调函数中获取数据,该函数可以完成1到x数的求和;2、函数调用的三种常见方式例如:(1)函数调用单独构成一条语句。即将函数调用作为一个语句使用welcome();(2)函数调用作为表达式的一部分,参与表达式运算。函数调用出现在表达式中,作为表达式中的一个运算对象,这时要求函数返回值以参加表达式运算。例如:(3)函数调用做为另一个函数调用的实参。也就是将函数调用的返回值作为实际参数调用另一个函数。例如:minnum=min(a,min(b,c));c=2*min(a,b);注意:函数需要先定义再调用。被调用的函数一定是已经定义过的函数。如果调用的函数属于系统标准库函数,一般应在源文件开头处使用编译预处理命令#include将该标准库函数所属的头文件包含到本源文件中。【例3-8】编写一个函数求整数m到n之间所有奇数的和,其中m和n由用户指定。调用该函数验证其功能。intOdd(intx,inty){}inti,sum=0;while(i<=y)if(x%2==1)i=x;elsei=x+1;{sum=sum+i;}i=i+2;intmain(){}intm,n,t;printf("请输入两个整数:");scanf("%d,%d",&m,&n);printf("%d到%d之间的所有奇数的和:%d\n",m,n,Odd(m,n));#include<stdio.h>if(m>n)t=m;m=n;n=t;{}return(sum);return0;
【例3-9】编写一个判断素数的函数。在主函数中输入一个整数,调用该函数判断这个数是不是素数并输出判断结果。intPrime(intx){}inti;for(i=2;i<x;i++)intmain(){}intn;printf("请输入一个整数:");scanf("%d",&n);printf("%d不是素数\n",n);#include<stdio.h>if(Prime(n))printf("%d是素数\n");elseif(x%i==0)if(i>=x)return(1);elsereturn(0);break;return0;3、函数的参数与函数的返回值
一般情况下,在函数调用时,在主调函数和被调函数之间会发生数据传递。这种数据传递由函数参数来实现。函数参数的作用是:在进行函数调用时,将主调函数中的数据传递给被调函数,在被调函数的函数体中对传入的数据进行处理并将处理结果返回主调函数。(1)函数的形式参数与实际参数
在定义函数时函数名后圆括号中的参数称为“形式参数”(简称形参);在调用函数时函数名后圆括号中的参数称为“实际参数”(简称实参)。
C语言中发生函数调用时,主调函数中实参的值会传递给被调函数相应的形参。在被调函数中对形参进行处理,函数调用结束后,无论形参的值是否发生改变都不会影响实参的值。因此这种数据传递是一种“单向值传递”,即实参能够把值传递给形参,但形参值不能回传给实参。
【例3-10】编写一个swap函数用来交换两个变量的值,在主函数中调用swap函数交换用户通过键盘输入的两个整数并输出交换后的两个整数。voidswap(intx,inty){}inttemp;intmain(){}inta,b;printf(“请输入两个整数a和b:");scanf("%d,%d",&a,&b);printf("\na=%d,b=%d\n",a,b);#include<stdio.h>swap(a,b);temp=x;x=y;y=temp;printf("\nx=%d,y=%d",x,y);请输入两个整数a和b:5,8↙x=8,y=5a=5,b=8程序运行结果如下:ab58xy58tempreturn0;(2)函数的返回值
非void类型的函数在被调用后会返回一个值,该值称为函数的返回值或简称为函数值。函数的返回值与函数类型密切相关,函数类型决定了函数返回值的类型。①函数的类型
【例3-11】定义一个函数用于计算指定半径的圆的面积。在主函数中调用该函数计算并输出圆面积。#include<stdio.h>ints(floatr){return(3.14*r*r);}intmain(){intr,area;scanf("%f",&r);printf("%d\n",s(r));return0;}自动转换为int型思考:若要得到单精度实型的圆面积,程序应如何修改212程序运行情况如下:
intfloatf
【例3-12】无返回值函数的定义和调用。要求定义一个显示欢迎信息的函数并在主函数中进行调用。voidwelcome(){charstr[50];printf("请输入你的名字:");gets(str);printf("*******************************\n");printf("%s,欢迎你来到中国重庆!\n",str);printf"*******************************\n");}intmain(){welcome();return0;}#include<stdio.h>函数的调用能通过返回值使主调函数得到一个确定的值。描述:使函数运行结束,并返回一个确定的值。语法:return(表达式);注释:
return语句只能用于函数中,它使得函数运行结束,并向主调函数传回“表达式”的值。函数的返回值是通过return语句来获得的。函数返回值应具有确定的类型。应当在定义函数时获得。注:如果函数返回值的类型是void,则不能有“表达式”,其它情形应该提供“表达式”。理论上“表达式”的类型应该与函数定义的类型相同,如果不同。则C语言以函数定义的类型为准自动进行类型转换。②函数返回值方法return语句函数返回值建议:函数用return语句确定表示函数执行结束,且返回值。没有返回值的函数应该定义类型为:void。使用强制类型转换代替可能的自动类型转换。
return语句的表达式用()使程序更清楚。函数返回值的分析:当函数调用结束后,返回值将通过“中间量”或地址(指针)传递返回。如果使用“中间量”,则函数返回后应立即引用该“中间量”,否则函数返回值将不在存在。例如:u=func(12,12);←立即引用函数返回值
func(12,12);←不引用函数返回值函数被定义为基本类型,都是采用“中间量”进行值传递返回。如果函数被定义为复杂的构造类型,则返回值借助指针进行值传递返回
一个函数调用另一函数:⑴调用函数必须存在(函数库内),否则将在连接时出错。例如:intmain(){printF("Hello!\n");return0;}⑵如果使用库函数,一般应该在本文件的开头用#include命令将调用有关库函数时用到的信息“包含”到本文件中来。例如:#include<stdio.h>⑶调用函数一般要在调用前先有明确声明;其一般形式:函数返回值类型说明符被调用函数名(形参表);
形参表可以给出形参的数据类型和形参名,也可以只给出形参的类型名。4、函数声明和函数原型
#include<stdio.h>
intmain(){inti;
for(i=0;i<2;i++)print();putchar('\n');return0;}voidprint(){putchar('*');}#include<stdio.h>intmain(){
inti;
for(i=0;i<2;i++)print();putchar('\n');return0;}voidprint(){putchar('*');}说明语句的位置应该在函数定义之前。函数说明语句既可以置于函数外,也可以置于函数内。voidprint();voidprint();4、函数声明和函数原型
4、函数声明和函数原型
C语言中有三种情况可以省略函数的说明:⑴被调用函数的定义出现在调用它的函数之前。#include<stdio.h>voidprint(){putchar('*');}intmain(){inti,j;
for(i=0;i<2;i++){for(j=0;j<3;j++)print();putchar('\n');}return0;}⑵如果被调用函数的返回值是整型或字符型。⑶对C编译提供的库函数的调用不需要再作函数说明,但必须把该函数的头文件用#include命令包含在源程序的最前面。
【例3-13】定义一个双精度型函数求两个双精度实数的和。doubleadd(doublex,doubley){doublez;z=x+y;
return(z);}#include<stdio.h>doubleadd(double,double);intmain(){doublea,b,sum;printf("请输入两个实数a和b(用逗号分隔):");scanf("%lf,%lf",&a,&b);sum=add(a,b);printf("\n%f+%f=%f",a,b,sum);return0;}5、函数的嵌套调用
在C语言中,把函数调用也作为一个表达式。因此凡是表达式可以出现的地方都可以出现函数调用。例如:①welcome();
②if(iabs(a)>max)max=iabs(a);
③m=max(c,max(a,b));C语言中不允许作嵌套的函数定义。因此各函数之间是平行的,不存在上一级函数和下一级函数的问题。但是C语言允许在一个函数的定义中出现对另一个函数的调用。这样就出现了函数的嵌套调用。#include<stdio.h>intsub1(intm,intn){return(m>n?m:n);}intsub2(intx,inty){x=110;
return(sub1(x,y));}intmain(){inta=45,b=120,c;c=sub2(a,b);printf(“c=%d\n”,c);return0;}例如:其调用过程可以图示如下:【例3-14】使用函数的嵌套调用实现求12+22+32+…+n2,其中n由用户键盘输入。intSquare(intx){}return(x*x);intSum(intn){}inti,sum=0;for(i=1;i<n;i++)sum=sum+Square(i);return(sum);intmain(){}intn;printf(“请输入一个整数:");scanf("%d",&n);printf("1到%d的平方和:%d\n",n,Sum(n));#include<stdio.h>return0;222习题:以下程序的输出结果是()func2(inta,intb){intc;c=a*b%3;return(c);}func1(inta,intb){intc;a+=a;b+=b;c=func2(a,b);return(c*c);}intmain(){intx=7,y=17;printf("%d\n".func1(x,y));return0;}A.7B.17.C.4D.0Cmainfunc1func2xy717a7b17c1434ab34c1414*34%33.3.3知识扩展:知识扩展:Hanoi(汉诺)塔问题。
古代有一个梵塔,塔内有三个座A、B、C,开始时,A座上有64个盘子,盘子大小不等,大的在下,小的在上,如图3-9所示,有一个老和尚想把64个盘子从A座移到C座,但每次只允许移动一个盘子,且在移动过程中在3个座上都始终保持大盘在下,小盘在上。在移动过程中可以利用B座,要求编程序输出移动步骤。①将A的4个顶盘假想成1个顶盘,则②向右移动A的顶盘到B③向右移动A的底盘到C④向右移动B的底盘到CABC
即,将五个盘移动的原始问题分解成一个盘移动的基本问题和有待解决的四个盘移动的新问题,再对新问题逐步分解,直至基本问题。函数的递归调用
递归调用:一个函数直接或间接地调用了它本身,就称为函数的递归调用。递归函数:在函数体内调用该函数本身。
综上所述,用递归解决问题应分为两部分:一部分属于基本问题,对它可以直接求出结果;另一部分称为新问题,虽然不是基本问题,但是与原始问题类似并且比原始问题简单一些。对稍微简单一些的新问题继续进行分解,直至达到仅有基本问题。解决完基本问题后,函数会沿着调用顺序不断给上一次的调用返回结果,直至原始问题。
求解递归问题有两个过程:第一个过程是递归调用,从原始问题出发,层层向下,直至基本问题;第二个过程是返回过程,从基本问题出发,层层向上返回,直至原始问题。intmain(){intm;printf("inputthenumberofdiskes:");scanf("%d",&m);printf("thesteptomoving%3ddiskes:\n",m);hanoi(m,'A','B','C');return0;}voidmove(charx,chary){printf("%c%c\n",x,y);}voidhanoi(intn,charone,chartwo,charthree){if(n==1)move(one,three);else{hanoi(n-1,one,three,two);move(one,three);hanoi(n-1,two,one,three);}voidhanoi(intn,charone,chartwo,charthree){if(n==1)move(one,three);else{hanoi(n-1,one,three,two);move(one,three);hanoi(n-1,two,one,three);}2ABC1ACB1BACvoidhanoi(intn,charone,chartwo,charthree){if(n==1)move(one,three);else{hanoi(n-1,one,three,two);move(one,three);hanoi(n-1,two,one,three);}1ACBA→CA→BB→C1BAC例:编一递归函数求n!。longfac(intn){inti;longfc=1;if(n==0)return(1);elsereturn(n*fac(n-1));}intmain(){intn;scanf("%d",&n);printf("%d!=%d\n",fac(n);return0;}
#include<stdio.h>假定n=5,则调用过程为:2*11fac(5)5*fac(4)4*fac(3)3*fac(2)2*fac(1)3*24*65*24120递归与迭代的比较:有的问题不仅可以用递归方法解决,也可以用迭代方法解决。下面我们分别写出阶乘的迭代程序和递归程序进行分析。分析:根据上面左边的迭代程序可以看出,它是从基本问题出发,由前向后,由简单到复杂,每一步都得出一个确定的值,作为下一步计算的基础,最后得到所求问题的解。longfac(intn){inti;longfc=1;if(n==0);elsefor(i=1;i<=n;i++)
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 铸造培训课件范文
- 山西地质集团有限公司招聘真题2024
- 我不玩火的安全教育
- 2024年凉山州招聘初高中教师考试真题
- 学校校园安全
- 亳州市蒙城县县直幼儿园教师选调真题2024
- 2025深圳租房合同样本
- 2025年贷款质押担保合同(正式版本)
- 2025年土地流转合同范本
- 2025铝合金门窗采购合同范本
- DL∕T 806-2013 火力发电厂循环水用阻垢缓蚀剂
- 人教版 九年级上册音乐 第二单元 鳟鱼 教案
- 四年级美术测国测复习题答案
- 《宽容别人 快乐自己》班会课件
- 2024光伏电站索悬柔性支架施工方案
- 仲裁法全套课件
- 教育家精神专题讲座课件
- 300立方米柴油储罐设计
- 颈椎后路术后护理查房
- 2024年事业单位考试贵州省毕节地区毕节市A类《职业能力倾向测验》统考试题含解析
- 幼儿足球知识讲座
评论
0/150
提交评论