1、一、为什么要使用数组 例题:输入50个学生的某门课程的成绩,打印出低于平均分的学生序号与成绩。 田肖倦娄【分析】在解决这个问题时,虽然可以通过一个变量来累加读入的50个成绩求出学生的总分,进而求出平均分。但因为只有读入最后一个学生的分数后才能求得平均分,并且要求打印出低于平均分的学生序号和成绩,故必须把50个学生的成绩都保留起来,然后逐个和平均分比较,把低于平均分的成绩打印出来。如果,用简单变量a1,a2,…,a50存储这些数据,要用50个变量保存输入的数据,程序片断如下: cin>>a1>>a2>>…>>a10; … cin>>a41>>a42>>…>>a50;注意,如果真正要像上面这样编写程序,则上面的所有省略号必须用完整的语句写出来。可以看出,这样的程序是多么繁琐。如果说处理的数据规模达到成千上万,上面的例子单单读入就会异常复杂,电脑的优势没有得到体现。 从以上的讨论可以看出,如果只使用简单变量处理大量数据,就必须使用大量只能单独处理的变量,即使是简单问题也需要编写冗长的程序。如果能像数学中使用下标变量ai形式表示这50个数,则问题就容易实现。在C++语言中,具有下标性质的数据类型是数组。如果使用数组,上面的问题就变得十分简单、清晰。例如,读入50个学生的成绩,只需写如下语句即可: for (int i=1;i<=50;++i) cin>>a[i]; 在这里引用了带下标的变量(分量变量称为数组元素)a[i]来代替a1,a2…,a50,方括号中的i称为下标,当循环变量i=1时a[i]就是a[1];当i=2时a[i]就是a[2]……;当i=50时a[i]就是a[50]。输入的时候,让i从1变化到50,循环体内输入语句中的a[i]也就分别代表了a1,a2…,a50这50个带下标的变量。这样上述问题的程序可写为: tot = 0; // tot存储50个学生的总分 for (int i=1;i<=50;++i) // 循环读入每一个学生的成绩,并把它累加到总分中 { cin>>a[i]; tot+=a[i]; } ave= tot/50; //计算平均分 for (int i=1;i<=50;++i) if (a[i]<ave) cout<<"No. "<<i<<" "<<a[i]; //如果第i个同学成绩小于平均分,则将输出这个学生的序号和成绩。 要在程序中使用下标变量,必须先说明这些下标变量的整体为数组,即数组是若干个同名(如上面的下标变量的名字都为a)下标变量的集合,这些变量的类型全部一致。
2、二、一维数组的定义 当数组中每个元素只带有一个下标时,我们称这样的数组为一维数组。 数组的定义格式如下: 类型标识符 数组名[常量表达式] 说明: ①数组名的命名规则与变量名的命名规则一致。 ②常量表达式表示数组元素的个数。可以是常量和符号常量,但不能是变量。 例如: int a[10]; //数组a定义是合法的 int b[n]; //数组b定义是非法的
3、三、一组数组的引用 通过给出的数组名称和这个元素在数组中的位置编号(即下标),程序可以引用这个数组中的任何一个元素。 一维数组元素的引用格式: 数组名[下标] 例如: int a[10]; 其中,a是一维数组的数组名,该数组有10个元素,依次表示为: a[0],a[1],a[2],a[3],a[4],a[5],a[6],a[7],a[8],a[9]。 需要注意的是:a[10]不属于该数组的空间范围。
4、当在说明部分定义了一个数组变量之后,C++编译程序为所定义的数组在内存空间开辟一串连续的存储单元。例如:上例中的a数组在内存的存储如表所示:
5、a数组共有10个元素组成,在内存中10个数组元素共占10个连续的存储单元。a数组最小下标为0,最大下标9。按定义a数组所有元素都是整型变量。 再次提醒注意:类型和变量是两个不同概念,不能混淆。就数组而言,程序的执行部分使用的不是数组类型而是数组变量。说明: (1)下标可以是整型常量或整型表达式。如果使用表达式作为下标,就要计算表达式的值以确定下标。 (2)C++语言中,每个数组第一个元素的下标都是0,因此第一个元素为第0个数组元素。 (3)C++语言只能逐个引用数组元素,而不能一次引用整个数组。 例如:int a[100],b[100]; a=b;这样的写法是非法的。 (4)数组元素可以像同类型的普通变量那样使用,对其进行赋值和运算的操作,和普通变量完全相同。例如: c[10]=34;实现了给c[10]赋值为34。
6、四、一维数组的初始化 数组的初始化可以在定义时一并完成。格式: 类型标识符 数组名[常量表达式]={值1,值2,…} 例如: int a[5]={1,2,3,4,5} 说明: (1)在初值列表中可以写出全部数组元素的值,也可以写出部分。例如,以下方式可以对数组进行初始化: int x[10]={0,1,2,3,4}; 该方法一次仅对数组的前5个元素依次进行初始化。 (2)对数组元素全部初始化为0,可以简写为:{0}。 例如: int a[5]={0}; 将数组a的5个元素都初始化为0。
7、五、一维数盲褓梆尺组的应用 例5.1 输入n个数,要求程序按输入时的逆序把这n个数打印出来,已知整数不超过100邗锒凳审个。也就是说,按输入相反顺序打印这n个数。 【分析】我们可定义一个数组a用以存放输入的n个数, 然后将数组a中的内容逆序输出。#include<cstdio>int a[100];int main(){ int x,n=0; while(scanf("%d",&x)==1) a[n++]=x; //相当{a[n]=x;n++;} for (int i=n-1;i>=1;--i) printf("%d ",a[i]); //注意%d后面有一个空格,保证行首行尾均无空格 printf("%d\n",a[0]); return 0;}【说明】: 语句int a[100]声明了一个包含100个整型变量的数组,它们是:a[0],a[1],a[2],…,a[99]。注意,没有a[100]。在上述程序中,数组a被声明在main函数的外面。只有放在外面时,数组a才可以开得很大;放在main函数内时,数组稍大就会异常退出。。 数组不能够进行赋值操作:如果声明的是int a[MAXN],b[MAXN],是不能赋值b=a的(Pascal语言可以的)。如果要从数组a复制k个元素到数组b,可以这样做:memcpy(b,a,sizeof(int)*k)。如果数组a和b都是浮点型的,复制时要写成memcpy(b,a,sizeof(double)*k)。如果需要把数组a全部复制到数组b中,可以写得简单一些:memcpy(b,a,sizeof(a))。使用memcpy函数要包含头文件cstring。