您的位置:首页 > 编程语言

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

2018-02-23 22:47 204 查看

(一) 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]();
 
PS:java的数组和这个还是不一样的,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));        
a77c
//填值[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));      //二分查找1int 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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: