编程语言学习(五) 三种编程语言的数组

7 篇文章 0 订阅
6 篇文章 0 订阅

(一) C/C++语言当中的数组: 

1. 定义: <类型>变量名[元素数量]

定义的同时,分配栈空间,得到内存。

C99之后,元素数量可以是变量了,之前要求的是编译时就要确定值的常量  //我对于变长数组VLA仍然不清楚,DEVc++在调成C99情况下仍然出问题。

 

2. 取值  变量名[下标],所取的一个元素可以作为左值使用,左值在指针那一节会讨论,等待修改补充,下标越界编译器不会检查,但是运行时会发生数组下标越界

 

3. 初始化:

(1) 默认初始化:静态生存期的数组自动初始化为0,动态生存期的数组垃圾值

(2) 全部初始化:直接大括号给出所有值,可以不写元素数量

(3) 部分初始化:给出部分值并且给出数组大小,未赋值的元素自动为0

(4) 定位初始化:在大括号中,以方括号小标等于一个值的形式赋值:

 

int a[]={[2]=8,[6]=6};   //最后一个是a[6],可见有7个元素,不用标个数

printf("%d\n",a[6]);

printf("%d\n",sizeof(a)/sizeof(a[0]));   //显示 6  7 以此获得数组大小

(4)强制初始化:数组若加上const修饰,代表其中每个元素都是常量,所以数组定义时就要初始化:

const int a[]={1,2,3,4,5,6};

 

4. 复制:由于数组名本身是指针常量,所以不能对其赋值,应该遍历逐个赋值,也正是因为数组名本身是指针,所以数组当做参数传入时,sizeof(a)/sizeof(a[0])不可用,应当额外传入数组长度。

 

5. 二维数组: 行列排列与矩阵相同,内存上也是连续存放,排列顺序与n进制递增是一致的:003-010

(1) 定义   <类型>变量名[行下标][列下标]

(2) 遍历:两层循环,对行列分别遍历

(3) 初始化:可以指明行列数后直接按一维对的方式写,比如:

int a[][3]={1,2,3,4,5,6};

printf("%d",a[1][2]);

也可以如下方法:

int a[3][5]={

{1,2,3,4,5},   //逗号不能忘记了

{6,7,8,9,10},

{11,12,13,14,15}

};

printf("%d",a[2][4]);


6. 数组作参数:

C/C++当中数组名本质不仅仅是地址,也标明数组的属性,但是数组名在表达式当中进行运算时,编译器会将其转化成一个指针常量,但在两种情况下,这种包含数量信息、作为数组整体的属性会被保留:

(1)sizeof(数组名):返回数组长度(所占的字节数,不是数组元素个数),而不是指向数组的指针的长度。

 

(2)&数组名:产生一个指向数组的指针,而不是一个指向某个指针常量的指针。

C/C++当中除了取地址和sizeof运算符的情况下,会有整体的数组概念,但是做参数传递时,实际传递的只是一个内存单元的地址,导致了在传递至函数里面时,sizeof运算符失效了,所以C/C++需要额外传递数组的长度进入函数。

 

数组作参数分为两个情况讨论:

(1) 形参中的数组,我们可以对行列数进行规定,也可以不规定

(2) 实参当中的数组:实际上传的是地址,函数操作可能修改各个元素

例如:

 void inc(int a[][3],int nRow){  //对数组的列数给出了要求 行数需额外传入

  for(int i=0;i<nRow;i++){

  for(int j=0;j<3;j++){

  a[i][j]++;

 }

 }

 }

int main() {

int a[][3]={1,2,3,4,5,6};

inc(a,2);

  for(int i=0;i<2;i++){

  for(int j=0;j<3;j++){

  printf("%d ",a[i][j]); //输出2 3 4 5 6 7,可见已经改变原先元素

 }

 }

return 0;

}


7. 对象数组(C++独有)

对象数组的定义和普通数组相同,初始化的实质是调用构造函数对每个元素都进行构造的过程,例如:

Location a[2]={Location(1,2),};   //另一对象元素是通过调用默认构造函数构造的

对象数组消亡时,也是对所有元素逐一调用析构函数完成的。

 

8. 利用动态内存分配创建数组

java一致,需要先申请内存,但C/C++用指针变量去接收,java用引用去接收。

int a[]=new int [5]();// 这样是不可以的,因为实际上只返回了首地址

比如: 

int *a = new int[5]();    //带上小括号,全部初始化为0,与java相同。

cout << sizeof(a) / sizeof(a[1]) << endl; //输出1,可见sizeof(a)实质是sizeof(a[0])

delete[] a;

 

若希望创建多维数组,则实际上是返回T类型数组的指针  //此处强调数组

实际上返回是 int[4](*a),也就是指向具有4个元素的数组的指针

int (*a)[4]=new int[5][4]();

int (*a)[4][8]=new int [7][4][8]();

 

PSjava的数组和这个还是不一样的,java当中其实是一个数组当中装了n个指针,应该是   int**a=new int*[10](); 指针指向指针,C/C++是指针指向数组。

 

(二) Java语言当中的数组

Java当中的数组与C/C++的数组完全不同,java当中的数组完全建立在堆内存上,声明得到的数组变量实际是一个引用类型。

1. 声明一个数组:

类型[]数组名,或者 类型 数组名[],后者为C/C++风格,java程序里前者居多。

本质是声明一个数组的引用,不占用内存。

 

这里浅谈java当中的变量名,C/C++当中,所有变量/函数名都是地址,而JAVA当中除了基本数据类型外,其他的类型的名字本质都是引用,但是又区别于C++java的引用实际上是可以先声明不立即赋值的。

 

 

2. 取值

取值方法与C/C++相同,但是C/C++对于数组下标越界是不会检查的,内存读写会跨过数组边界,java在编译时也是不能找出数组下标越界的,但是在运行的时候会报异常。

 

3.  初始化一个数组:

由于java的数组都要在堆中申请内存,所以初始化较C/C++多了一步申请内存,所以有两步:

第一步:申请内存

new 类型名 [数组大小]

第二步:赋初值

(1) 默认初始化:Java当中帮助完善了对于一个数组的初始化,数组对象建立起来的时候就已经全部元素分配为0了,字符串数组会自动赋值null

(2) 自己动手赋值

 

也可以两步合成一步,有两种方法:

(1) int []a={1,2,3,4,5,6}

(2) Int []a=new int[]{1,2,3,4}   //构造时给出数量反而报错

 

4. 复制:java当中的数组名,本质是引用,带有C++的指针的性质,所以数组变量可以互相赋值,但是两个引用指向同一个数组对象,两个管理员管一个对象,会出类似于C++当中类似浅复制的问题。

 

 

5. 二维数组

区别与C/C++C++当中,数组名可以充当地址来使用,通过数组名和下标确定具体哪个元素,由于java数组名实际是一种对象的引用,因此这种管理关系是可以改变的;java当中实际上没有多维数组,二维数组的本质是数组的数组,数组元素在内存当中的排列并不连续,这个概念较C++数组为宽泛,对应有了不规则数组:

(1) 实现二维数组行之间的交换

(2) 实现不规则数组

 

 

public class hello {

 

public static void main(String[] args) {

int a[][]= {

{1,2,3,4},

{5,6,7},      //a[0]引用{1,2,3,4,} a[1]引用{5,6,7}

};

int b[]=a[1];

a[1]=a[0];

a[0]=b;

System.out.println(a[1].length);  //输出4 可见所引用的元素已经变化

}

}

 

6. 数组作参数:

Java当中,数组不是基本数据类型,而是引用类型(类类型),因此数组类当可以有自己的特有的数据成员,java当中数组类具有length成员,可以用数组名.length得到,因此不再需要额外传入数组的长度。

 

7. Java提供了数组的几个API,看着眼熟即可:

int []a=new int[4];

Arrays.fill(a, 55);

System.out.println("填值"+Arrays.toString(a));        //填值[55, 55, 55, 55]

for (int i = 0; i < a.length; i++) {   

a[i]=88-i;

}

System.out.println("赋值 "+Arrays.toString(a));      //赋值 [88, 87, 86, 85]

Arrays.sort(a);

System.out.println("升序排序 "+Arrays.toString(a));//升序排序 [85, 86, 87, 88]

/* java当中并没有降序排序的API*/

System.out.println("二分查找"+Arrays.binarySearch(a, 86));      //二分查找1

int b[]=Arrays.copyOf(a, 2);

System.out.println("按长度截取"+Arrays.toString(b));     //按长度截取[85, 86]

int []c=Arrays.copyOfRange(a, 1, 3);

System.out.println("按范围截取"+Arrays.toString(c));     //按范围截取[86, 87]

System.out.println( "比较"+Arrays.equals(a, b));          //比较false

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值