1.cpp中的数组和java中不大一样,首先cpp中的数组不是对象,无法调用length方法,只能通过计算来得到数组的长度.
一维数组;
而且要么在定义的时候确定数组的长度.
要么在后面初始化的时候确定数组长度;
反正是不能和java一样写个空数组放在那里,,,,,,,,,
一维数组定义的时候,如果没有确定元素,就一定要确定长度
如果确定了元素(初始化完成)但是没有给出长度,那么cpp就可以自己猜出长度来
int arrrr[] = { 12345 };
很顺滑地知道长度是1了
数组在定义的时候,使用类型+数组名+[]={}进行定义;
其中有一个处理方法
//typedef定义类型 前面也那这个定义过指针
//这里也可以修改成
typedef int A[10];//此时A就不再是一个变量,而是"长度为十的数组"的别名
关于多维数组(以二维数组为例)
二维数组在内存中的排列,其实还是线性的,这一点可以由指针进行验证
//多维数组仍然是线性排列的内存空间,而不是我们想象中的矩阵
//00 01 02 03 04 10 11 12 13 14
//用指针可以试一下,而Java中实现的是矩阵(数组的数组)
int vec[2][2] = { 1,2,3,4 };
int * point2 = &vec[0][0];//(对于二维数组,不能用数组名字代替第一个元素的地址了)
for (int i = 1; i <= 4; i++) {
cout << *point2 << endl;
point2++;
}
输出结果为1234,证明仍然是线性排列的
但是作为矩阵进行储存和调用的时候还是不受影响的,可以随便使用...
关于二维数组的定义和初始化问题
对于二维数组,注意一下高低维度
低纬度必须定义长度数值
合理的情况是可以猜测的
不足可以自动填充(考试时候的数组有可能缺得像狗啃的
下面代码是为了方便,其实是跑不起来的
例如这样可以自动填充上去
int[4][2]={{1,2}{3.4}{5}}
实际上的填充效果是{ {1,2}, {3,4}, {5.0}, {0,0} }
最高维度在这种情况下可以不写
int[][2]={1,2,3,4}
会自己分成{ {1,2} , {3,4} }
但是剩下的维数是必须写的,如下图所示就会报错
(错误代码)int[4][]={1243};
考试时候注意一个特殊情况
// 特殊情况----------关于cpp自动识别------------------------------------------------------------
// 顺序读取的
//[2][2]={1,2,{3,4}}前面读完1,2可以当成第一行
// 下面三四自动识别为第二行
//[2][2]={1,{3,4}}是不行的读取完一个他不知道接下来3是第几行的
2.关于数组地址和指针的问题
(1)数组的名字(无论是及维度数组都是一样的)都代表第一个元素的位置
cout << vec << endl;
cout << &vec[0][0] << endl;
// 由这个验证可知,无论是第及维度的数组,数组名字都是第一个元素的位置
// 只不过int指针无法匹配int[][];
数组的第一位元素均可与对应类型的指针匹配,但是数组名字不一定
对于一维数组
int arr[] = { 1 };
int * point1 = arr;//可以用数组名字代替第一个地址
对于二维数组或者高维数组
int vec[2][2] = { 1,2,3,4 };
int * point2 = &vec[0][0];//不能用数组名字代替第一个元素的地址
按照老师的回复,int[][] 和 int *不匹配----------------------------------------
只有int[] 和int*才是匹配的,所以一维数组可以直接用
盖棺定论:数组名字一定是第一个元素的地址,错的只是指针可能不匹配
挺烦的,所以以后数组在传参之类的操作时做一个规范
要么直接指明第一个元素建立指针,而不是只想数组名字
要么直接用数组名字开搞(传参什么的),不管指针了
3.关于数组作为参数.
关于数组作为形参,和结构体形参不太一样好像,结构体形参分为值传递和地址传递
// 数组不存在值传递这个问题,一般直接传入名字即可
//而传递数组名就是在传递数组头位置的地址,
// 也可以用指针传入第一个数字的地址,也可以不用指针直接传入名称
// 多维数组也可以直接传入名称
//数组地址传递作为参数有两种方式
//int * arr
//int arr[]
(不过大家需要的都是地址)
关于传入的时候,也有两种方式(而且数组只存在值传递)
可以利用&传入第一个元素的地址/指针
也可以传入数组名字
补充:在传递时刻可能会有的问题
(1)数组处在形参列表的时候,可以省略掉最高维的长度,但是剩下的低纬度都的不行
(例如)
void sort(int x[][][2])//不行
void sort(int x[2][][])//不行
void sort(int x[][2][2])//行
(2)在传参时可能遇到的几个问题
void bub1(int arr[][10]) {}
void bub2(int arr[][12]) {}
void bub3(int arr[2][10]) {}
void bub(int arr[5][]) ;这个本身的语法就是错误的,没有低纬度;
int m1[5][10];
bub1(m1);第一个方法没问题,低纬度的数目是确定的,高纬度没有指定
bub2(m1);低纬度不一样,他不认为这是同类型的数组
bub3(m1);传入没有问题,但是高纬度会发生风险
做个总结;
传入的时候,参数和列表中的
1,低维必须对应,否则根本不认为是同一种数组
2.高维尽量对应,因为可能会有风险存在
一点小总结
/1,数组并不是对象,数组名就是第一个的地址,所以不能用length
//2.越界几乎没啥影响
//3.没有赋值的元素可能为0或者null
//4.指定长度超出的时候,int{2}={1 2 3 4 4}挑衅行为不建议
//5.关于一维数组定义的时候,如果没有确定元素,就一定要确定长度
3.关于字符数组和字符串的区别和字符数组的一些方法.
在java里面,无论是string还是stringbuffer,底层都是字符类型的数组,但在这里貌似不大一样
(1)字符数组的长度和字符串的长度是不一致的(哪怕内容一致)
string ar="123";占据空间为四个
char ar[]={1,2,3};占据空间为三个
字符串最末尾其实还有一个\0的字符,这个字符不计入长度,但是会扎据内存,代表字符串的结束.
两者可以相互转化但是
char ar[4] = "1234";这个是有问题的,这个字符串的内存其实是五个字节
char ar[4] = "123"这个才是正确的
// 里面有一个\0,作为字符串截止的符号
//而开辟的仅仅是四个字节的空间而已
char ar[4] = { 1,2,3,4 };//而这样子写数组,长度为四
//多出来的那个\0是作为数组结尾,不计入数组长度,但是占用数组空间
//字符数组里面没有这个东西
(2)字符数组的一些方法
[1]strcat方法,拼接方法(拼接的时候保证前面的数组有充足的长度容纳)
char arr1[20] = { "thisaass" };
char arr2[5] = { "FUCK" };
//strcat_s(arr1,arr2);//组合方案
[2]我感觉比较重要,关于strcpy方法
char arr1[20] = { "thisaass" };
char arr2[5] = { "FUCK" };
strcpy( arr1 , arr2 );
输出结果是fuck对吧?
这是替换对吧?
唉
不对!哈皮!
这个底层原理如下
//并不是直接替换,准确而说,这两个里面输入的不是字符串,而是输入十六进制的地址
//例如strcpy(a, b)从第一个数组的a地址(一般就是首位),后面全部替换成b地址的东西
//如果贴上去的是数组(一般都是数组)
//那么就是从这个地址往后的全部贴上
//举个例子 strcpy(arr1, arr2) ; 输出结果就是FUCK
//再举个例子 strcpy(arr1+1, arr2+1)
//arr1把第二个地址替换成arr2的第二个地址
// (t)hisissass___F(UCK) 输出结果就是 tUCK
另外上述两个方法前面要加上宏文件,不然没法太好地使用
#define _CRT_SECURE_NO_WARNINGS
//还有下面这两个包导入一个
#include <cstring>
#include <string.h>