【新手C语言】6.数组与函数

6.数组与函数

前面的都是小闹的东西
如果之前有人用之前的知识和你装X,那多半是个sb

下面,我们正式进入"基础的基础"的大门

数组

数组初步介绍

当我们要存储同一类型的多个变量时,我们使用数组
可以把数组看成一个篮子,相同类型的变量全部放进去

<数组类型> <名字> [大小]
int GroupA [100];

<类型> <名称> [元素数量]        这里的类型是指数组内部存储的数据的类型 
	int grades[100]; 
	doubke weight[20];

数组通过下标来访问对应位置的变量,下标从0开始
我们上面定义了大小为100的数组,则下标范围是0-99

另外,元素数量必须是整数
在C99之前:元素数量必须是编译时刻确定的字面量 (不能是变量、程序运行过程中动态产生的数字)

数组定义实例:

#include <stdio.h>
int main(){
	//写一个程序,计算平均数并输出大于平均数的数字 
	
	int x ;
	double sum = 0;
	int cnt = 0 ;
	int number [100]; //定义一个数组,其大小为100个 
	//int 名字A [大小X] 表示这个数组A里面最多可以放 X个int    
	
	scanf("%d",&x);
	while (x! = -1){
		number [cnt] = x ;  //让数组上cnt位置的那个单元=x ;而cnt是递增的,所以x分别会在1,2,3....位置上存放 
		//对数组中的元素进行赋值
		 
		sum += x ;
		cnt ++;
		scanf ("%d",&x);
	} 
	if (cnt > 0 ){
		printf("%f \n",sum/cnt);
		int i ;
		for (i = 0 ; i<cnt;i++){  //进行数组数字的输出。遍历数组
		//遍历数组:浏览整个数组 
		 
			if (number[i]>sum/cnt){//使用数组中的元素 
				printf("%d \n",number[i]);
				//当数组i位置的数符合条件,输出它 
			}
			
		} 
	}
	
	;return 0 ;
}

1.数组中的元素具有相同的数据类型
2.一旦创建,数组不能改变其大小
3.使用数组时在[]中的数字是下标/索引,下标从0开始计数
4.!!无论是编译器还是运行环境,都不会去检查下标是否越界,无论你在读还是写(segmentation fault)
5.数组中的元素在内存中是连续依次排列的
6.可以创建长度为0的数组,但是没什么锤子用

二维数组

我们把数放到一个方形区域里来,想象一个个方格!
二维数组的定义和使用同一维,不过它有两个中括号,代表行列,先行后列

遍历二维数组将利用嵌套循环

#include <stdio.h>
int main(void){
	int a [3][5] ; //定义了一个三行五列的矩阵,定义基本都是先行(y数)后列(x数)的
	int therow = 3 ; 
	int thecol = 5 ;
	//二维数组的遍历
	for(int i=0;i< therow ;i++){
		for(int j=0;j<thecol;j++){
			a [i][j] = (i+1)*(j+1) ;  //数组名字+数组下标,就可以表示这是一个普通的变量了,可以在一些地方直接使用
			printf("%d \n",a[i][j]);
		}
	}
	
	//二维数组初始化
	int b [][5] = {
		{1,2,3,4,5},
		{6,2,4,5,7},
		
	};
	/*
		列数是不可以省略的,函数可以让编译器自己整
		每个{}之间使用大括号隔开,最后一个的逗号存不存在无所谓,如果省略,表示“补零”
	*/
	
	; return 0 ;
}

函数

重头戏之一来了

定义函数

<返回值> <函数名字>(参数表){
函数执行,如果有返回值的话要return
}

比如我们定义一个加法的函数sum

void sum(int begin,int end){
	int i ; 
	int sum = 0 ; 
	for(i=begin ; i<=end ;i++){
		sum+= i;
	}
	printf("%d 到 %d的和是%d \n",begin,end,sum);
}

定义的函数要写在用它的地方之前才行,比如我想在主函数中使用sum函数,就要先写它
实例:

#include <stdio.h>
void sum(int begin,int end){
	int i ; 
	int sum = 0 ; 
	for(i=begin ; i<=end ;i++){
		sum+= i;
	}
	printf("%d 到 %d的和是%d \n",begin,end,sum);
}
/*
在这里,我们在主函数之前定义了一个自己的函数sum 
*/
int main (void){
	sum(1,10);//在这里,我们运用了自己的sum函数 
	sum(20,30);
	sum(35,45); 
	; return 0 ;
} 

显然,这样子并不美观,那么我们可以先用原型声明来“占位”

原型声明

我们可以现在最开始声明我们这个函数的基本内容,而不写执行代码
然后在主函数结束后,再在后面补上对应的执行代码
比如:

#include <stdio.h>
//C的编译器是由上而下来分析代码的,和eclipse不一样,这导致你要用的函数需要在前面先写出来
//这个在各编译器是不一样的,不过还是建议用的先写在前面

//但是可以把函数头加上分号放在前面,其它部分放在后面,这样就可以了。这个做法叫做  原型声明 
void sum (int a , int b);  //声明 

int main ()
{
	sum(1,10);
	; return 0 ; 
}

void sum (int a, int b){  //定义 
	int i ; 
	int sum = 0 ; 
	for (i =a ; i <=b ; i ++){
		sum +=1 ;  
	}
}

//另外,原型声明里面可以只给参数类型,不给参数名字。因为原型声明的意义就是让编译器知道有这个东西 

return

返回返回值的操作是必不可少的,而且要和你所声明的返回值对应
当然,如果你声明返回值是void(无),那就不用return了

#include <stdio.h> 、
//当使用void类型的函数时,函数是没有返回值的,也就是可以没有return 
int max (int a,int b)
{//返回值是int类型的函数max 
	int ret ; 
	if(a>b){
		ret = a ; 
	}else {
		ret = b ; 
	}
	return ret ; //返回一个ret的数值,另外在一个函数里面可以有多个return语句,而且return不一定要在尾(不过这不是单一出口,习惯不好) 
}

int main () {
/* return 
1.return 会停止函数的运行,并且返回一个值
2.写法  return <值> ;  或者  return[表达式] ;
 
*/
int a,b,c ; 
c = max(12,10);
printf("%d \n ",c);


return 0 ; 
}

参数传递和本地变量

说实话觉得这里有一点点点点深入了,不过还是写一下好了

函数每次运行都产生独立的变量空间
在这个空间中的变量是它这次运行独有的,称为本地变量
定义在函数内部的变量就是本地变量/局部变量
参数也是本地变量/局部变量

生存期:变量从出现到消失的时间
作用域:该变量可以起作用的范围
对于本地变量,二者属于一个范围,那就是大括号内,我们把他叫

1.本地变量是定义在块内的,可以是函数块内,也可以是语句块内
2.程序运行到某个块之前,该块其中的变量是不存在的,离开了之后,其中的变量也会消失
块外面定义的变量在块里面是依然生效的
3.如果块里面定义了和外面同名的变量,那么块内的变量会覆盖外面的 (Java不能这么干)
4.一个块中是不能定义同名变量的
5.本地变量不会被默认初始化,参数在进入函数的时候被初始化了

#include <stdio.h>
//以下内容请利用debug辅助理解

//这样的代码可以完成a、b数值的互换吗   答案是不可以 
void swap(int a , int b);

int main(void){
	int a = 5 ; 
	int b = 16 ; 
	
	swap(a,b);
	printf("a = %d b = %d",a,b);
	return 0 ;
}

void swap(int a,int b){
	//虽然在这里的参数是a b ,刚才传进来的数值也是a b ,但实质上二者是完全不同的东西
	//swap函数中,只是把a的值5,以及把b的值16 给到了swap的形式参数a b 里面,此ab非彼ab
	 
	int t = a ;
	a = b ; 
	b = t ;
}

其它

1.void f(void) 表示f函数没有参数
void f() 表示f函数的参数表未知(传统C)

2.逗号在圆括号内算作标点符号,而不是运算符
f(a,b) 传入a,b
f((a,b)) 传入(a,b),此时我们要的是(a,b)而非a,b。因此逗号会被当作运算符被使用

3.C语言不允许在函数里面定义函数

C啊,你是那么牛逼那么基础,又是那么捞

#include <stdio.h>
void swap(); //原型声明

int main(void){
	int a = 5 ; 
	int b = 6 ; 
	
	//原型声明的时候外面没有指定参数,在这里外面尝试传入两个int
	swap(a,b); //而事实上,我们的函数会对两个double进行处理,因此结果会出错(但是运行是正常的)
	printf("a = %d , b = %d \n",a,b);
	
	
	;return 0 ; 
}

//注意这里给的是double
void swap (double a , double b){
	int t = a ; 
	printf("IN SWAP,a = %f , b = %f  \n",a,b);
	a = b ; 
	
	b = t ; 
}

数组运算

因为有那么点承上启下的意思,所以放在这里了

集成初始化时的定位:
1.用[n]在初始化数据中给出定位
2.没有定位的数据会接在前面的位置后面
3.其它位置的数值同前文,补为0
4.也可以不给出数组的大小,让编译器自己算
5.这种做法比较适合初始数据稀疏的数组

#include <stdio.h>
int main (void){
	
	int a [] = {1,2,3,5,6,7};  //集成初始化
	for(int i=0;i<7;i++){  //这里提一句,很多时候习惯使用<某个阙值
		printf("%d \t",a[i]);
	}
	
	//如果一开始就规定了数组的大小,但是没有填充完数组,那么会把剩余未规定的部分全部初始化为0
	
	//int a [10] ={2};
	
	
	//int b[10] = {[0] = 2 , [2] =3 ,6 ,};  只能在C99下使用				
	
	//sizeof可以给出整个数组所占据的内容的大小,单位为字节。在整形数组中,一个单位4字节
	
	printf("\n %d \n",sizeof(a));
	printf("\n %d \n",sizeof(a[0]));
	printf("\n 所以a的大小就是 %d \n",sizeof(a) / sizeof(a[0]));
	
	//sizeof(a) / sizeof(a[0] 起到了Java中类似与length系列的作用

	; return 0 ; 
}

数组不能直接被赋值,像 int b [] = a 是不行的,我们只能使用遍历来完成这件事
数组作为函数参数时,我们习惯于用另一个参数来传入数组的大小————为什么呢,继续看下一篇吧

posted @ 2021-09-16 19:43  RetenQ  阅读(347)  评论(0编辑  收藏  举报