C++深入体验之旅六:数组

原创 2013年12月02日 10:29:30

1.数组的声明和初始化

我们知道,在程序设计中,大多数数据都是存放在变量里的。如果我们要处理较多的数据,增加存放数据的空间最简单的方法就是多开设一些变量。然而,变量多了就难以管理了。这就好像一个班级里的学生名字有长有短,即使没有重复的名字,要在一长串名单里找到一个同学的名字也不是件容易的事情。于是,最方便的方法就是给同学们编上学号了,把名单按学号排列好以后,查找起来只要找学号就可以了。因为数字的排列是从小到大的,是有序的,所以查找起来要比在一堆长短不一的名字中查找要方便多了。
我们受到“学号”的启发,可以给变量也编一个号,把存储着相关内容的变量编在一组内,这就称为数组(Array)。

数组的声明

数组的本质也是变量,所以我们在使用数组之前,必须要声明数组。声明一个数组的语法格式为:
数据类型数组名[常量表达式];
和声明变量类似,数据类型仍然是整型、字符型等等,数组的命名规则和变量的命名规则也一样。在这里,我们要说明两个问题:以前我们说过在语法规则中的中括号表示可有可无的东西,然而在数组名后的中括号有着其独特的含义,而不是可有可无的。数组名后的中括号是数组的一个特征,没有这个特征就不是数组了。数组中每个存放数据的变量称为数组元素。中括号内的常量表达式称为数组的大小,即元素的个数。例如int a[5];这句语句就是声明了一个可以存放五个整型数据的数组,它所能存储的数据相当于五个整型变量。
电脑必须在程序执行之前就已经知道数组的大小,因此中括号内只能是一个常量表达式,而不能含有变量。
通过实验,我们知道我们无法根据程序运行的实际情况来声明一个数组的大小。所以,为了保证程序有足够的存储空间和正常运行,我们尽量要声明一个足够大的数组。要注意,足够大不是无穷大。比如我们要存放一个班级学生的成绩,我们声明一个大小为70的数组是足够大,但是声明一个大小为1000的数组却是不必要的浪费。

数组的初始化

我们知道,变量在声明的同时可以进行初始化。同样地,数组在声明的时候进行初始化,声明并初始化数组的语法格式为:
数据类型数组名[常量表达式]={初始化值1,初始化值2,……初始化值n};
在初始化数组时,大括号中的值的个数不能大于声明数组的大小,也不能通过添加逗号的方式跳过。但是初始化值的个数可以小于声明数组的大小,此时仅对前面一些有初始化值的元素依次进行初始化。比如:

int array1[3]={0,1,2}; //正确 
int array2[3]={0,1,2,3}; //错误,初始化值个数大于数组大小 
int array3[3]={0,,2}; //错误,初始化值被跳过 
int array4[3]={0,1,}; //错误,初始化值被跳过(即使是最后一个元素,添加逗号也被认为是跳过) 
int array5[3]={0,1}; //正确,省略初始化最后一个元素

2.数组操作和数组下标

我们前面说到,数组就像是给变量编了号。那么我们要访问数组中的某一个元素时自然就要用到这个编号了。给学生编的号称为学号,给数组元素编的号称为下标(Subscript)。我们要表达数组中某一个元素的格式是:数组名[下标]。在C++中,下标是从0开始的,所以一个大小为n的数组,它的有效下标是0~n-1。如果下标不在这个范围内,就会发生错误。和声明数组时不同,操作一个数组时,它的下标既可以是一个常量表达式,也可以是一个变量表达式。
对数组元素的操作就如同对某一相同数据类型的变量的操作。下面我们来看一个简单的例子:(程序7.1)

#include "iostream.h" 
int main() 
{ 
   int array[5];//声明一个可以存放五个整数的数组 
   for (int i=0;i<5;i++)//如果写成i<=5就要出问题了 
   { 
      array[i]=i+1;//对各数组元素赋值 
   } 
   for (int j=0;j<5;j++) 
   { 
      cout <<array[j] <<" ";//输出各数组元素 
   } 
   cout <<endl; 
   return 0; 
} 
运行结果:
1 2 3 4 5 
阅读了以上程序,我们发现除了要注意下标是否有效,对数组的操作和对变量的操作并无异样。


算法时间:数组的下标和循环控制变量
在一开始,我们就说了给学生编号是为了避免在长短不一的姓名中查找。使用一个数组而不使用多个变量的原因也是类似的。由于循环语句和数组下标的存在,再搭配循环控制变量,就能很方便地对多个数据进行类似的反复操作。(我们一般把循环控制变量作为数组的下标。如程序7.1.1中所示。)这种优势是多个变量所没有的。这也是数组存在的重要意义。如果一种高级语言没有数组功能,那么它将很难实现大数据量的复杂程序。

试试看:
输入下列程序,看看在编译的时候会发生什么错误:

#include "iostream.h" 
int main() 
{ 
int size; 
int a[size]; 
cin >>size; 
return 0; }

3.省略数组大小的写法

我们已经知道了如何定义和初始化一个数组。然而有时候我们既要赋初值又要数元素个数,有些麻烦。既然我们对各元素赋了初值,电脑能否自己算出有多少个元素呢?
答案是肯定地的。只要我们对各元素赋了初值,电脑会自动计算出声明的数组应该有多大。比如:
    int array[]={0,3,4,8};
这句语句就相当于:
    int array[4]={0,3,4,8};
这样的写法便于我们对数组元素的插入或修改,我们只需要直接在花括号中对数据进行修改就可以了,而不必去考虑中括号中的数组大小应该怎么变化。但是,这种情况下,我们又怎么才能知道数组的大小呢?我们将在下一节讲述这个问题。

试试看:
1、声明一个大小为6的数组,试试看能否输出下标为6的元素的数据?能否修改下标为6的元素的数据?
结论:可以输出下标超出有效范围的元素(我们称为越界访问),但是修改下标超出有效范围的元素将可能导致未知的错误。
2、改写程序7.1,通过键盘输入给数组的五个元素赋值,再输出这五个元素。

4.数组的存储

我们以前说变量像箱子,数组像仓库。在这一节,我们要来深入探究一下,这些“箱子”和“仓库”在电脑内部是怎样摆放的。

内存和地址

我们知道变量和数组都是放在内存里的,我们有时候还能够听到内存地址(Address)这个词。那么地址究竟是什么意思呢?
其实在内存里,就像是许许多多的街道,每条街道有它的名字,而街道上的每幢房子又按顺序地编了号,于是街道名和房子在街道上的编号就能确定内存中唯一的一幢房子,我们在这里认为所有的数据在内存中都是放在房子里。电脑就是依照这个原理找到所要的访问或修改的数据的。街道名和房子在街道上的编号就称为这个房子的地址。我们通常把地址表示为一串十六进制的数。关于十六进制数我们在这里不作展开说明。
那么这些内存中的房子和我们所说的变量和数组是什么关系呢?在内存里的房子的大小是规定的,每幢房子只能存储一个字节(Byte)的数据。(一个字节相当于一个半角的英文字母,一个汉字需要占用两个字节。)有时候,一种类型的变量需要比较大的空间,比如一个浮点型的实数,一幢房子是放不下的,而是需要4幢房子的空间才能放得下。于是电脑就把连起来的4幢房子拼起来,每幢房子放这个实数的一部分数据。而这连起来的4幢房子,构成了一个能够存放浮点型实数的变量。
我们认为,内存中的“房子”是客观存在的,每幢房子的大小一样,没有任何区别;而不同类型的变量“箱子”则是由若干幢房子拼接而成,箱子在内存中是不存在的,只是我们为了方便理解而臆想出来的。右图就是一个浮点型变量在内存中的情况。(图7.2.1)

数组在内存中的存储情况

变量在内存中是由若干个相邻的“房子”拼接而成的,而数组在内存中则是由若干个相邻的数组元素按顺序拼接而成的。每个数组元素又相当于一个变量。左图是一个大小为3的短整型(short)数组在内存中的情况。(图7.2.2)
我们在上一节的最后说到可以省略数组的大小,但是这样一来我们就无法得知数组的大小了,这将可能造成越界访问。当我们了解了数组在内存中的存储情况后,我们就能够知道数组的大小了。在C++中,有一个名为sizeof的操作符,可以求出一个数组或一种数据类型在内存中占了多少“房子”,它的使用方法是:
    sizeof(数组名或数据类型);
通过左图我们可以理解,要求出数组的大小,应该是用整个数组占的“房子”数除以每一个数组元素占的“房子”数,即6除以2等于3。下面我们就来看一个求出数组大小的程序实例:(程序7.2.1)

#include "iostream.h" 
int main() 
{ 
int array[]={3,5,6,8,7,9}; 
int size=sizeof(array)/sizeof(int); 
cout <<"size="<<size <<endl; 
for (int i=0;i<size;i++) 
cout <<array[i] <<" "; 
cout <<endl; 
return 0; 
} 
运行结果:
size=6 
3 5 6 8 7 9 
通过这个程序,可以成功地知道一个数组的大小,我们也不用为可能发生的越界访问而发愁了。

字符的存储情况

电脑是用电来计算和保存信息的。在电脑里,就好像有许许多多的开关,用导通(开)来表示1,用断开(关)来表示0。那么这些个“0”和“1”是怎么来表示一些字符的呢?
当只有一个开关的时候,这个开关能表示两种状态,即0和1;当有两个开关的时候,这两个开关可以表示四种状态,即00、01、10、11……如果你学过排列,就不难理解,当有8个开关的时候,可以表示28=256种状态,分别是0~255。在电脑中,就是用8个开关(0或1)来表示一个字节的,每一个开关(0或1)称为一个“位”(Bit),即8位组成一个字节。我们把一个字节所能表示的256种状态和256个字符按一定的顺序一一对应起来,一个字节就可以表示256种不同的字符。这种用8位二进制表示一个字符的编码称为ASCII码(念aski),它的全称是美国信息交换标准码(America Standard Code for Information Interchange)。我们需要记住的ASCII码有三个,数字0的ASCII码为十进制的48,大写字母A的ASCII码为十进制的65,小写字母a的ASCII码为十进制的97。
下面我们就来编写一段程序,输出ASCII码表的常用部分:(程序7.2.2)

#include "iostream.h" 
#include "iomanip.h" 
int main() 
{ 
   char temp; 
   for (int i=32;i<=127;i++) 
   { 
      temp=i; 
      cout << setw(2) <<temp; 
      if (i%16==15) //从0~15正好16个,所以余数为15的时候换行 
      { 
         cout <<endl;  
      } 
   } 
   return 0; 
} 
运行结果:

以上这段程序输出了96个常用的字符,从空格(ASCII码为十进制的32)一直到三角(ASCII码为十进制的127)。每行16个字符,共6行。有些人可能要问一个问题,上面这段程序中怎么能把整型变量i赋值给字符型变量temp呢?根据前面我们所说的字符的存储原理,不难发现字符的实质是一个0~255的整数,所以把一个在这个范围内的整数赋值给字符变量在C++中是允许的。

字符数组在内存中的存储情况

我们以前说过,字符和字符串是不同的:字符只能是一个,而字符串是由若干个字符连接而成。可是,’a’和”a”有区别吗?
其实字符和字符串的区别有点像单词和句子的区别。一句句子可能只有一个单词组成,但是句号却是必不可少的,否则就不能称为句子了。字符串在结尾处也会加上一个“句号”来表示字符串的结束,称为结尾符。在C++中用数组表示的字符串的结尾符是’\0’,它也是一个字符。所以字符串”a”实际上是两个字符,即字符’a’和结尾符’\0’。
在初始化一个字符数组的时候有两种初始化方式,一种是按字符串初始化,一种是按字符初始化。按字符串初始化就会在最后一个元素出现结尾符,而结尾符也要占用一个字符的空间,所以在声明数组的时候一定要注意空间是否足够。下面我们就来看一下这两种初始化方法:(程序7.2.3)

#include "iostream.h" 
int main() 
{ 
   char a[]={"Hello"};//按字符串初始化 
   char b[]={'H','e','l','l','o'};//按字符初始化 
   char c[]={'H','e','l','l','o','\0'};//按字符串初始化 
   cout <<"Size of A=" <<sizeof(a) <<endl; 
   cout <<"Size of B=" <<sizeof(b) <<endl; 
   cout <<"Size of C=" <<sizeof(c) <<endl; 
   cout <<a <<endl; 
   cout <<b <<endl; 
   cout <<c <<endl; 
   return 0; 
} 
运行结果:
Size of A=6 
Size of B=5 
Size of C=6 
Hello 
Hello烫蘃ello 

Size of A=6 
Size of B=5 
Size of C=6 
Hello 
Hello烫蘃ello 
Hello 
从数组a、b和c的大小,我们就能看出按字符串和按字符初始化的不同了。你可能还会发现,输出的数组a和c都是正常的,为什么输出的b却夹杂着乱码呢?这是因为a和c的属性都是字符串的字符数组,而b是普通字符数组。b数组没有结尾符,电脑在输出它的时候就会发生问题了。
数组a和b在内存中的存储情况如右上图所示(图7.2.3)

5.向函数传递数组

数组的存储空间很大,如果能够把它作为参数传递给函数,那么就能发挥很大的作用了。比如本来一个选出最大数的max函数只能在两个数或三个数里面选出一个最大的数字,如果我们把数组传递过去,它就能够在一堆数字中选出最大的数了,这大大提高了程序的效率。当函数中的某个参数是数组时,在参数名后加上一对中括号,比如int a[],表示参数a是一个数组。下面我们就来看这样一个在一堆正数里面找一个最大数的程序:(程序7.3.1)

#include "iostream.h" 
int max(int a[],int size);//size是数组的大小 
int main() 
{ 
   int number[]={2,45,12,6,23,98,13,3}; 
   cout <<max(number,sizeof(number)/sizeof(int)) <<endl; 
   return 0; 
} 
int max(int a[],int size) 
{ 
   int max=0; 
   for (int i=0;i<size;i++) 
   { 
      if (a[i]>max) 
      max=a[i]; 
   } 
   return max; 
} 
运行结果:
98 
我们发现,在函数里使用数组也是比较方便的。但大家有没有考虑过一个问题,我们为什么不在函数里面用sizeof算出数组的大小,而非要在函数外面算好了,再作为参数传递给函数呢?在这里,我们就有必要讲一下数组作为参数传递给函数的原理了。
我们以前说过,参数的传递是将实参的值赋给形参。然而对于数组来说却是一个例外,因为数组的数据太多了,将其一一赋值既麻烦又浪费空间,所以数组作为参数传递给函数的只是数组首元素的地址,函数在需要用到后面元素时再按照这个地址和数组下标去查找。也就是说后面的元素根本没到函数里来,所以在函数里求不出数组的大小也就不足为奇了。
所以,当一个函数的参数是一个数组时,我们必须注意要想办法让这个函数知道数组的大小。
不过,既然数组传递给函数的是数组首元素在内存中地址,而数据又都是存在内存里的,那么在函数中对数组参数的修改会不会影响到实参本身的值呢?让我们来看一段程序,验证一下我们的想法:(程序7.3.2)
#include "iostream.h" 
#include "iomanip.h" 
void sort(int a[],int size);//将数组中的元素从大到小排列 
int main() 
{ 
   int num[]={2,3,8,6,4,1,7,9}; 
   const int size=sizeof(num)/sizeof(int); 
   sort(num,size); 
   cout <<"排列后的数组元素" <<endl; 
   for (int i=0;i<size;i++)//输出排列好以后的数组元素 
   { 
      cout <<setw(2) <<num[i]; 
   } 
   cout <<endl; 
   return 0; 
} 
void sort(int a[],int size) 
{ 
   cout <<"原来的数组元素" <<endl; 
   for (int i=0;i<size;i++)//输出原来的数组元素 
   { 
      cout <<setw(2) <<a[i]; 
   } 
   cout <<endl; 
   for (int j=0;j<size;j++) 
   { 
      int min=a[j],mink=j;//先假设未排序的首元素是最小的数 
      for (int k=j;k<size;k++)//找到尚未排序的元素中最小的数 
      { 
         if (a[k]<min) 
         { 
            min=a[k]; 
            mink=k; 
         } 
      } 
      int temp=a[j];//交换两个元素 
      a[j]=a[mink]; 
      a[mink]=temp; 
   } 
} 
运行结果:
原来的数组元素 
2 3 8 6 4 1 7 9 
排列后的数组元素 

2 3 8 6 4 1 7 9 
排列后的数组元素 
1 2 3 4 6 7 8 9 


算法时间:排序(Sort)
排序是经常要使用到的一项功能。排序的算法也有多种。程序7.3.2所使用的排序方法称为直接选择排序,即在未排序的元素中选择出最小的一个,与未排序的首元素交换,直到所有的元素都已经排序。(如右上表所示)以后大家还会在数据结构课程中学习到一些更高效的排序算法,如快速排序法,插入排序法等等。
我们交换了sort函数中参数数组a的顺序,却发现回到主函数以后,num数组的元素次序也发生了变化。正是因为我们在函数中将内存中的数据作了操作,所以影响到了实参。

6.二维数组

我们知道,一维空间是一条线,数学中用一条数轴来表达;二维空间是一个平面,数学中用平面坐标系来表达。那么二维数组又是什么样的呢?

线与面

我们用一个下标来描述一维数组中的某个元素,就好像在用数描述一条线上的点。而所有的数据都是存储在一条线上。如果我们采用两个下标,就能形成一个平面,犹如一张表格,有行有列,所有的数据就能够存放到表格里。

我们把二维数组的两个下标分别称为行下标和列下标,在前面的是行下标,在后面的是列下标。
那么什么时候要用二维数组呢?一般有两种情况,一种是描述一个二维的事物。比如用1表示墙,用0表示通路,我们可以用二维数组来描述一个迷宫地图;用1表示有通路,0表示没有通路,我们可以用二维数组来描述几个城市之间的交通情况。还有一种是描述多个具有多项属性的事物。比如有多个学生,每个学生有语文、数学和英语三门成绩,我们就可以用二维数组来描述。
对于第二种情况,我们要注意各项属性应该是同一种数据类型,比如三种学科的成绩都是整数。如果出现了姓名(字符串属性),就不能将他们组合到一个二维数组里去。所以不要企图将不同数据类型的属性整合到一个二维数组中去。

二维数组的声明和初始化

二维数组的声明和一维数组是类似的,不同之处只是多了一个下标:
数据类型数组名[行数][列数];
要注意,二维数组的下标也都是从0开始的。
二维数组的初始化分为两种,一种是顺序初始化,一种是按行初始化,我们来看一段程序,就能够对它们有所了解了:(程序7.4.1)

#include "iostream.h" 
#include "iomanip.h" 
int main() 
{ 
   int array1[3][2]={4,2,5,6};//顺序初始化 
   int array2[3][2]={{4,2},{5},{6}};//按行初始化 
   cout <<"array1" <<endl; 
   for (int i=0;i<3;i++)//输出数组array1 
   { 
      for (int j=0;j<2;j++) 
     { 
         cout <<setw(2) <<array1[i][j]; 
      } 
      cout <<endl; 
   } 
   cout <<"array2" <<endl; 
   for (int k=0;k<3;k++)//输出数组array2 
   { 
      for (int l=0;l<2;l++) 
      { 
         cout <<setw(2) <<array2[k][l]; 
      } 
      cout <<endl; 
   } 
   return 0; 
} 
运行结果:
array1 
4 2 
5 6 
13 4 
array2 
4 2 
5 8 
6 8 
我们可以看出,所谓按顺序初始化就是先从左向右再由上而下地初始化,即第一行所有元素都初始化好以后再对第二行初始化。而按行初始化则是用一对大括号来表示每一行,跳过前一行没有初始化的元素,在行内从左向右地进行初始化。对于没有初始化的元素,则都是一个不确定的值。

省略第一维的大小

我们在第一节学到,一维数组的大小可以省略。可是二维数组的元素个数是行数和列数的乘积,如果我们只告诉电脑元素个数,电脑无法知道究竟这个数组是几行几列。所以,C++规定,在声明和初始化一个二维数组时,只有第一维(行数)可以省略。比如:
    int array[][3]={1,2,3,4,5,6};
相当于:
    int array[2][3]={1,2,3,4,5,6};

二维数组在内存中的存储情况

先前已经说明,内存是依靠地址来确定内存中的唯一一个存储单元的,即只有一个参数。所以在内存中,所有的数据都是像一维数组那样顺序存储的。那么具有两个下标的二维数组是怎样存放到内存中的呢?
在内存中,先将二维数组的第一行按顺序存储,接着就是第二行的数据,然后是第三行的数据……右图(图7.4)所示的就是一个二维数组在内存中的存储情况。

向函数传递二维数组

我们知道,数组作为参数传递给函数的是数组首元素的地址。对于二维数组来说亦是如此。不过有两个问题,一个是我们必须让函数知道行数和列数,这就像我们要让函数知道一维数组的大小一样,防止发生越界访问。另一个就是我们必须让电脑知道这个二维数组是怎样的一个表格,即必须告知数组的列数。这和只能省略二维数组的行数道理是一样的。下面我们就来看一个向函数传递二维数组的程序:

#include "iostream.h" 
#include "iomanip.h" 
void disp(int a[][2],int r,int c);//告知数组的列数 
int main() 
{ 
   int array[3][2]={4,2,5,6,3,1}; 
   cout <<"array" <<endl; 
   disp(array,3,2); 
   return 0; 
} 
void disp(int a[][2],int r,int c) 
{ 
   for (int i=0;i<r;i++) 
   { 
      for (int j=0;j<c;j++) 
      { 
         cout <<setw(2) <<a[i][j]; 
      } 
      cout <<endl; 
   } 
} 
运行结果:
array 
4 2 
5 6 
3 1

二维数组转化成一维数组

有些时候,我们觉得用二维数组来描述一样事物很方便。比如我们用二维数组来画一个迷宫地图,行下标和列下标就如同直角坐标系一样。可是在某些情况下,不能使用二维数组,或者难以制造一个二维数组。二维数组在内存中的存储情况和一维数组是相同的,所以我们只好用一个一维数组来代替它了。

于是,我们不难总结出一个结果,一个二维数组元素a[x][y]在一维数组b中,是:
    a[x][y]=b[x*列数+y]




版权声明:本文为博主原创文章,未经博主允许不得转载。

相关文章推荐

【C++探索之旅】第一部分第九课:数组威武,动静合一

我们将学习两种类型的数组。一种数组是预先知道其中所包含的元素数目的,例如一场比赛的前10个最佳得分;另一种数组的元素数目会变化,例如一个网站的用户名列表。...

C++深入体验之旅九:程序调试

1.头文件的奥秘 如何创建一个头文件 在第二章中,我们看到一个C++的工程里面除了源文件还有头文件。根据以下步骤便能创建一个头文件: 首先要创建或打开一个工程,然后按File菜单中的new...

C++深入体验之旅八:枚举类型和结构体

1.什么是枚举类型 在基本的数据类型中,无外乎就是些数字和字符。但是某些事物是较难用数字和字符来准确地表示的。比如一周有七天,分别是Sunday、Monday、Tuesday、Wednesday...

C++深入体验之旅三:分支结构

1.if语句 对于可能发生的事情,我们平时经常会说“如果……,那么……”。语文里,我们叫它条件复句。“如果”之后的内容我们称为条件,当条件满足时,就会发生“那么”之后的事件。我们来看这样一句英语:If...

C++深入体验之旅二:变量和数据

1.C++变量简介   1、什么是变量? 电脑具有存储的功能。我们可以通过Word打开一个保存的文章,也可以通过FPE(整人专家,一款游戏修改软件)来查看或锁定内存中保存的游戏人物的生命值。那么,一...

C++深入体验之旅十一:类(上)

1.类是一种数据类型 我们已经了解了数据类型和变量的关系。数据类型是各个变量的归类,而变量则是某个数据类型的具体表现,我们称变量为数据类型的一个实例(Instance)。各个变量都有他们的属性:...

C++深入体验之旅七:指针

1.什么是指针 在我们的桌面上,往往有这样一些图标:在它们的左下角有个小箭头,我们双击它,可以调出本机内的一些程序或文件。然而我们发现这些图标所占的存储空间很小,一般也就几百到几千字节。可是那么小的...

C++深入体验之旅十二:类(下)

12.友元类 在编写链表类的时候我们有着这样的困惑:链表类和链表结点类都是我们编写的,我们能保证链表类对链表结点类的操作都是安全的。但由于类的封装性,我们不得不编写一些成员函数,以便于链表类访问链表...

C++深入体验之旅四:循环结构

1.for循环语句 大家看过赛车的话都知道,赛车就是围绕着一个固定的跑道跑一定数量的圈数,如果没有发生意外,那么跑完了指定数量的圈数,比赛就结束了。 我们来设想一下赛车的实际情况,当比赛开始,赛车越...

C++深入体验之旅五:C++函数

1.什么是函数   在日常生活中,我们经常会用到工具。比如我们画一个表格需要用到直尺,它可以告诉我们线段的长度;我们开瓶子的时候需要用开瓶器,它可以把瓶子打开;我们在做计算题的时候需要用到计算器,它...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:C++深入体验之旅六:数组
举报原因:
原因补充:

(最多只允许输入30个字)