数组学习2

1、二维数组的定义和使用:
(1)定义形式:
类型名 数组名 [行长度][列长度];
类型名:数组中每个元素的类型;
数组名:数组变量(数组)的名称;
行长度和列长度:整型常量表达式,分别给定数组的行数和列数;
例如:int a[3][2]//定义一个二维数组,3行2列,共3*2=6个元素
(2)引用:
二维数组的引用要指定两个下标,即行下标和列下标,形式为:
数组名 [行下标][列下标]
如:a[0][1]
注意下标不要越界!
!!!行长度的合理取值范围为:[0,行长度-1]!!!
!!!列长度的合理取值范围为:[0,列长度-1]!!!
二维数组的元素按先行后列的形式顺序存放。
2、二维数组的初始化:
(1)分行赋初值:
一般形式为:
类型名 数组名 [行长度][列长度] = {{初值表0},……{初值表k},……};
如:int a[3][3] = {{1,2,3},{4,5,6},{7,8,9}}; 初始化数组a。
此时,a数组中各元素为:
1 2 3 
4 5 6
7 8 9
二维数组的初始化也可以只针对部分元素:
static int b[4][3] = {{1,2,3},{ },{4,5}}
//只对b数组第0行全部元素赋初值和第二行的前两个元素赋初值,其余元素初值都是0.
(2)顺序赋初值:
一般形式为:
类型名 数组名[行长度][列长度] = {初值表};
如:int a[3][3] = {1,2,3,4,5,6,7,8,9};
即等价于:int a[3][3] = {{1,2,3},{4,5,6},{7,8,9}};
注意:
如果只对部分元素赋初值,要注意初值表中数据的书写顺序。
如:static int b[4][3] = {1,2,3,0,0,0,4,5};
等价于:static int b[4][3] = {{1,2,3},{ },{4,5}};
如在初值表中列出了全部行,就可以省略行长度。
如:static int b[4][3] = {1,2,3,4,5,6,7,8,9};
等价于:static int b[ ][3] = {1,2,3,4,5,6,7,8,9};
不过建议不要省略行长度!!!
4、使用二维数组编程:
讲行下标和列下标分别作为循环变量,通过二重循环,就可以遍历二维数组。
一般把行下标作为外循环的循环变量,列下标作为内循环的循环变量,可以提高程序执行效率!
编程如下:
for(j=0;j<n;j++){
    for(i=0;i<m;i++){
        scanf("%d",&a[i][j]);
    }
}

矩阵的术语于二维数组下标的对应关系

术语

含义下标规律
主对角线从矩阵的左上角至右下角的连线i == j

上三角

主对角线以上的部分

i <= j
下三角主对角线以下的部分i >= j
副对角线从矩阵的右上角至左下角的连线i + j == N - 1


例:求矩阵的最大值。输入两个正整数m和n(1<=m,n<=6),再输入1个m*n的矩阵,找出
最大值及它的行下标和列下标。假设最大值唯一。

#include <stdio.h>
//以下为宏定义,方便使用
#define MAXN 6
#define MAXM 6
int main(void)
{
	int i,j,m,n;
	int a[MAXN][MAXM];
	int row,col;//row为行下标,col为列下标 
	scanf("%d %d",&m,&n);
	//行下标作为外循环 
	for(i = 0;i < m;i++){
		//列下标作为内循环
		for(j = 0;j < n;j++){
			scanf("%d",&a[i][j]);	
		} 
	}
	//输入完毕!
	//以下为寻找最大值及其行下标和列下标 
	row = 0;
	col = 0;
	for(i = 0;i < m;i++){
		for(j = 0;j < n;j++){
			if(a[row][col] < a[i][j]){
				row = i;
				col = j;
			}
		}
	}
	//寻找完毕
	//以下为输出最大值及其行下标和列下标
	printf("max = a[%d][%d] = %d\n",i,j,a[row][col]); 
	return 0;
} 

从中的启发:
1)宏定义前要有“#”,不然无定义
2)行下标作为外循环,列下标作为内循环
3)具体步骤与一维数组操作一致 

 练习:方阵转置。输入一个正整数n(1<=n<=6),根据下式生成一个n*n的方阵,将该方阵转置(行列互换)后输出。
1  2  3 
4  5  6 
7  8  9

1  4  7 
2  5  8 
3  6  9


我的编程如下:

#include <stdio.h>
#define MAXN 6
#define MAXM 6
int main(void)
{
	int i,j,n,count = 0,temp;
	int a[MAXN][MAXM];
	scanf("%d",&n);
	for(i = 0;i < n;i++){
		for(j = 0;j < n;j++){
			scanf("%d",&a[i][j]);
		}
	}
	//输入完毕
	//以下对矩阵转置输出
	for(i = 0;i < n;i++){
		for(j = 0;j < n;j++){
			temp = a[i][j];
			a[i][j] = a[j][i];
			a[j][i] = temp;
		}
	} 
	//转换完毕
	//以下对转换后的矩阵进行输出
	for(j = 0;j < n;j++){
		for(i = 0;i < n;i++){
			printf("%d ",a[i][j]);
			count++;
			if(count >= n&&count % n == 0){
				printf("\n");
			}
		}
	} 
	return 0;
}

书本编程如下:

#include <stdio.h>
#define MAXN 6
#define MAXM 6
int main(void)
{
	int i,j,n,count = 0,temp;
	int a[MAXN][MAXM];
	scanf("%d",&n);
	for(i = 0;i < n;i++){
		for(j = 0;j < n;j++){
			scanf("%d",&a[i][j]);
		}
	}
	//输入完毕
	//以下对矩阵转置输出
	for(i = 0;i < n;i++){
		for(j = 0;j < n;j++){
            //以下遍历上三角阵
			if(i <= j){
				temp = a[i][j];
				a[i][j] = a[j][i];
				a[j][i] = temp;
			}
			
		}
	} 
	//转换完毕
	//以下对转换后的矩阵进行输出
	for(i = 0;i < n;i++){
		for(j = 0;j < n;j++){
			printf("%d ",a[i][j]);
			count++;
			if(count >= n&&count % n == 0){
				printf("\n");
			}
		}
	} 
	return 0;
}

两者的区别为:

1)书本中的编程只遍历上三角阵,我的编程遍历全部元素

2)书本中输出时与输入时一致,都是把行下标在外,列下标在内,而我的编程是行下标在内,列下标在外

输出结果都为:

只遍历上三角阵的代码有两种:

for(i = 0;i < n;i++){
    for(j = 0;j < n;j++){
        if(j <= j){
            ...
        }    
    }    
}
for(i = 0;i < n;i++){
        for(j = i;j < n;j++){
            ...
        }
}

听课后的启示:

如果遍历所有元素,相当于转置后的元素又转置回来了,等同于无遍历,因此此段代码没有意义!!!

对于n*n的方阵来说,直接行坐标与列坐标颠倒输出即为n*n的方阵倒置!!!

但此种方法对于不是n*n的方阵来说方阵倒置不管用!!!

应改为遍历上三角阵或者下三角阵(如书本代码所示,如上图)!!!

练习:
计算天数。定义函数day_of_year(year,month,day),计算并返回年year、月month和日day对应的是该年的第几天。
 

编程如下:

我写的:

#include <stdio.h>
int day_of_year(int year,int month,int day);
int main(void)
{
	int year,month,day;
	scanf("%d %d %d",&year,&month,&day);
	printf("%d",day_of_year(year,month,day));
	return 0;
}
int day_of_year(int year,int month,int day)
{
	int k,leap,sum = 0;
	//以下定义二维数组 
	int a[2][13] = {
	{0,31,28,31,30,31,30,31,31,30,31,30,31},
	{0,31,29,31,30,31,30,31,31,30,31,30,31}
	};
	//定义完毕
	//以下判断是否为闰年
	if(year % 4 == 0 && year % 100 != 0 || year % 400 == 0){
		leap = 1;
	}else{
		leap = 0;
	}
	//判断完毕
	if(leap == 1){
		k = month;
		for(k = 1;k < month;k++){
			sum = sum + a[leap][k];
		}
		sum = sum + day;
	}else{
		k = month;
		for(k = 1;k < month;k++){
			sum = sum + a[leap][k];
		}
		sum = sum + day;
	} 
	return sum;
}

简化后的:

#include <stdio.h>
int day_of_year(int year,int month,int day);
int main(void)
{
	int year,month,day;
	scanf("%d %d %d",&year,&month,&day);
	printf("%d",day_of_year(year,month,day));
	return 0;
}
int day_of_year(int year,int month,int day)
{
	int k,leap;
	//以下定义二维数组 
	int a[2][13] = {
	{0,31,28,31,30,31,30,31,31,30,31,30,31},
	{0,31,29,31,30,31,30,31,31,30,31,30,31}
	};
	//定义完毕
	//以下判断是否为闰年
	if(year % 4 == 0 && year % 100 != 0 || year % 400 == 0){
		leap = 1;
	}else{
		leap = 0;
	}
	//判断完毕
	//以下计算天数
	for(k = 1;k < month;k++){
		day = day + a[leap][k];
	} 
	return day;
}
wAAACH5BAEKAAAALAAAAAABAAEAAAICRAEAOw==

运行如下:

  • 7
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值