当前位置:   article > 正文

C语言基础---5.数组相关详解:入门(一维数组 & 二维数组 & 应用案例)_二维数组的例子 c语言

二维数组的例子 c语言

1.数组基础

在程序设计中,为了方便处理数据把具有相同类型的若干变量按有序形式组织起来——称为数组。
数组就是在内存中连续的相同类型的变量空间。同一个数组所有的成员都是相同的数据类型,同时所有的成员在内存中的地址是连续的。

在这里插入图片描述

2.数组的定义及赋值

#include <stdio.h>

int main()
{
	int a[10];				//定义了一个数组,名字叫a,有10个成员,每个成员都是int类型
	a[0] = 0;				//a[0]…… a[9],没有a[10]
	//……				   //没有a这个变量,a是数组的名字,但不是变量名,它是常量
	a[9] = 9;

	int i = 0;
	for (i = 0; i < 10; i++)
	{
		a[i] = i; 				//给数组赋值
	}

	for (i = 0; i < 10; i++)   	//遍历数组,并输出每个成员的值
	{
		printf("%d ", a[i]);
	}
	printf("\n");

	return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23

3.一维数组的初始化

  • 在定义数组的同时进行赋值,称为初始化。
  • 全局数组若不初始化,编译器将其初始化为零。
  • 局部数组若不初始化,内容为随机值。

int a[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };//定义一个数组,同时初始化所有成员变量
int a[10] = { 1, 2, 3 };//初始化前三个成员,后面所有元素都设置为0
int a[10] = { 0 };//所有的成员都设置为0
int a[] = { 1, 2, 3, 4, 5 };//定义了一个数组,有5个成员 ,[]中不定义元素个数,定义时必须初始化

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

4.数组名:第一个元素的地址


#include <stdio.h>

int main()
{
	int a[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };			//定义一个数组,同时初始化所有成员变量

	printf("a = %p\n", a);
	printf("&a[0] = %p\n", &a[0]);

	int n = sizeof(a); 			//数组占用内存的大小,10个int类型,10 * 4  = 40
	int n0 = sizeof(a[0]);		//数组第0个元素占用内存大小,第0个元素为int,4

	int i = 0;
	for (i = 0; i < sizeof(a) / sizeof(a[0]); i++)
	{
		printf("%d ", a[i]);
	}
	printf("\n");

	return 0;
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23

a = 00EFFE98			// 可以看到,数组名即为第一个元素的地址
&a[0] = 00EFFE98
1 2 3 4 5 6 7 8 9 10

  • 1
  • 2
  • 3
  • 4
  • 5

5.二维数组的定义及使用

1.基础定义

类型说明符 数组名 [常量表达式1] [常量表达式2]

  • int a[3][4]-------定义了一个三行四列的数组,数组名为a, 其元素类型为整型,该数组的元素个数为3×4个

在这里插入图片描述

  • 内存中不存在真正的二维数组,二维数组只是个抽象的概念。实际是多个一维数组的拼接,即放完一行之后顺次放入第二行,和一维数组存放方式是一样的。
  • 通过每行的首元素(例如,a[0] 和 a[1])可以找到每行的元素,然后再找到这行中的具体每个元素。

在这里插入图片描述

1.二维数组a[3][4],可以看做是数组的数组,即:最外层的一维数组,元素是a[0],a[1],a[2]
2.内存的一维数组a[0],a[1],a[2],对应的元素为a[0][0],a[1][0],a[2][0]…
3.中间层,a[0],a[1],a[2],即是外层数组的元素,也是内存数组的数组名
4. **a最终才能取到元素的值,就是因为2层数组的缘故(二维数组名栏目里面,有详细介绍)


#include <stdio.h>

int main()
{
	//定义了一个二维数组,名字叫a
	//由3个一维数组组成,这个一维数组是int [4]
	//这3个一维数组的数组名分别为a[0],a[1],a[2]
	int a[3][4];

	a[0][0] = 0;
	//……
	a[2][3] = 11;

	//给数组每个元素赋值
	int i = 0;
	int j = 0;
	int num = 0;
	for (i = 0; i < 3; i++)
	{
		for (j = 0; j < 4; j++)
		{
			a[i][j] = num++;
		}
	}

	//遍历数组,并输出每个成员的值
	for (i = 0; i < 3; i++)
	{
		for (j = 0; j < 4; j++)
		{
			printf("%d, ", a[i][j]);
		}
		printf("\n");
	}

	return 0;
}


  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40

0, 1, 2, 3,
4, 5, 6, 7,
8, 9, 10, 11,

  • 1
  • 2
  • 3
  • 4
  • 5

2.二维数组的初始化

//分段赋值 	int a[3][4] = {{ 1, 2, 3, 4 },{ 5, 6, 7, 8, },{ 9, 10, 11, 12 }};
	int a[3][4] = 
	{ 
		{ 1, 2, 3, 4 },
		{ 5, 6, 7, 8, },
		{ 9, 10, 11, 12 }
	};

	//连续赋值
	int a[3][4] = { 1, 2, 3, 4 , 5, 6, 7, 8, 9, 10, 11, 12  };

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
	//可以只给部分元素赋初值,未初始化则为0
	int a[3][4] = { 1, 2, 3, 4  };

// 结果为:
//	1, 2, 3, 4,
//	0, 0, 0, 0,
//	0, 0, 0, 0,

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
	//所有的成员都设置为0
	int a[3][4] = {0};


// 结果为:
//	0, 0, 0, 0,
//	0, 0, 0, 0,
//	0, 0, 0, 0,
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

	//[]中不定义元素个数,定义时必须初始化
	int a[][4] = { 1, 2, 3, 4, 5, 6, 7, 8};



// 结果为:
//	1, 2, 3, 4,
//	5, 6, 7, 8,

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

3.二维数组名:

因为数组名是二维数组,2层嵌套,需要a才能取到最终的值:**


#include <stdio.h>

int main() {
	int a[3][4] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 };


	printf("a 的地址---%p\n", a);		 
	printf("*a的地址---%p\n", *a);
	printf("**a的值---%d\n", **a);

	return 0;
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

a 的地址---005DFCC4
*a的地址---005DFCC4
**a的值---1

  • 1
  • 2
  • 3
  • 4
  • 5

#include <stdio.h>

int main()
{
	//定义了一个二维数组,名字叫a
	//二维数组是本质上还是一维数组,此一维数组有3个元素
	//每个元素又是一个一维数组int[4]
	int a[3][4] = { 1, 2, 3, 4 , 5, 6, 7, 8, 9, 10, 11, 12 };

	
	printf("a = %p\n", a);    			//数组名为数组首元素地址,二维数组的第0个元素为一维数组
	printf("a[0] = %p\n", a[0]);		//第0个一维数组的数组名为a[0]


	//测二维数组所占内存空间,有3个一维数组,每个一维数组的空间为4*4
	//sizeof(a) = 3 * 4 * 4 = 48
	printf("sizeof(a) = %d\n", sizeof(a));

	
	printf("sizeof(a[0]) = %d\n", sizeof(a[0]));	//测第0行一维数组所占内存空间,a[0]为第0个一维数组,大小为4,即:4*4=16

	printf("sizeof(a[0][0]) = %d\n", sizeof(a[0][0]));		//测第一个元素字节大小,即:第0行0列元素a[0][0],是一个int类型,4字节

	printf("i = %d\n", sizeof(a) / sizeof(a[0]));			//求二维数组行数

	printf("j = %d\n", sizeof(a[0]) / sizeof(a[0][0]));		// 求二维数组列数

	printf("n = %d\n", sizeof(a) / sizeof(a[0][0]));		//求二维数组行*列总数

	return 0;
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33

a = 008FFE40
a[0] = 008FFE40
sizeof(a) = 48
sizeof(a[0]) = 16
sizeof(a[0][0]) = 4
i = 3
j = 4
n = 12

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
4.二维数组应用案例:
#include <stdio.h>

int main()
{
	//二维数组:  五行、三列
	//行代表人:  老大到老五
	//列代表科目:语、数、外
	float a[5][3] = { { 80, 75, 56 }, { 59, 65, 71 }, { 59, 63, 70 }, { 85, 45, 90 }, { 76, 77, 45 } };

	int i, j, person_low[3] = { 0 };
	float s = 0, lesson_aver[3] = { 0 };

	for (i = 0; i < 3; i++)
	{
		for (j = 0; j < 5; j++)
		{
			s = s + a[j][i];
			if (a[j][i] < 60)
			{
				person_low[i]++;
			}
		}

		lesson_aver[i] = s / 5;
		s = 0;
	}

	printf("各科的平均成绩:\n");
	for (i = 0; i < 3; i++)
	{
		printf("%.2f\n", lesson_aver[i]);
	}
		
	printf("各科不及格的人数:\n");
	for (i = 0; i < 3; i++)
	{
		printf("%d\n", person_low[i]);
	}
		
	return 0;
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
各科的平均成绩:
71.80
65.00
66.40
各科不及格的人数:
2
1
2

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9




6.常见错误用法:

1.未初始化的局部变量数组 & 未初始化的全局变量数组

#include <stdio.h>

int a[5];


int main() {

	int b[5];
	for (int i = 0; i < 5; i++) {
		printf("a数组的各个元素-----%d\n", a[i]);
	}
	for (int i = 0; i < 5; i++) {
		printf("b数组的各个元素-----%d\n", b[i]);
	}

}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

a数组的各个元素-----0
a数组的各个元素-----0
a数组的各个元素-----0
a数组的各个元素-----0
a数组的各个元素-----0
b数组的各个元素------858993460
b数组的各个元素------858993460
b数组的各个元素------858993460
b数组的各个元素------858993460
b数组的各个元素------858993460

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 未初始化的全局变量,系统默认给的值为0
  • 未初始化的局域变量,系统会随机分配值
2.二维数组初始化错误(使用小括号)
#include <stdio.h>

int main() {
	int a[3][2] = { (1, 2), (3, 4), (5, 6) };	// {2,4,6} 或 {2,4}{6,0},{0,0}
	int* p;
	p = a[0];
	printf("%d   %d\n", a[0][0],p[0]);			//p[0]代表的是第0行的首元素吗?
	printf("%d   %d\n", a[1][0],p[1]);			//p[1]代表的是第1行的首元素吗?
	printf("%d   %d\n", a[2][0],p[2]);
	printf("===============\n");

	printf("%d   \n", a[0][1]);
	printf("%d   \n", a[1][1]);
	printf("%d   \n", a[2][1]);
	return 0;
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

2   2
6   4		// 这里为什么不一样??
0   6
===============
4
0
0

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

二维数组是一个抽象的概念,存储的值转换为抽象的概念如下:

二维数组初始化的时候,int a[3][2] = { (1, 2), (3, 4), (5, 6) },这个相当于是 int a[3][2] = {2, 4, 6}


int a[3][2] = {2, 4, 6}						// 原始二维数组
int a[3][2] ={ {2, 4}{6,0}, {0,0} }		// 转换之后的二维数组

  • 1
  • 2
  • 3
  • 4

a[0][0]    = 2
a[1][0]	   = 6
a[2][0]    = 0

a[0][1]    = 4
a[1][1]	   = 0
a[2][1]    = 0

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

指针和地址,对应实际内存的地址,某个地址存储什么值,直接就读取什么值:

根据如上代码,我大致推测的存储方式:
在这里插入图片描述

  • int a[3][2] = {2, 4, 6}二维数组,内存存储的时候,可以把真个二维数组看成是一个一维数组
  • 上图中,每个数值占用4个字节,所以可以把2,4、6,看作是一个正常的连续存储的一维数组
  • 因为指针p指向了首地址,所以可以把p看做是数组名去获取值,或通过指针偏移获取值,如:*(p+i)


为了证明我们的推测,再次准备代码:

#include <stdio.h>

int main() {
	int a[3][2] = { 2, 4, 6, 8, 9 };
	int* p;
	p = a[0];
	printf("%d   %d   \n", p[0], *(p + 0));
	printf("%d   %d   \n", p[1], *(p + 1));
	printf("%d   %d   \n", p[2], *(p + 2));
	printf("%d   %d   \n", p[3], *(p + 3));
	printf("%d   %d   \n", p[4], *(p + 4));
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
2   2
4   4
6   6
8   8
9   9

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

最终发现,通过偏移量或者p[i]这两种形式,都可以正常获取值了。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/笔触狂放9/article/detail/492781
推荐阅读
相关标签
  

闽ICP备14008679号