数组与函数

一、数组

数组概念及基础知识

定义数组
•<类型>变量名称[元素数量];
• Int grades[ 100];
• double weight [20];
•元素数量必须是整数
•C99之前:元素数量必须是编译时刻确定的字面量

数组
• 是一种容器(放东西的东西),特点是:
•其中所有的元素具有相同的数据类型;
•一旦创建,不能改变大小
•* (数组中的元素在内存中是连续依次排列的)

int a 10
•一个int的数组
• 10个单元:a[o],a[1],a[9]
•每个单元就是一个int类型的变量
•可以出现在赋值的左边或右边:
• a[2]= a[1]+6;
•*在赋值左边的叫做左值

数组的单元
•数组的每个单元就是数组类型的一个变量
•使用数组时放在口中的数字叫做下标或索引,下标从0
开始计数:
• grades [0]
• grades[99]
• average[5]

有效的下标范围
•编译器和运行环境都不会检查数组下标是否越界,无论是对数组单元做读还是写
•一旦程序运行,越界的数组访问可能造成问题,导致程序崩溃
•segmentation fault
• 但是也可能运气好,没造成严重的后果
•所以这是程序员的责任来保证程序只使用有效的下标值:[0,数组的大小一1]

长度为0的数组
·int a[0]
·可以存在但无用

1、利用数组求平均值

	int x;
	double sum = 0;
	int cnt = 0;
	int number[100];		//定义数组 
	scanf("%d", &x);
	while ( x!= -1 ){
		number[cnt]=x;		//对数组中的元素赋值 
		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]);		//遍历数组 
			}
		}
	}

2、求1-9出现的次数

	const int number = 10;
	int x;
	int count[number];
	int i;
	
	for(i=0; i<number;i++) {
		count[i]=0;
	}
	scanf("%d", &x);
	while(x!=-1){
		if (x>=0 && x<=9) {
			count[x] ++;
		}
		scanf("%d",&x);
	}
	for (i=0;i<number;i++){
		printf("%d:%d\n", i, count[i]);
	}

二、函数

什么是函数?
•函数是一块代码,接收零个或多个参数
做一件事情,并返回零个或一个值
•可以先想像成数学中的函数:
•y=f(x)

1、函数求和

	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);
	}//函数体
	 
	int main()
	{
		sum(1, 10);
		sum(20, 30);
		sum(35,45);

以上这种注释方法不可取
这里只是为了便于认识函数

调用函数
•函数名(参数值);
•()起到了表示函数调用的重要作用
•即使没有参数也需要()
•如果有参数,则需要给出正确的数量和顺序
•这些值会被按照顺序依次用来初始化函数
中的参数

函数返回
·函数知道每一次在哪里调用它,会返回到正确的地方

从函数中返回值
·return停止函数的执行,并送回一个值
·return;
·return 表达式;
·可以赋值给变量
·也可以再传给函数
·甚至可以丢弃

没有返回值的函数
·void函数名(参数表)
·不能使用带值的return
·可以没有return
·调用的时候不能做没有返回值的赋值

如果函数有返回值必须使用带值的return

2、函数定义可在后也可在前

	void sum(int begin, int end); 		//原型声明 
	 
	int main()
	{
		sum(1, 10);
		sum(20, 30);
		sum(35,45);
		
		return 0;
	}	
		
		
	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);		
	}	

函数先后关系
·c的编译器自上而下顺序分析你编码
·再看到sum(1,10)的时候,他需要知道sum()的样子
·也就是知道sum()要几个参数,每个参数的类型如何,返回什么类型
·这样才能检验你对sum()的调用是否正确

函数原型
·函数头,已分号“;”结尾,就构成函数的原型
·函数原型的目的是告诉编译器这个函数长什么样
·名称
·参数(数量及类型)
·返回类型
·现在一般写在调用它的函数前

调用函数
·如果函数有参数,调用函数时必须传递给他数量、类型的正确的值
·可以传递给函数的值是表达式的结果,这包括
·字面量
·变量
·函数的返回值
·计算的结果

3、值

	void swap(int a, int b);		//a,b形参 ;参数 
	
	int main()
	{
		int a = 5;
		int b = 6;
		
		swap(a,b);		//实参 ; 值 
		
		printf("a=%d b=%d\n", a, b);		
		
		return 0;
	}
	
	void swap(int a, int b)		//形参 ; 参数 
	{
		int t = a;
		a = b;
		b = t;
	}

传值
•每个函数有自己的变量空间,参数也位于这个独立的空间中,和其他函数没有关系
•过去,对于函数参数表中的参数,叫做”形式参数“,调用函数时给的值叫做“实际参数”
•现在,对于函数参数表中的参数,叫做”参数“,调用函数时给的值叫做“值”

本地变量
·函数的每次运行就产生了一个独立的变量空间这个空间中的变量,是函数的这次运行所独有的作本地变量
·定义在函数内部的变量就是本地变量
·参数也是本地变量

变量的生存期和作用域
·生存期:什么时候这个变量开始出现了,到什么时候它消亡了
·作用域:在(代码的)什么范围内可以访问这个变量(这个变量可以起作用)
·对于本地变量,这两个问题的答案是统一的:大括号内一块

本地变量的规则
•本地变量是足义在块内的
•它可以是定义在函数的块内
•也可以定义在语句的块内
•甚至可以随便拉一对大括号来定义变量
•程序运行可以这个块之前,其中的变量不存在,离开这个块,其中的变量就消失了
•块外面定义的变量在里面仍然有效
•块里面定义了和外面同名的变量则掩盖了外面的
•不能在一个块内定义同名的变量
•本地变量不会被默认初始化

没有参数时
·void f(void)
·还是void f()
·在传统的C中,它表示f函数的参数表未知,并不表示没有参数

调用函数时圆括号里的逗号是标点符号,不是运算符,例f(a,b)
而f((a,b))中逗号是运算符

C语言不允许嵌套定义

三、数组运算

数组的集成初始化
int a[] = {2,4,6,7,1,3,5,9,11,13,23,14,32};
•直接用大括号给出数组的所有元素的初始值
• 不需要给出数组的大小,编详器替你数数

集成初始化时的定位 C99 ONLY!
int all0] ={
[0] =2, [2]=3, 6 ,
•用n在初始化数据中给出定位
•没有定位的数据接在前面的位置后面
•其他位置的值补零
•也可以不给出数组大小,让编译器算
•特别适合初始数据稀疏的数组

数组的大小
1、sizeof给出整个数组所占据的内容的大小,单位是字节
sizeof(a)/sizeof(a[0])
2、sizeof[0])给出数组中单个元素的大小,于是相除就得到了数组的单元个数
3、这样的代码;一旦修改数组中初始的数据,不需要修改遍历的代码

数组的赋值
int a[] ={ 2,4,6,7,1,3,5,9,11,13,23,14,32};
不能 Int b[]=a[];
1、数组变量本身不能破赋值
2、要一个数组的所有元素交给另一个数组,必领采用遍历
for( i=0; i<length; i++ ) {
b[i] = a[i];
}

遍历数组

	for  ( i=0; i<length; i++ ) {
	b[i]=a[i];
	}
	
	for  (i =0; i<number; i++) {
	Count[i];
	}
	
	for (i=o; i<length; i++){
	If ( a[i] == key ) {
	ret = i
	break;
	}
	}
	
	for ( i=0; i<cnt; i++ ) {
	If ( number[i] > average ) {
	Printf(%d”, number[i]);
	}
	}
	
	for ( i=0; i=number; i++ ) {
	Printf(%d:%d\n”, i, count[i]);
	}

1、通常都是使用for循环,让循环变量以0到<数组的长度,这样缩环体内最大的正好是数组最大的有效下标
2、常见错误是:
•循环结束条件是<=数组长度,或;
•离开循环后,继续用i的值来做数组元素的下标!

数组作为函数参数时:
•往往必须再用另一个参数来传人数组的大小
•不能在中给出数组的大小
•不能再利用sizeof来计算数组的元素个数

1、二维数组(矩阵)井字棋

#include <stdio.h>

int main()
{
    const int size = 3;
    int board[size][size];
    int i, j;
    int numOfX1; 
    int numOfO1;
    // 添加两个变量,判断行列的时候,标记列中X和O的个数;判断对角线的时候,标记另一条对角线的X和O的而数量;以便减少循环次数。
    int numOfX2; 
    int numOfO2;
    int result = -1;  // -1:没人赢,1:X赢,0:O赢 
    // 读入矩阵
    for(i = 0;i < size;i++){
        for(j=0;j <size;j++){
            scanf("%d",&board[i][j]);
        }
    }
    // 判断行列
    for (i = 0; i < size && result == -1; i++)
    {
        numOfX1 = numOfO1 = numOfX2 = numOfO2 = 0;
        for (j = 0; j < size; j++)
        {
            if (board[i][j] == 1)
            {
                numOfX1++;
            }
            else
            {
                numOfO1++;
            }
            if (board[j][i] == 1)
            {
                numOfX2++;
            }
            else
            {
                numOfO2++;
            }
        }
        if (numOfO1 == size || numOfO2 == size)
        {
            result = 0;
        }
        else if (numOfX1 == size || numOfX2 == size)
        {
            result = 1;
        }
    }
    // 判断对角线
    if (result == -1)
    {
        numOfX1 = numOfO1 = numOfX2 = numOfO2 = 0;
        for (i = 0; i < size && result == -1; i++)
        {
            if (board[i][i] == 1)
            {
                numOfX1++;
            }
            else
            {
                numOfO1++;
            }
            if (board[i][size - i - 1] == 1)
            {
                numOfX2++;
            }
            else
            {
                numOfO2++;
            }
        }
        if (numOfO1 == size || numOfO2 == size)
        {
            result = 0;
        }
        else if (numOfX1 == size || numOfX2 == size)
        {
            result = 1;
        }
    }
    if (result == 0)
    {
        printf("O方胜\n");
    }
    else if (result == 1)
    {
        printf("X方胜\n");
    }
    else
    {
        printf("平局\n");
    }
 
    return 0;

}

2、线性搜索

	#include <stdio.h>
	
	/*
	找出key在数组a中的位置
	@param key 要寻找的数宇
	@param a要寻找的数组
	@param length 数组a的长度
	@return 如果找到,返回其在a中的位置;如果找不到则返回-1
	*/
	int search(int key, int a[], int length);
	int main(void)
	{

	int a[] = {12,4,6,7,1,3,5,9,11,13,23,14,32}; 
	int x;
	int loc; 
	printf("请输入一个数字:");
	scanf("%d", &x); 
	loc=search(x, a, sizeof(a)/sizeof(a[0]));
	if ( loc != -1 ) {
		printf("%d在第%d个位置上\n", x, loc);
	}else{
		printf("%d不存在\n",x);
	}
	
	return 0;
	}
	int search(int key, int a[], int length)
	{
		int ret = -1;
		int i;
		for ( i=0; i< length; i++ ) {
			if ( a[i] == key ) {
			ret = 1;
			break;
			}
		}
		return ret;
	}

3、搜索的例子 美分对应单词

#include <stdio.h>

int amount[] = {1,5,10,25,50};
char *name[] = {"penny", "nickel", "dime", "quarter", "half-dollar"};

int search(int key, int a[], int len)
{
	int ret = -1;
	for ( int i=0; i<len; i++ )
	{
		if ( key == a[i] )
		{
			ret = i;
			break;
		}
	}
	return ret;
}

int main()
{
	int k = 10;
	int r = search(10, amount, sizeof(amount)/sizeof(amount[0]));
	if ( r > -1 )
	{
		printf("%s\n", name[r]);
	}
	return 0;
}

4、数字排序(由小到大)

#include <stdio.h>

int max(int a[], int len)
{
	int maxid = 0;
	for ( int i=1; i<len; i++ )
	{
		if ( a[i] > a[maxid] )
		{
			maxid = i;
		}
	}
	return maxid;
}

int main()
{
	int a[] = {2,45,6,12,87,34,90,24,23,11,65};
	int len = sizeof(a)/sizeof(a[0]);
	
	//选择排序 
	for ( int i=len-1; i>0; i-- )
	{
		int maxid = max(a, i+1);
		//swap a[maxid], a[len-1]
		int t = a[maxid];
		a[maxid] = a[i];
		a[i] = t;
	}
	
	for ( int i=0; i<len; i++)
	{
		printf("%d ", a[i]);
	}
	
	
	return 0;
	
	
}

5、搜索对应位置

#include <stdio.h>

int search(int key, int a[], int len)
{
	int ret = -1;
	for ( int i=0; i<len; i++ )
	{
		if ( key == a[i] )
		{
			ret = i;
			break;
		}
	}
	return ret;		//单一出口 
}

int main()
{
	int a[] = {1,3,2,5,12,14,23,6,9,45};
	int r = search(12, a, sizeof(a)/sizeof(a[0]));
	printf("%d\n", r);
	return 0;
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值