C++学习day--14 二维数组

从今天开始,进入C++高级部分了。

1、二维数组

  什么是数组?数组,就是多个同类型的元素的有序“组合”。所谓二维数组就是指含有多个数组的数组

如果把一维数组理解为一行数据,那么,二维数组可形象地表示为行列结构。
二维数组的定义:和数组一样,需要先定义,再使用。

inta[25];//一行女兵

实例:

inta[5][25];//五行女兵

//定义了一个二维数组,

//数组名是“a”,
//包含5行25列,共125元素,

//每个元素是int类型的变量

2、二维数组的初始化 

inta[3][4];//二维数组元素的值可能是随机的(如果变量没有初始化全局变量会默认为0,局部变量值随机
方式一初始化时指定每行的值
inta[3][4]={//等效于inta[][4]
{1,2,3,4},

{5,6,7,8},

{9,10,11,12}
};
注:最外围括号内部的每个括号相当于初始化一行,括号中可以省略某些元素的初始化

 方式二初始化时从头开始,依次序进行
inta[3][4]={1,2,3,4,5,6,7,8,9,10,11,12};

inta[3][4]={0};//所有元素都初始化为0
注:后面的多个元素可以不指定,不指定全部初始化为0,例如int a[3][4]={1},a[0][0]为1,其余元素默认为0。

#include<stdlib.h>
#include<stdio.h>
intmain(void){
    //int ages[5][25];//定义一个二维数组
    int i=0,j=0;
   //初始化

   //第一种方式初始化时指定每行的值
   int a[3][4]={

                {1},//省略掉得列会默认置零
                {5,6,7},
                {9,10,11,12}
               };
    //第二种方式初始化时从头开始,依次序进行
int a1[3][4]={1,2,3,4,5,6,7,8,9,10,11,12};

int a2[3][4]={1};//只初始化第一个,其他得默认置零
for(i=0;i<3;i++){
    for(j=0;j<4;j++){
    printf("%d",a[i][j]);
    }
   printf("\n");
}
  system("pause");
   return0;
}

3、二维数组的访问 

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

如下图表示,左侧表示的是一个大小为M+1的一维数组,右侧表示的是一个大小为(M+1)*(N+1)的二维数组。

 

int i=0,j=0;

int a[3][4];
//给数组成员赋值
for(int i=0;i < 12; i++){

a[i/4][i%4] = i+1;
}
//或
 for(int i=0; i < 3; i++){
 for(int j=0; j < 4;j++){

   a[i][j]=4*i+j+1;
  }

//输出
for(int i=0; i < 3; i++){
for(int j=0; j < 4; j++){
  printf("%d",a[i][j]);
}
   printf("\n");
}

4、二维数组的存储方式

 一维数组是按顺序存储的,二维数组呢?同样也是!

 设置断点调试,可以看到二位数组中的所有元素在内存中的存储方式。如下图所示:

 左边表示地址,右边表示改地址对应的存储数据,一般我们的变量都是4字节、2字节、1字节,查看的时候根据变量的字节大小调整,由于这里是int类型,因此设置为按4列显示。

5、多维数组
  上面讨论的二维数组的相关内容都适用于三维数组或更多维的数组。声明一个三维数组:

  int girl[3][8][5];

可以把一维数组想象成一排女兵,把二维数组想象成一个女兵方阵,把三维数组想象成多个女兵方阵。这样,当你要找其中的一个女兵时,你只要知道她在哪个方阵(从0、1、2中选择),在哪一行(从0-7)中选择,在哪一列(从0-4中选择)。

5 节 二维数组作为函数的参数 

切记! 数组作为函数的参数传递,不是单纯的值传递,传递的是数组本身。是址传递。
二维数组作为函数的参数 :
#include <stdio.h>
#include <stdlib.h>
//版本 1 指明参数
void print1(int a[3][4]) {
	for (int i = 0; i < 3; i++) {
		for (int j = 0; j < 4; j++) {
			printf("%d ", a[i][j]);
		}
		printf("\n");
	}
}
//版本 1 省略一个高维参数
void print2(int a[][4], int lines) {
	for (int i = 0; i < lines; i++) {
		for (int j = 0; j < 4; j++) {
			printf("%d ", a[i][j]);
		}
		printf("\n");
	}
}
int main(void) {
	//int arr[3][4]={{},{3,4}};
	int a[3][4] = { 0 };
	int i = 0;
	int j = 0;
	//给数组成员赋值
	for (int i = 0; i < 3; i++) {
		for (int j = 0; j < 4; j++) {
			a[i][j] = 4 * i + j;
		}
	}
	print1(a);
	print2(a,3);
}

二维数组作为参数,形参要么写上行数和列数,要么只写列数,但是行数要作为形参传递进去,一般建议在写形参的时候既写上行数又写上列数

6 节 项目精讲-常见错误总结

数组定义时编译器不能确定数组的大小
int a[3][] ;
int a[][4] ;
int a[3][]={{1 2} {3 4} {5 6}}
一条原则 :仅定义时(无初始化)不能省略,有初始化可以省略高维
严禁数组越界
在使用数组时,要防止数组下标超出边界。也就是说,必须确保下标是有效的值。
int a[10] ;
a[10]=100; // 错误,访问越界, a[10] 的成员是 a[0] - a[9]
int a[3][4];
a[3][0]=666; // 错误 , a[3][4] 包含了 3 4 列的数组,行下标也是从 0 开始,
有效范围 0 - 2
数组(无论几维)传参并不是整个数组的复制:
#include <stdio.h>
#include <stdlib.h>
//int arr[3][4];
void fun(int a[3][4]) {
	for (int i = 0; i < 3; i++) {
		for (int j = 0; j < 4; j++) {
			a[i][j] = 0;
		}
	}
}
int main(void) {
	//int arr[3][4]={{},{3,4}};
	int a[3][4] = { 0 };
	int i = 0;
	int j = 0;
	//给数组成员赋值
	for (int i = 0; i < 3; i++) {
		for (int j = 0; j < 4; j++) {
			a[i][j] = 4 * i + j;
		}
	}
	fun(a);
	//输出
	for (int i = 0; i < 3; i++) {
		for (int j = 0; j < 4; j++) {
			printf("%d ", a[i][j]);
		}
		printf("\n");
	}
}

运行结果:

说明数组传递是地址传递而不是只传递!! 

完成项目:人工智能之地形导航系统

介绍:2018 年 11 26 日,“洞察”号火星探测器在火星上成功着陆,执行人类首次探究火星“内

心深处”的任务。火星上地形比较复杂,高低起伏,有山峰和低谷,稍有不慎,就会引起“翻
车”。因此我们必须要识别地形上的各个最高点(峰点)和最低点(谷点),以便为探测器
提供导航数据。峰点就是一个其周围所有点的海拔都低于它的点。
现在我们要做的就是分析来自地图上的海拔数据,以确定地形中峰点的数目和位置。

 项目实现思路:

假设下面的数据代表一个 6 x 7 的网格 , 加了下划线的网格即为峰点。
5039   5127   5238   5259   5248   5310   5299
5150   5392   5410   5401   5320   5820   5321
5290    5560    5490   5421   5530    5831    5210
5110   5429   5430   5411   5459   5630    5319
4920   5129   4921    5821    4722   4921   5129
5023   5129   4822   4872   4794   4862   4245
为了描述峰点的位置,我们需要使用一个位置方案:使用二维数组描述 假定左上角是[0][0], 那么向下移动,则行号加 1 ;向右移动,则列号加 1, 那么这些峰点的位置就可以描述为:[2][1] [2][5] [4][3] 。 位置确定后,与周围 4 个邻节点比较即可确定峰点!( 注: 网格边界点缺乏 4
个相邻点不计算峰点) 地形数据保存map.txt于文件中。

 

算法设计
1) 将地形数据从文件读入二维数组 ;
2) 逐行遍历二维数组的每个元素,确定是否峰值并打印结果。
代码实现如下:
#include<iostream>
#include<fstream>
#include<string>

using namespace std;

#define MAX_MAP 64

//判断某点是不是峰点
bool isPeakPoint(int map[MAX_MAP][MAX_MAP], int r, int line);

int main() {
	int map[MAX_MAP][MAX_MAP] = { 0 };
	int row, col;
	string fileName;
	ifstream file;

	cout << "输入文件名:" << endl;
	cin >> fileName;
	file.open(fileName.c_str());
	if (file.fail()) {
		//cerr输出到标准错误的ostream对象,通常用来输出警告和错误信息给程序的使用者
		cerr << "打开文件出错!" << endl;
		exit(1);//当程序非正常终止时,exit()里面写数字1,正常终止时数字0
	}
	file >> row >> col;
	if (row<0 || row>MAX_MAP || col<0 || col>MAX_MAP) {
		cerr << "网格太大,应调整网格大小!" << endl;
	}

	//从文件读取数据到数组里
	for (int i = 0; i < row; i++) {
		for (int j = 0; j < col; j++) {
			file >> map[i][j];
		}
	}

	//找出峰点并打印其所在位置
	for (int i = 1; i < row - 1; i++) {
		for (int j = 1; j < col - 1; j++) {
			if (isPeakPoint(map, i, j)) {
				cout << "峰点行号:" << i << "  列号:" << j << endl;
			}
		}
	}
	file.close();
	return 0;
}

bool isPeakPoint(int map[MAX_MAP][MAX_MAP], int r, int line)
{
	if (r<0 || r>MAX_MAP || line<0 || line>MAX_MAP) {
		cerr << "坐标不合理!" << endl;
		exit(1);
	}
	else {
		if ((map[r][line] > map[r - 1][line]) &&
			(map[r][line] > map[r + 1][line]) &&
			(map[r][line] > map[r][line - 1]) &&
			(map[r][line] > map[r][line + 1]))
			return true;
	}
	return false;
}

运行结果:

本项目的思想就是如此,并不是说是那种大项目,因为现在学的知识点不足以开发正式的项目,我们只需把一些项目的思想简化通过编程实现即可。

难点:对文件的输入输出可能有疑问,可以自己补充一下文件输入输出的知识点:

如下:

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值