文章目录
- 第6章 利用数组处理批量数据
- 6.1 对10个数组元素依次赋值为0,1,2,3,4,5,6,7,8,9,要求按逆序输出
- 6.2 用数组处理求Fibonacci数列问题
- 6.3 有10个地区的面积,要求对它们按由小到大的顺序排列。
- 以上是一维数组的相关练习
- 以下是二维数组的相关练习:
- 6.4将一个二维数组行和列的元素互换,存到另一个二维数组中
- 6.5 有一个3×4的矩阵,要求编程序求出其中值最大的那个元素的值,以及其所在的行号和列号
- 6.6 输出一个已知的字符串
- 6.7输出数组内所有的元素
- 6.8输出一个菱形图
- 6.9字符串和字符串结束标志
- 6.10善于使用字符串处理函数
- 6.11输入一行字符,统计其中有多少个单词,单词之间用空格分隔开
- 6.12有3个字符串,要求找出其中最大者
- 第7章 用函数实现模块化程序设计
- 7.1输入两个整数,要求输出其中值较大者。要求用函数来找到大数
- 7.2输入4个整数,找出其中最大的数。用函数的嵌套调用来处理
- 函数的递归调用:
- 7.3有5个学生坐在一起
- 请问第5个学生多大
- 7.4用递归方法求n!
- 7.5Hanoi(汉诺)塔问题。古代有一个梵塔,塔内有3个座A、B、C,开始时A座上有64个盘子,盘子大小不等,大的在下,小的在上。有一个老和尚想把这64个盘子从A座移到C座,但规定每次只允许移动一个盘,且在移动过程中在3个座上都始终保持大盘在下,小盘在上。在移动过程中可以利用B座。要求编程序输出移动一盘子的步骤。
- 数组元素作函数实参
- 7.6输入10个数,要求输出其中值最大的元素和该数是第几个数
- 数组名作函数参数
- 7.7有一个一维数组score,内放10个学生成绩,求平均成绩
- 7.8有两个班级,分别有5名和10名学生,调用一个average函数,分别求这两个班的学生的平均成绩
- 7.9用选择法对数组中10个整数按由小到大排序
- 多维数组名作函数参数
- 7.10有一个3×4的矩阵,求所有元素中的最大值
- 局部变量和全局变量
- 7.11有一个一维数组,内放10个学生成绩,写一个函数,当主函数调用此函数后,能求出平均分、最高分和最低分
- 若外部变量与局部变量同名,分析结果
- 7.12变量的存储方式:动态存储方式与静态存储方式
- 7.13局部变量的存储类别
- 7.14全局变量的存储类别
- 7.15存储类别小结
- 特殊:
- 7.16关于变量的声明和定义
- 内部函数
- 外部函数
第6章 利用数组处理批量数据
6.1 对10个数组元素依次赋值为0,1,2,3,4,5,6,7,8,9,要求按逆序输出
解题思路:
1)定义一个数组类型为整型且长度为10的数组a[i]
2)要赋的值是从0到9,可以用for循环来赋值
3)用循环按下标从大到小输出这10个数组元素
#include<stdio.h>
int main()
{
int a[10],i;
for(i=0;i<=9;i++)
{
a[i]=i;
}
for(i=9;i>=0;i--)
{
printf("%d\t",a[i]);
}
printf("\n");
return 0;
}
编译结果如下:
6.2 用数组处理求Fibonacci数列问题
说明:我的上一篇博客(C语言基础练习(一))(https://blog.csdn.net/weixin_45870610/article/details/107289218)中的5.5也是求Fibonacci数列的,不同的是5.5中是用简单变量处理的,缺点不能在内存中保存这些数。假如想直接输出数列中第25个数,是很困难的。如果用下面的方法,即数组处理,每一个数组元素代表数列中的一个数,就可以依次求出各数并存放在相应的数组元素中。
解题思路:
1)先定义一个数组长度为40的整型数组a[40]
2)由于Fibonacci数列的特殊,数组的第1、2个元素都是1,且可以直接定下来
3)根据Fibonacci数列的递推公式用for循环求得其余的38个数组元素,在内存中保存下来
4)接下来就是如何把这个数组好看地打印出来,当然要考虑for循环,一个个打印出来,间隔可以在打印时用%12d
#include<stdio.h>
int main()
{
int a[40]={1,1},i;
for(i=2;i<40;i++)
{
a[i]=a[i-1]+a[i-2];
}
for(i=0;i<40;i++)
{
if(i%5==0)
{
printf("\n");
}
printf("%12d",a[i]);
}
printf("\n");
return 0;
}
编译结果如下:
6.3 有10个地区的面积,要求对它们按由小到大的顺序排列。
解题思路:
1)采用起泡法排序(起泡法和冒泡法是同一种方法,不过就冒泡法分的细点的话,还可以分好几种,但出发点一样的)
(1)从第一个元素开始,比较相邻的元素,若是前一个比后一个大,则两者调换位置,若前一个比后一个小,则两者位置不变
(2)每一对相邻的元素进行重复的工作,从开始对一直到结尾对,这步完成后,结尾为最大的数
(3)针对除了最后一个元素重复进行上面的步骤
重复1-3步骤直到完成排序
冒泡排序动图演示:
此动图来源于:
https://blog.csdn.net/fengge2018/article/details/105328957
#include<stdio.h>
int main()
{
int a[10];
int i,j,t;
printf("input 10 numbers :\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("the sorted numbers :\n");
for(i=0;i<10;i++)
{
printf("%d ",a[i]);
}
printf("\n");
}
编译结果如下:
以上是一维数组的相关练习
以下是二维数组的相关练习:
6.4将一个二维数组行和列的元素互换,存到另一个二维数组中
解题思路:
1)可以定义两个数组:数组a为2行3列,存放指定的6个数;数组b为3行2列,开始时未赋值
2)将a数组中的元素a[i][j]存放到b数组中的b[j][i]元素中
用嵌套的for循环完成
#include <stdio.h>
int main()
{
int a[2][3]={{1,2,3},{4,5,6}};
int b[3][2],i,j;
printf("array a:\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("array b:\n");
for (i=0;i<=2;i++)
{
for(j=0;j<=1;j++)
printf("%5d",b[i][j]);
printf("\n");
}
return 0;
}
编译结果如下:
6.5 有一个3×4的矩阵,要求编程序求出其中值最大的那个元素的值,以及其所在的行号和列号
解题思路:
采用"打擂台算法"
打擂台算法的原理:先找出任一人站在台上,第2人上去与之比武,胜者留在台上,第3人与台上的人比武,胜者留台上,败者下台,以后每一个人都是与当时留在台上的人比武,直到所有人都上台比为止,最后留在台上的是冠军
同理:
1)先把a[0][0]的值赋给变量max(max用来存放当前已知的最大值)
2)a[0][1]与max比较,如果a[0][1]>max,则表示a[0][1]是已经比过的数据中值最大的,把它的值赋给max,取代了max的原值
3)以后依此处理,最后max就是最大的值
#include<stdio.h>
int main()
{
int i,j,row=0,colum=0,max;
int a[3][4]={{1,2,3,4},{9,8,7,6},{-10,10,-5,2}};
max=a[0][0];
for (i=0;i<=2;i++)
{
for (j=0;j<=3;j++)
{
if (a[i][j]>max)
{
max=a[i][j];
row=i;
colum=j;
}
}
}
printf("max=%d\nrow=%d\ncolum=%d\n",max,row,colum);
}
编译结果如下:
6.6 输出一个已知的字符串
解题思路:
1)定义一个字符数组,并用"初始化列表"对其赋以初值
2)用for循环逐个输出此字符数组中的字符
#include <stdio.h>
int main()
{
char c[15]={'I',' ','a','m',' ','a',' ','s','t','u','d','e','n','t','.'};
int i;
for(i=0;i<15;i++)
{
printf("%c",c[i]);
}
printf("\n");
return 0;
}
编译结果如下:
6.7输出数组内所有的元素
解题思路:
很简单的一道题,想要依次输出数组里的元素,首先数组里的元素要有值,有值了下一步就考虑如何依次输出到屏幕上,就自然想到了for循环(可以输出了以后就可以考虑美观问题,再设置数组元素输出的间隔)
#include<stdio.h>
int main()
{
int a[10]={0},i;
for(i=0;i<10;i++)
{
printf("%2d",a[i]);
}
printf("\n");
}
编译结果如下:
6.8输出一个菱形图
解题思路:
1)对于这种有多个元素要输出的,我们最好是把这些元素存放在数组里,再用for循环输出到屏幕上。
2)菱形图,先在草稿纸上画出一个菱形,观察它的结构,下面的你就懂了哈哈!
#include <stdio.h>
int main()
{
char diamond[][5]={{' ',' ','*'},{' ','*',' ','*'},{'*',' ',' ',' ','*'},{' ','*',' ','*'},{' ',' ','*'}};
int i,j;
for (i=0;i<5;i++)
{
for (j=0;j<5;j++)
{
printf("%c",diamond[i][j]);
}
printf("\n");
}
return 0;
}
编译结果如下:
6.9字符串和字符串结束标志
1)在C语言中,是将字符串作为字符数组来处理的,输出字符串时考虑的是字符串的有效长度而不是字符数组的长度
2)为了测定字符串的实际长度,C语言规定了字符串结束标志’\0’, '\0’代表ASCII码为0的字符,从ASCII码表可以查到,ASCII码为0的字符不是一个可以显示的字符,而是一个"空操作符",即它什么也不做,用它作为字符串结束标志不会产生附加的操作或增加有效字符,只起一个供辨别的标志
char c[]={"I am happy"};
可写成
char c[]="I am happy";
相当于
char c[11]={"I am happy"};
#include<stdio.h>
int main()
{
char c[10]={"China"};
printf("%s\n",c);
}
字符数组的输入输出可以有两种方法:
1)逐个字符输入输出(%c)
2)整个字符串一次输入输出(%s)
注意事项:
1)输出的字符中不包括结束符’\0’
2)用%s输出字符串时,printf函数中的输出项是字符数组名,不是数组元素名
3)如果一个字符数组中包含多个’\0’,则遇第一个’\0’时输出就结束
4)可以用scanf函数输入一个字符串,scanf函数中的输入项c是已定义的字符数组名,输入的字符串应短于已定义的字符数组的长度,如下:
例1:
#include<stdio.h>
int main()
{
char c[8];
printf("请输入一个字符串且字符串的长度小于等于8:\n");
scanf("%s",&c);
printf("%s\n",c);
}
编译结果如下:
例2:
#include<stdio.h>
int main()
{
char str1[5],str2[5],str3[5];
scanf("%s%s%s",str1,str2,str3);
printf("%s %s %s\n",str1,str2,str3);
}
编译结果如下:
6.10善于使用字符串处理函数
1.puts函数----输出字符串的函数
1)其一般形式为:puts (字符数组名)
2)作用是将一个字符串输出到终端
char str[20]=“China”;
puts(str);
输出China到屏幕上
2. gets函数----输入字符串的函数
1)其一般形式为:gets(字符数组名)
2)作用是输入一个字符串到字符数组
char str[20];
gets(str);
Computer↙即从屏幕上输入20个元素,接收到数组中,赋值给数组的20个元素
3. strcat函数----字符串连接函数
1)其一般形式为:strcat(字符数组1,字符数组2)
2)其作用是把两个字符串连接起来,把字符串2接到字符串1的后面,结果放在字符数组1中
3)使用字符串函数时,在程序开头用#include <string.h>
如下:
#include<stdio.h>
#include<string.h>
int main()
{
char str1[30]="People";//数组长度要足够大
char str2[]="China";
printf("%s\n", strcat(str1,str2));
}
4. strcpy和strncpy函数-字符串复制
1)strcpy一般形式为:strcpy(字符数组1,字符串2)
2)作用是将字符串2复制到字符数组1中去
char str1[10],str2[]=“China”;
strcpy(str1,str2);
3)可以用strncpy函数将字符串2中前面n个字符复制到字符数组1中去
4)strncpy(str1,str2,2);
作用是将str2中最前面2个字符复制到str1中,取代str1中原有的最前面2个字符
5)复制的字符个数n不应多于str1中原有的字符
5. strcmp函数----字符串比较函数
1)其一般形式为:strcmp(字符串1,字符串2)
2)作用是比较字符串1和字符串2
strcmp(str1,str2);
strcmp(“China”,“Korea”);
strcmp(str1,“Beijing”);
3)字符串比较的规则是:将两个字符串自左至右逐个字符相比,直到出现不同的字符或遇到’\0’为止
4)如全部字符相同,认为两个字符串相等
5)若出现不相同的字符,则以第一对不相同的字符的比较结果为准(实则比较ASCLL码的值)
"A"<"B" "a">"A" "computer">"compare"
"these">"that" "1A">"$20" "CHINA">"CANADA"
"DOG"<"cat" "Tsinghua">"TSINGHUA"
6)比较的结果由函数值带回
如果字符串1=字符串2,则函数值为0
如果字符串1>字符串2,则函数值为一个正整数
如果字符串1<字符串2,则函数值为一个负整数
if(str1>str2) printf("yes"); // 错误
if(strcmp(str1,str2)>0) printf("yes"); //正确
6.strlen函数----测字符串长度的函数
1)其一般形式为:strlen (字符数组)
2)它是测试字符串长度的函数
3)函数的值为字符串中的实际长度
如下:
char str[10]="China";
printf("%d",strlen(str));
输出结果是5
也可以直接测试字符串常量的长度
strlen("China");
7.strlwr函数----转换为小写的函数
1)其一般形式为:strlwr (字符串)
2)函数的作用是将字符串中大写字母换成小写字母
8. strupr函数----转换为大写的函数
1)其一般形式为:strupr (字符串)
2)函数的作用是将字符串中小写字母换成大写字母
6.11输入一行字符,统计其中有多少个单词,单词之间用空格分隔开
解题思路:
1)问题的关键是怎样确定“出现一个新单词了”
2)从第1个字符开始逐个字符进行检查,判断此字符是否是新单词的开头,如果是,就使变量num的值加1,最后得到的num的值就是单词总数
3)判断是否出现新单词,可以由是否有空格出现来决定(连续的若干个空格作为出现一次空格;一行开头的空格不统计在内)
4)如果测出某一个字符为非空格,而它的前面的字符是空格,则表示“新的单词开始了”,此时使num累加1
5)如果当前字符为非空格而其前面的字符也是非空格,则num不应再累加1
6)用变量word作为判别当前是否开始了一个新单词的标志,若word=0表示未出现新单词,如出现了新单词,就把word置成1
7)前面一个字符是否空格可以从word的值看出来,若word等于0,则表示前一个字符是空格;如果word等于1,意味着前一个字符为非空格
#include<stdio.h>
#include<string.h>
int main()
{
char string[81],c;
int i,num=0,word=0;
printf("请输入句子或多个单词:\n");
gets(string);
for(i=0;(c=string[i])!='\0';i++)
{
if(c==' ')
{
word=0;
}
else if(word==0)
{
word=1;
num++;
}
}
printf("%d words\n",num);
}
编译结果如下:
6.12有3个字符串,要求找出其中最大者
解题思路:
1)设一个二维的字符数组str,大小为3×10。每一行存放一个字符串 char str[3][10];
2)可以把str[0],str[1],str[2]看作3个一维字符数组,可以把它们如同一维数组那样进行处理
3)经过三次两两比较,就可得到值最大者,把它放在一维字符数组string中
if (strcmp(str[0],str[1])>0)
strcpy(string,str[0]);
else
strcpy(string,str[1]);
if (strcmp(str[2],string)>0)
strcpy(string,str[2]);
#include<stdio.h>
#include<string.h>
int main()
{
char str[3][10];
char string[10];
int i;
for(i=0;i<3;i++)
{
gets (str[i]);
}
if(strcmp(str[0],str[1])>0)
{
strcpy(string,str[0]);
}
else
{
strcpy(string,str[1]);
}
if(strcmp(str[2],string)>0)
{
strcpy(string,str[2]);
}
printf("\nthe largest:\n%s\n",string);
return 0;
}
编译结果如下:
第7章 用函数实现模块化程序设计
简单说明:
1、一个函数并不从属于另一个函数,即函数不能嵌套定义。函数间可以互相调用,但不能调用main函数,main函数是被操作系统调用的。
2、从用户使用的角度看,函数有两种:
1)库函数,它是由系统提供的,用户不必自己定义而直接使用它们。应该说明,不同的C语言编译系统提供的库函数的数量和功能会有一些不同,当然许多基本的函数是共同的。
2)用户自己定义的函数。它是用以解决用户专门需要的函数。
3、从函数的形式看,函数分两类:
1)无参函数。无参函数一般用来执行指定的一组操作。无参函数可以带回或不带回函数值,但一般以不带回函数值的居多。
2)有参函数。在调用函数时,主调函数在调用被调用函数时,通过参数向被调用函数传递数据,一般情况下,执行被调用函数时会得到一个函数值,供主调函数使用。
7.1输入两个整数,要求输出其中值较大者。要求用函数来找到大数
#include<stdio.h>
int bigger(int x,int y);
int bigger(int x,int y)
{
int z;
z=x>y?x:y;
return z;
}
int main()
{
int a,b,c;
printf("请输入两个正整数,并用空格隔开:\n");
scanf("%d%d",&a,&b);
c=bigger(a,b);
printf("较大值为c=%d\n",c);
return 0;
}
编译结果如下:
简单说明:
1、在定义函数中指定的形参,在未出现函数调用时,它们并不占内存中的存储单元。在发生函数调用时,函数max的形参被临时分配内存单元
2、调用结束,形参单元被释放,实参单元仍保留并维持原值,没有改变,如果在执行一个被调用函数时,形参的值发生改变,不会改变主调函数的实参的值
3、通常,希望通过函数调用使主调函数能得到一个确定的值,这就是函数值(函数的返回值)
1)在定义函数时指定的函数类型一般应该和return语句中的表达式类型一致
2)如果函数值的类型和return语句中表达式的值不一致,则以函数类型为准
如下:
将7.1稍作改动,将在bigger函数中定义的变量z改为float型。函数返回值的类型与指定的函数类型不同,分析其处理方法。
解题思路:如果函数返回值的类型与指定的函数类型不同,按照赋值规则处理。
#include <stdio.h>
int bigger(float x,float y);
int bigger(float x,float y)
{
float z;
z=x>y?x:y;
return z;
}
int main()
{
float a,b;
int c;
printf("请输入两个小数,并用空格隔开:\n");
scanf("%f%f",&a,&b);
c=bigger(a,b);
printf("bigger is %d\n",c);
return 0;
}
编译结果如下:
7.2输入4个整数,找出其中最大的数。用函数的嵌套调用来处理
简单说明:C语言的函数定义是互相平行、独立的,即函数不能嵌套定义,但可以嵌套调用函数,即调用一个函数的过程中,又可以调用另一个函数
解题思路:
1)main中调用max4函数,找4个数中最大者
2)max4中再调用max2,找两个数中的大者
3)max4中多次调用max2,可找4个数中的大者,然后把它作为函数值返回main函数
4)main函数中输出结果
#include <stdio.h>
int max4(int a,int b,int c,int d);
int max2(int a,int b);
int max2(int a,int b)
{
return a>b?a:b;
}
int max4(int a,int b,int c,int d)
{
int m;
m=max2(a,b);
m=max2(m,c);
m=max2(m,d);
return m;
}
int main()
{
int a,b,c,d,max;
printf("4 interger numbers:\n");
scanf("%d%d%d%d",&a,&b,&c,&d);
max=max4(a,b,c,d);
printf("max=%d\n",max);
return 0;
}
编译结果如下:
函数的递归调用:
7.3有5个学生坐在一起
1)问第5个学生多少岁?他说比第4个学生大2岁
2)问第4个学生岁数,他说比第3个学生大2岁
3)问第3个学生,又说比第2个学生大2岁
4)问第2个学生,说比第1个学生大2岁
5)最后问第1个学生,他说是10岁
请问第5个学生多大
解题思路:
要求第5个年龄,就必须先知道第4个年龄
要求第4个年龄必须先知道第3个年龄
第3个年龄又取决于第2个年龄
第2个年龄取决于第1个年龄
每个学生年龄都比其前1个学生的年龄大2
即:
age(5)=age(4)+2
age(4)=age(3)+2
age(3)=age(2)+2
age(2)=age(1)+2
age(1)=10
即:
#include <stdio.h>
int age(int n);
int main()
{
printf("NO.5,age:%d\n",age(5));
return 0;
}
int age(int n)
{
int c;
if(n==1)
{
c=10;
}
else
{
c=age(n-1)+2;
}
return c;
}
编译结果如下:
7.4用递归方法求n!
解题思路:
1)求n!也可以用递归方法,即5!等于4!×5,而4!=3!×4…,1!=1
2)可用下面的递归公式表示:
#include <stdio.h>
int fac(int n);
int main()
{
int n; int y;
printf("input an integer number:");
scanf("%d",&n);
y=fac(n);
printf("%d!=%d\n",n,y);
return 0;
}
int fac(int n)
{
int f;
if(n<0)
{
printf("n<0,data error!");
}
else if(n==0||n==1)
{
f=1;
}
else
{
f=fac(n-1)*n;
}
return(f);
}
编译结果如下:
7.5Hanoi(汉诺)塔问题。古代有一个梵塔,塔内有3个座A、B、C,开始时A座上有64个盘子,盘子大小不等,大的在下,小的在上。有一个老和尚想把这64个盘子从A座移到C座,但规定每次只允许移动一个盘,且在移动过程中在3个座上都始终保持大盘在下,小盘在上。在移动过程中可以利用B座。要求编程序输出移动一盘子的步骤。
解题思路:
1)要把64个盘子从A座移动到C座,需要移动大约264 次盘子。一般人是不可能直接确定移动盘子的每一个具体步骤的
2)老和尚会这样想:假如有另外一个和尚能有办法将上面63个盘子从一个座移到另一座。那么,问题就解决了。此时老和尚只需这样做:
(1) 命令第2个和尚将63个盘子从A座移到B座
(2) 自己将1个盘子(最底下的、最大的盘子)从A座移到C座
(3) 再命令第2个和尚将63个盘子从B座移到C座
编写程序:
1)用hanoi函数实现第1类操作(即模拟小和尚的任务)
2)用move函数实现第2类操作(模拟大和尚自己移盘)
3)函数调用hanoi(n,one,two.three)表示将n个盘从“one”座移到“three”座的过程(借助“two”座)
4)函数调用move(x,y)表示将1个盘子从x 座移到y 座的过程。x和y是代表A、B、C座之一,根据每次不同情况分别取A、B、C代入
#include <stdio.h>
void hanoi(int n,char one,char two,char three);
void move(char x,char y);
int main()
{
int m;
printf("the number of diskes:");
scanf("%d",&m);
printf("move %d diskes:\n",m);
hanoi(m,'A','B','C');
}
void hanoi(int n,char one,char two,char three)
{
if(n==1)
{
move(one,three);
}
else
{
hanoi(n-1,one,three,two);
move(one,three);
hanoi(n-1,two,one,three);
}
}
void move(char x,char y)
{
printf("%c-->%c\n",x,y);
}
编译结果如下:
数组元素作函数实参
7.6输入10个数,要求输出其中值最大的元素和该数是第几个数
解题思路:
1)定义数组a,用来存放10个数
2)设计函数max,用来求两个数中的大者
3)在主函数中定义变量m,初值为a[0],每次调用max函数后的返回值存放在m中
4)用“打擂台”算法,依次将数组元素a[1]到a[9]与m比较,最后得到的m值就是10个数中的最大者
#include <stdio.h>
int max(int x,int y);
int main()
{
int a[10],m,n,i;
printf("10 integer numbers:\n");
for(i=0;i<10;i++)
{
scanf("%d",&a[i]);
}
printf("\n");
for(i=1,m=a[0],n=0;i<10;i++)
{
if (max(m,a[i])>m)
{
m=max(m,a[i]);
n=i;
}
}
printf("largest number is %d\n",m);
printf("%dth number.\n",n+1);
}
int max(int x,int y)
{
return x>y?x:y;
}
编译结果如下:
数组名作函数参数
7.7有一个一维数组score,内放10个学生成绩,求平均成绩
解题思路:
1)用函数average求平均成绩,用数组名作为函数实参,形参也用数组名
2)在average函数中引用各数组元素,求平均成绩并返回main函数
#include <stdio.h>
float average(float array[10]);
int main()
{
float score[10],aver;
int i;
printf("input 10 scores:\n");
for(i=0;i<10;i++)
{
scanf("%f",&score[i]);
}
printf("\n");
aver=average(score);
printf("%5.2f\n",aver);
return 0;
}
float average(float array[10])
{
int i;
float aver,sum=array[0];
for(i=1;i<10;i++)
{
sum=sum+array[i];
}
aver=sum/10;
return aver;
}
编译结果如下:
7.8有两个班级,分别有5名和10名学生,调用一个average函数,分别求这两个班的学生的平均成绩
解题思路:
1)需要解决怎样用同一个函数求两个不同长度的数组的平均值的问题
2)定义average函数时不指定数组的长度,在形参表中增加一个整型变量i
3)从主函数把数组实际长度从实参传递给形参i
4)这个i用来在average函数中控制循环的次数
#include <stdio.h>
float average(float array[],int n);
int main()
{
float score1[5]={98.5,97,91.5,60,55};
float score2[10]={67.5,89.5,99,69.5,77,89.5,76.5,54,60,99.5};
printf("%6.2f\n",average(score1,5));
printf("%6.2f\n",average(score2,10));
return 0;
}
float average(float array[],int n)
{
int i;
float aver,sum=array[0];
for(i=1;i<n;i++)
{
sum=sum+array[i];
}
aver=sum/n;
return(aver);
}
编译结果如下:
7.9用选择法对数组中10个整数按由小到大排序
解题思路:
1)所谓选择法就是先将10个数中最小的数与a[0]对换;再将a[1]到a[9]中最小的数与a[1]对换……每比较一轮,找出一个未经排序的数中最小的一个
2)共比较9轮
#include <stdio.h>
void sort(int array[],int n);
int main()
{
int a[10],i;
printf("enter array:\n");
for(i=0;i<10;i++)
{
scanf("%d",&a[i]);
}
sort(a,10);
printf("The sorted array:\n");
for(i=0;i<10;i++)
{
printf("%d ",a[i]);
}
printf("\n");
return 0;
}
void sort(int array[],int n)
{
int i,j,k,t;
for(i=0;i<n-1;i++)
{
k=i;
for(j=i+1;j<n;j++)
{
if(array[j]<array[k])
{
k=j;
}
}
t=array[k];
array[k]=array[i];
array[i]=t;
}
}
编译结果如下:
多维数组名作函数参数
7.10有一个3×4的矩阵,求所有元素中的最大值
解题思路:
1)先使变量max的初值等于矩阵中第一个元素的值
2)然后将矩阵中各个元素的值与max相比,每次比较后都把“大者”存放在max中,全部元素比较完后,max 的值就是所有元素的最大值。
#include <stdio.h>
int max_value(int array[][4]);
int main()
{
int a[3][4]={{1,3,5,7},{2,4,6,8},{15,17,34,12}};
printf("Max value is %d\n",max_value(a));
return 0;
}
int max_value(int array[][4])
{
int i,j,max;
max = array[0][0];
for (i=0;i<3;i++)
{
for(j=0;j<4;j++)
{
if (array[i][j]>max)
{
max = array[i][j];
}
}
}
return max;
}
编译结果如下:
局部变量和全局变量
7.11有一个一维数组,内放10个学生成绩,写一个函数,当主函数调用此函数后,能求出平均分、最高分和最低分
解题思路:
1)调用一个函数可以得到一个函数返回值,现在希望通过函数调用能得到3个结果。
2)可以利用全局变量来达到此目的。
#include <stdio.h>
float average(float array[],int n);
float Max=0,Min=0;
int main()
{
float ave,score[10]; int i;
printf("Please enter 10 scores:\n");
for(i=0;i<10;i++)
{
scanf("%f",&score[i]);
}
ave=average(score,10);
printf("max=%6.2f\nmin=%6.2f\naverage=%6.2f\n",Max,Min,ave);
return 0;
}
float average(float array[],int n)
{
int i;
float aver,sum=array[0];
Max=Min=array[0];
for(i=1;i<n;i++)
{
if(array[i]>Max)
{
Max=array[i];
}
else if(array[i]<Min)
{
Min=array[i];
}
sum=sum+array[i];
}
aver=sum/n;
return aver;
}
编译结果如下:
说明:建议不在必要时不要使用全局变量
若外部变量与局部变量同名,分析结果
#include <stdio.h>
int max(int a,int b);
int a=3,b=5;
int main()
{
int a=8;
printf("max=%d\n",max(a,b)); //b为全局变量,a为局部变量,仅在此函数内有效
return 0;
}
int max(int a,int b)
{
int c;
c=a>b?a:b;
return c;
}
7.12变量的存储方式:动态存储方式与静态存储方式
从变量值存在的时间(即生存期)观察,变量的存储有两种不同的方式:静态存储方式和动态存储方式
1)静态存储方式是指在程序运行期间由系统分配固定的存储空间的方式
2)动态存储方式是在程序运行期间根据需要进行动态的分配存储空间的方式
静态存储区:
1)全局变量全部存放在静态存储区中
2)程序开始执行时给全局变量分配存储区,程序执行完毕就释放。在程序执行过程中占据固定的存储单元
动态存储区:
1)①函数形式参数②函数中定义的没有用关键字static声明的变量③函数调用时的现场保护和返回地址等存放在动态存储区
2)函数调用开始时分配,函数结束时释放。在程序执行过程中,这种分配和释放是动态的
简单说明:数据都存放在静态存储区和动态存储区
每一个变量和函数都有两个属性:数据类型和数据的存储类别
1)数据类型:如整型、浮点型等
2)存储类别指的是数据在内存中存储的方式(如静态存储和动态存储)
存储类别包括:自动的、静态的、寄存器的、外部的
3)根据变量的存储类别,可以知道变量的作用域和生存期
7.13局部变量的存储类别
1.自动变量(auto变量)
1)局部变量,如果不专门声明存储类别,都是动态地分配存储空间的
2)调用函数时,系统会给局部变量分配存储空间,调用结束时就自动释放空间。因此这类局部变量称为自动变量
3)自动变量用关键字auto作存储类别的声明
2.静态局部变量(static局部变量)
1)函数中的局部变量在函数调用结束后不消失而继续保留原值,即其占用的存储单元不释放,在下一次再调用该函数时,该变量已有值(就是上一次函数调用结束时的值),这时就应该指定该局部变量为“静态局部变量”,用关键字static进行声明
2)考察静态局部变量的值:
#include <stdio.h>
int f(int);
int main()
{
int a=2,i;
for(i=0;i<3;i++)
{
printf("%d\n",f(a));
}
return 0;
}
int f(int a)
{
auto int b=0;
static c=3;
b=b+1;
c=c+1;
return a+b+c;
}
编译结果如下:
3)输出1到5的阶乘值:
解题思路:
可以设计一个函数用来进行连乘,如第1次调用时进行1乘1,第2次调用时再乘以2,第3次调用时再乘以3,依此规律进行下去
#include <stdio.h>
int fac(int n);
int main()
{
int i;
for(i=1;i<=5;i++)
{
printf("%d!=%d\n",i,fac(i));
}
return 0;
}
int fac(int n)
{
static int f=1;
f=f*n;
return f;
}
编译结果如下:
3. 寄存器变量(register变量)
1)一般情况下,变量(包括静态存储方式和动态存储方式)的值是存放在内存中的
2)寄存器变量允许将局部变量的值放在CPU中的寄存器中
3)现在的计算机能够识别使用频繁的变量,从而自动地将这些变量放在寄存器中,而不需要程序设计者指定
7.14全局变量的存储类别
·全局变量都是存放在静态存储区中的。因此它们的生存期是固定的,存在于程序的整个运行过程
·一般来说,外部变量是在函数的外部定义的全局变量,它的作用域是从变量的定义处开始,到本程序文件的末尾。在此作用域内,全局变量可以为程序中各个函数所引用。
1、 在一个文件内扩展外部变量的作用域
1)外部变量有效的作用范围只限于定义处到本文件结束。
2)如果用关键字extern对某变量作“外部变量声明”,则可以从“声明”处起,合法地使用该外部变量
3)调用函数,求3个整数中的大者:
解题思路:
用extern声明外部变量,扩展外部变量在程序文件中的作用域。
#include <stdio.h>
int A,B,C;
int max();
int main()
{
extern int A,B,C;
printf("Please input 3 integers:\n");
scanf("%d %d %d",&A,&B,&C);
printf("max is %d\n",max());
return 0;
}
int max()
{
int m;
m=A>B?A:B;
if (C>m)
{
m=C;
}
return m;
}
编译结果如下:
2、将外部变量的作用域扩展到其他文件
1)如果一个程序包含两个文件,在两个文件中都要用到同一个外部变量Num,不能分别在两个文件中各自定义一个外部变量Num
2)应在任一个文件中定义外部变量Num,而在另一文件中用extern对Num作“外部变量声明”
3)在编译和连接时,系统会由此知道Num有“外部链接”,可以从别处找到已定义的外部变量Num,并将在另一文件中定义的外部变量num的作用域扩展到本文件
4)给定b的值,输入a和m,求a*b和a的m次方的值
解题思路:
(1)分别编写两个文件模块,其中文件file1包含主函数,另一个文件file2包含求am的函数。
(2)在file1文件中定义外部变量A,在file2中用extern声明外部变量A,把A的作用域扩展到file2文件。
#include <stdio.h>
int a;
int main()
{
int power(int);
int b=3,c,d,m;
printf("Please input a and m:");
scanf("%d%d",&a,&m);
c=a*b;
printf("%d*%d=%d\n",a,b,c);
d=power(m);
printf("%d**%d=%d\n",a,m,d);
return 0;
}
extern a;
int power(int n)
{
int i,y=1;
for(i=1;i<=n;i++)
{
y*=a;
}
return y;
}
编译结果如下:
3.将外部变量的作用域限制在本文件中
有时在程序设计中希望某些外部变量只限于被本文件引用。这时可以在定义外部变量时加一个static声明。
简单说明:
1)不要误认为对外部变量加static声明后才采取静态存储方式,而不加static的是采取动态存储
2)声明局部变量的存储类型和声明全局变量的存储类型的含义是不同的
3)对于局部变量来说,声明存储类型的作用是指定变量存储的区域以及由此产生的生存期的问题,而对于全局变量来说,声明存储类型的作用是变量作用域的扩展问题
4)用static 声明一个变量的作用是:
(1) 对局部变量用static声明,把它分配在静态存储区,该变量在整个程序执行期间不释放,其所分配的空间始终存在。
(2) 对全局变量用static声明,则该变量的作用域只限于本文件模块(即被声明的文件中)。
7.15存储类别小结
特殊:
static对局部变量和全局变量的作用不同
1)局部变量使变量由动态存储方式改变为静态存储方式
2)全局变量使变量局部化(局部于本文件),但仍为静态存储方式
3)从作用域角度看,凡有static声明的,其作用域都是局限的,或者是局限于本函数内(静态局部变量),或者局限于本文件内(静态外部变量)
7.16关于变量的声明和定义
1)把建立存储空间的变量声明称定义,而把不需要建立存储空间的声明称为声明
2)在函数中出现的对变量的声明(除了用extern声明的以外)都是定义
3)在函数中对其他函数的声明不是函数的定义
内部函数
1)如果一个函数只能被本文件中其他函数所调用,它称为内部函数
2)在定义内部函数时,在函数名和函数类型的前面加static,即: static 类型名 函数名(形参表)
3)内部函数又称静态函数,因为它是用static声明的
4)通常把只能由本文件使用的函数和外部变量放在文件的开头,前面都冠以static使之局部化,其他文件不能引用
外部函数
1)如果在定义函数时,在函数首部的最左端加关键字extern,则此函数是外部函数,可供其他文件调用
2)如函数首部可以为extern int fun (int a, int b)
3)如果在定义函数时省略extern,则默认为外部函数
4)有一个字符串,内有若干个字符,今输入一个字符,要求程序将字符串中该字符删去。用外部函数实现
解题思路:
1)分别定义3个函数用来输入字符串、删除字符、输出字符串
2)按题目要求把以上3个函数分别放在3个文件中。main函数在另一文件中,main函数调用以上3个函数,实现题目的要求
#include <stdio.h>
extern void enter_string(char str[]);
extern void delete_string(char str[],char ch);
extern void print_string(char str[]);
int main()
{
char c,str[80];
enter_string(str);
printf("Please enter the character to delete:\n");
scanf("%c",&c);
delete_string(str,c);
print_string(str);
return 0;
}
void enter_string(char str[80])
{
printf("Please input string:\n");
gets(str);
}
void delete_string(char str[],char ch)
{
int i,j;
for(i=j=0;str[i]!='\0';i++)
{
if(str[i]!=ch)
{
str[j++]=str[i];
}
}
str[j]='\0';
}
void print_string(char str[])
{
printf("The string after deletion is:%s\n",str);
}
编译结果如下: