第八章 数组

本文介绍了如何使用C语言处理数组,包括计算用户输入数字的平均数并输出大于平均数的数,数组的定义、初始化和运算,以及数组在函数参数中的使用。示例程序展示了统计特定范围内整数出现次数、判断素数以及二维数组的遍历和应用。
摘要由CSDN通过智能技术生成

第八章 数组

8.1.1 初试数组

如何写一个程序计算用户输入的数字的平均数,并输出所有大于平均数的数?

int num[100];
scanf("%d",&number[i]);
#include<stdio.h>
int main()
{
	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]);  //使用数组中的元素
			}
		}
	}
	return 0;
}

在这里插入图片描述

8.1.2 定义数组

<类型>变量名称[元素数量];

int grades[ 100];
double weight[20];
  • 元素数量必须是整数
  • C99之前:元素数量必须是编译时刻确定的字面量
  • 数组是一种容器(放东西的东西),特点是:
    • 其中所有的元素具有相同的数据类型;
    • 一旦创建,不能改变大小
    • *(数组中的元素在内存中是连续依次排列的)
int a[10]
  • 一个int的数组

  • 10个单元: a[0],a[1],…,a[9]

    a[0]a[1]a[2]a[3]a[4]a[5]a[6]a[7]a[8]a[9]
  • 每个单元就是一个int类型的变量

  • 可以出现在赋值的左边或右边:

    • a[2]=a[1]+6;
  • 在赋值左边的叫做左值

数组的单元

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

有效的数组下标

  • 编译器和运行环境都不会检查数组下标是否越界,无论是对数组单元做读还是写

  • 一旦程序运行, 越界的数组访问可能造成问题,导致程序崩溃

    • segmentation fault
  • 但是也可能运气好,没造成严重的后果

  • 所以这是程序员的责任来保证程序只使用有效的下标值: [0,数组的大小- 1]

长度为0的数组
可以但没必要

8.1.3 数组的例子:统计个数

写一个程序,输入数量不确定的[0,9]范围内的整数,统计每一种数字出现的次数,输入-1表示结束

#include<stdio.h>
int main()
{
	const int number=10;  //数组大小 
	int x;
	int count[number];    //定义数组 
	int i;
	for(i=0;i<number;i++){
		count[i]=0;       //初始化数组 
	}
	scanf("%d",&x);    //1.读入第一个x 
	while(x!=-1){         //2.如果x!=-1即x是要参与运算的数 
		if(x>=0&&x<=9){
			count[x]++;   //数组运算 
		}                  //3.在有效范围内,让计数器++ 
		scanf("%d",&x);
	}
	for(i=0;i<number;i++){
		printf("%d:%d\n",i,count[i]);   //4.遍历数组,计算I数组出现的次数 
	}
	return 0;
}

8.2.1 数组运算

数组的集成初始化

int a[]={2,4,6,7,1,3,5,9,11,13,23,14,32};
  • 直接用大括号给出数组的所有元素的初始值
  • 不需要给出数组的大小,编译器替你数数
int a[10]={[0]=2,[2]=3,6,}; //只有C99可以
  • 用[n]在初始化数据中给出定位

  • 没有定位的数据接在前面的位置后面

  • 其他位置的值补零

  • 也可以不给出数组大小,让编译器算

  • 特别适合初始数据稀疏的数组

数组的大小

sizeof给出整个数组所占据的内容的大小,单位是字节

sizeof(a)/sizeof(a[0])

sizeof(a[0])给出数组中单个元素的大小,于是相除就得到了数组的单元个数
这样的代码,一旦修改数组中初始的数据,不需要修改遍历的代码

数组的赋值

int a[]={2,4,6,7,1,3,5,9,11,13,23,14,32};
int b[]=a;     //这样不可以

数组变量本身不能被赋值
要把一个数组的所有元素交给另一个数组,必须采用遍历

for(i=0;i<length;i++){
    b[i]=a[i];
}
  • 通常都是使用for循环,让循环变量i从0到<数组的长度,这样循环体内最大的i正好是数组最大的有效下标

  • 常见错误是:

    • 循环结束条件是<=数组长度,或;
    • 离开循环后,继续用i的值来做数组元素的下标!

在一组给定的数据中,如何找出某个数据是否存在?

#include<stdio.h>
/*找出key在数组a中的位置,
@param key要寻找的数字
@param a要寻找的数组
@param length 数组a的长度
@return 如果找到,返回其在a中的位置:如果找不到则返回-1
*/
int search(int key,int a[],int length);
int search(int key,int a[],int length)
{
	int ret=-1;
	int i;
	for(i=0;i<length;i++){
		if(a[i]==key){
			ret=i;
			break;
		}
	}
	return ret;
}
int main()
{
	int a[]={2,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;
}

数组作为函数参数时,往往必须再用另一个参数来传入数组的大小

数组作为函数的参数时:
不能在[]中给出数组的大小
不能再利用sizeof来计算数组的元素个数!

8.2.2 数组例子:素数

//去掉偶数后,从3到x-1,每次加2
int isprime(int x)
{
    int ret=1;
    int i;
    if(x==1||(x%2==0&&x!=2))
        ret=0;
    for(i=3;i<x;i+=2){
        if(x%i==0){
            ret=0;
            break;
        }
    }
    return ret;
}
//如果x是偶数,返回0
//否则要循环(n-3)/2+1遍,n很大时就是n/2遍
//无须到x-1,到sqrt(x)就够了
int isprime(int x)
{
    int ret=1;
    int i;
    if(x==1||(x%2==0&&x!=2))
        ret=0;
    for(i=3;i<sqrt(x);i+=2){
        if(x%i==0){
            ret=0;
            break;
        }
    }
    return ret;
}
#include<stdio.h>
int isprime(int x,int knownprimes[],int number0fkownprimes);

int main(void)
{
	const int number=100;
	int prime[number]={2};
	int count=1;
	int i=3;
	while(count<number){
		if(isprime(i,prime,count)){
			prime[count++]=i;
		}
		i++;
	}
	for(i=0;i<number;i++){
		printf("%d",prime[i]);
		if((i+1)%5)
			printf("\t");
		else
			printf("\n");
	}
	return 0;
}
int isprime(int x,int knownprimes[],int number0fknownprimes)
{
	int ret=1;
	int i;
	for(i=0;i<number0fknownprimes;i++){
		if(x%knownprimes[i]==0){
			ret=0;
			break;
		}
	}
	return ret;
}


构造素数表

  • 欲构造n以内的素数表

    1. 令x为2
    2. 将2x、3x、4x直至ax<n的数标记为非素数
    3. 令x为下一个没有被标记为非素数的数,重复2;直到所有的数都已经尝试完毕
  • 欲构造n以内(不含)的素数表

    1. 开辟prime[n],初始化其所有元素为1,prime[x]为1 表示x是素数
    2. 令x=2
    3. 如果x是素数,则对于(i=2;xi<n;i+ + )令prime[ix]=0
    4. 令x++,如果x<n,重复3,否则结束
    int main()
    {
    	const int maxNumber=25;
    	int isPrime[maxNumber];
    	int i;
    	int x;
    	for(i=0;i<maxNumber;i++){
    		isPrime[i]=1;
    	}
    	for(x=2;x<maxNumber;x++){
    		if(isPrime[x]){
    			for(i=2;i*x<maxNumber;i++){
    				isPrime[i*x]=0;
    			}
    		}
    	}
    	for(i=2;i<maxNumber;i++){
    		if(isPrime[i]){
    			printf("%d\t",i);
    		}
    	}
    	printf("\n");
    	return 0;
    }
    

8.2.3 二维数组

int a[3][5]

通常理解为a是一个3行5列的矩阵

在这里插入图片描述

二维数组的遍历

for(i=0;i<3;i++){
    for(j=0;j<5;j++){
        a[i][j]=i*j;
    }
}

a [ i ] [ j ]是一个int
表示第i行第j列上的单元

二维数组的初始化

int a[][5]={{0,1,2,3,4},{2,3,4,5,6,}};
  • 列数是必须给出的,行数可以由编译器来数
  • 每行一个{},逗号分隔
  • 最后的逗号可以存在,有古老的传统
  • 如果省略,表示补零
  • 也可以用定位( * C99 ONLY)

tic-tac-toe游戏

在这里插入图片描述

读入一个3X3的矩阵,矩阵中的数字为1表示该位置上有一个X,为0表示为O
程序判断这个矩阵中是否有获胜的一方,输出表示获胜一方的字符X或O,或输出无人获胜

//读入矩阵
const int size=3;
int board[size][size];
int i,j;
int num0fX;
int num0f0;
int result=-1;  //-1:没人赢,1:X赢,0:0赢
//读入矩阵
for(i=0;i<size;i++){
    for(j=0;j<size;j++){
        scang("%d",&board[i][j]);
    }
}
//检查行
for(i=0;i<size&&result==-1;i++){
    num0f0=num0fX=0;       //0和X初始化为0
    for(j=0;j<size;j++){
        if(board[i][j]==1)
            num0fX++;
        else
            num0f0++; 
    }
    if(num0f0==size){
        result=0;
    }else if(num0fX==size){
        result=1;
    }
}
//检查列
if(result==1){
    for(j=0;j<size&&result==-1;j++){
    	num0f0=num0fX=0;       //0和X初始化为0
    	for(i=0;i<size;i++){
        	if(board[i][j]==1)
            	num0fX++;
        	else
            	num0f0++; 
    	}
    	if(num0f0==size){
        	result=0;
    	}else if(num0fX==size){
        	result=1;
    	}
	}
}

//检查对角线
num0f0=num0fX=0;
for(i=0;i<sizei;i++){
	if(board[i][j]==1)
         num0fX++;
     else
         num0f0++; 
}
if(num0f0==size){
    result=0;
}else if(num0fX==size){
    result=1;
}

num0f0=num0fX=0;
for(i=0;i<sizei;i++){
	if(board[i][size-i-1]==1)
         num0fX++;
     else
         num0f0++; 
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值