官术网_书友最值得收藏!

  • Visual C++實用教程
  • 鄭阿奇編著
  • 4880字
  • 2018-12-30 12:04:30

1.6 數組

迄今為止,程序所使用的數據類型都是基本數據類型,如int、float、double等。但C++還允許用戶按一定的規則進行數據類型的構造,如定義數組、指針、結構和引用等,這些類型統稱為構造類型。數組是應用最廣泛的構造類型之一,它有一維、二維和多維,分別應用于不同的場合。

1.6.1 一維數組

在C++中,數組是相同類型的元素的有序集合,每一個元素在內存中占用相同大小的內存單元,這些內存單元在內存空間中都是連續存放的。和變量一樣,在使用數組前需要對數組進行定義以通知編譯為其開辟相應的內存空間。數組一旦定義后,就可在程序中引用和操作這些數組元素,每個元素所對應的內存空間或在數組中的位置可用統一的數組名,通過下標運算符“[ ]”指定下標序號來唯一確定。這里先來討論一維數組。

1.一維數組的定義和引用

C++中,一維數組的一般定義格式如下:

<數據類型>  <數組名>[<常量表達式>];

其中,方括號“[ ]”是區分數組和變量的特征符號。方括號中的常量表達式的值必須是一個確定的整型數值,且數值必須大于0,它反映維的大小,對于一維數組來說,也可以是一維數組元素的個數或一維數組的大小、數組的長度。數據類型用來指定數組中元素的數據類型,以及每一個元素所占內存空間的大小,它必須是C++合法的數據類型。數組名與變量名一樣,遵循標識符命名規則。例如:

int  a[10];

這個定義會使編譯為其分配10個int元素連續的內存空間。其中,a表示數組名,方括號里的10表示該數組有10個元素,每個元素的類型都是int。在定義中,還可將同類型的變量或其他數組的定義寫在一行語句中,但它們必須用逗號隔開。例如:

int  a[10],b[20],n;

其中,a和b被定義成整型數組,n是整型變量。

一般地,數組方括號中的常量表達式中不能包含變量,但可以包括常量和符號常量,如:

int       a[4-2];                // 合法,表達式4-2是一個確定的值2
float     b[3*6];                // 合法,表達式3*6是一個確定的值18
const int size = 18;
int       c[size];               // 合法,size是一個標識符常量
int SIZE = 18;
int       d[SIZE];               // 不合法,SIZE是一個變量,不能用做下標大小的定義
int       d[0];                  //ANSI/ISO C++不合法,定義時,下標必須大于0

需要說明的是,當數組的數據類型是char時,則該數組稱為字符數組。由于字符數組的每一個元素都用來存儲一個字符,因此字符數組可用來存放一個字符序列,即字符串(后面還會專門討論)。

數組定義后,就可以用下標運算符通過指定下標序號來引用和操作數組中的元素,引用時按下列格式:

<數組名> [<下標表達式>]

其中,方括號“[ ]”是C++的下標運算符,下標表達式的值就是下標序號,反映該元素在數組中的位置。需要說明的是:

(1)C++數組的下標序號總是從0開始。例如,若有數組定義:

int  a[5];

則由于開始的下標序號為0,也就是說,a[0]是數組a的第一個元素。由于數組a被定義成具有5個元素的一維數組,因此a[0],a[1],a[2],a[3],a[4]是數組a的5個元素,a[4]是a的最后一個元素。注意:這里的數組a沒有a[5]這個數組元素。可見,在引用一維數組元素時,若數組定義時指定的大小為n,則下標序號范圍為0~(n-1)。

(2)在引用數組元素時,下標序號的值必須為整型,因此它可以是一個整型常量,也可以是一個整型變量,或是結果為一個整型值的表達式等。例如:

int  d[10];
// …
for (int i=0; i<10; i++) cout<<d[i]<< "\t";

代碼中的d[i]就是一個對數組d元素的合法引用,i是一個整型變量,用來指定下標序號。當i=0時,引用的是元素d[0],當i=1時,引用的是元素d[1]……以此類推。要注意,若將for中的i<10誤寫成i<=10,則當i=10時,數組d的下標序號已超界,而這一錯誤是不會在編譯與連接中反映出來的,因此在程序設計中必須保證數組下標序號取值的正確性。

(3)數組定義后,編譯會根據數組的大小開辟相應的內存空間,并依照下標序號從小到大的次序依次存放數組中的各個元素。顯然,所開辟的內存大小(字節數)應等于數組元素個數*sizeof (數組類型)。

(4)事實上,數組中的每一個元素都可看成一個與數組數據類型相同的變量。并且,若設元素為X[n](X表示數組名,n表示合法的下標序號),則引用X[n]就是引用該元素所對應的內存空間,它與變量名一樣,都是對相應內存空間的標識。因此在程序中對數組元素進行賦值或其他處理時,它的操作與變量相同。

2.一維數組的初始化和賦值

與變量一樣,在引用前還可對一維數組進行初始化或賦初值。數組元素既可以在數組定義的同時賦初值,即初始化,也可以在定義后賦值。一維數組的初始化格式如下:

<數據類型>  <數組名>[<常量表達式>]={初值列表};

它在數組定義格式中,在方括號之后,用“={初值列表}”的形式進行初始化。其中,初值列表中的初值個數不得多于數組元素個數,且多個初值之間要用逗號隔開。例如:

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

是將花括號“{ }”里的初值(整數)1,2,3,4,5依次填充到數組a的內存空間中,即將初值依次賦給數組a的各個元素。它的作用與下列的賦值語句相同:

a[0]=1;  a[1]=2;  a[2]=3;  a[3]=4;  a[4]=5;

對于一維數組的初始化和賦值需注意以下幾點:

(1)可以給其中的一部分元素賦初值。例如:

int  b[5]={1,2};                   //A

是使數組b的元素b[0] = 1,b[1] = 2。

(2)在對數組進行初始化時,若沒有明確列舉元素值的元素,則其值均為0,即“A”中的元素b[2],b[3],b[4]的值均為默認的值0。正因如此,若有:

int  b[5]={0};

則使得數組b的各個元素的值均設為0。

(3)在初始化的“={初值列表}”中,花括號中的初值可以是常量,也可以是常量表達式,但不能有變量。例如:

double  f[5]={1.0,3.0*3.14,8.0};   // 合法
double  d=8.0;
double  f[5]={1.0,3.0*3.14,d};    // 不合法,d是變量

(4)在對全部一維數組元素賦初值時,有時可以不指定一維數組的長度。例如:

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

編譯將根據數值的個數自動設定數組c的長度,這里是5。要注意,必須讓系統在編譯時知道數組的大小。若只有:

int  c[];                     // 不合法,未指定數組大小

則是錯誤的。

(5)初始化數組的值的個數不能多于數組元素的個數。例如:

int e[5]={1,2,3,4,5,6};          // 錯誤,初始化值個數多于數組元素個數

(6)“={初值列表}”的方式只限于數組的初始化,不能出現在賦值語句中。例如:

int  c[4];                     // 合法
c[4]={1,2,3,4};               // 錯誤

(7)在“={初值列表}”方式中,逗號前面必須要有表達式或值。例如:

int f[5]={1,,3,4,5};            // 錯誤,第2個逗號前面沒有表達式或值
int g[5]={1,2,3,};              //ANSI/ISO C++中合法
int h[5]={};                    //ANSI/ISO C++中合法,等價于int h[5]={0};

(8)兩個一維數組不能直接進行賦值“=”運算,但數組元素可以。例如:

int  a1[4]={1,2,3,4};           // 合法
int  a2[4];                     // 合法
a2=a1;                          // 錯誤,數組名表示一個地址常量,不能做左值(后面還會討論)
a2[0]=a1[0];                    // 合法:數組元素就是一個變量
a1[2]=a2[1];                    // 合法:數組元素就是一個變量

1.6.2 二維數組

在C++數組定義中,數組的維數是通過方括號的對數來指定的。顯然,若在數組定義時指定多對方括號,則定義的是多維數組。最常用的多維數組是二維數組,這里就來討論一下。

1.二維數組的定義和引用

二維數組定義的格式如下:

<數據類型>  <數組名>[<常量表達式1>][<常量表達式2>];

從中可以看出,二維數組定義的格式與一維數組基本相同,只是多了一對方括號。同樣,若定義一個三維數組,則在二維數組定義格式的基礎上再增加一對方括號,以此類推。顯然,對于數組定義的統一格式可表示為:

<數據類型>  <數組名>[<常量表達式1>][<常量表達式2>]…[<常量表達式n>];

其中,各對方括號中的常量表達式用來表示相應維的大小。例如:

float b[2][3];
char c[4][5][6];

其中,b是二維數組,每個元素的類型都是float型。c是三維數組,每個元素的類型都是字符型。

需要說明的是:

(1)要注意數組定義中維的高低。如圖1.9所示,四維數組d的維的次序從右向左逐漸升高,最右邊的是最低維,最左邊的是最高維。

圖1.9 多維數組的維次序

(2)對于多維數組來說,數組元素的個數是各維所指定的大小的乘積。例如,上述定義的二維數組b中的元素個數為2×3=6個,三維數組c中的元素個數為4×5×6=120個。

一旦定義了二維數組,就可以通過下面的格式來引用數組中的元素:

<數組名> [<下標表達式1>][<下標表達式2>]

對于多維數組來說,引用的格式為:

<數組名> [<下標表達式1>][<下標表達式2>]…[<下標表達式n>]

這里的下標表達式1、下標表達式2等分別與數組定義時的“維”相對應。也就是說,對于上述定義“float b[2][3];”中的二維數組b來說,其元素引用時需寫成b[i][j]的形式。其中,每一維的下標序號都從0開始,且都小于相應維定義時指定的大小,即i的取值只能是0和1,j的取值只能是0、1和2。再如,對于上述定義“char c[4][5][6];”中的三維數組c來說,其合法的元素引用應是c[i][j][k]的形式,其中,i的取值只能是0~3的整數,j的取值只能是0~4的整數, k的取值只能是0~5的整數。

注意:

這里的下標序號都不能超過定義時所對應的維的大小。

與一維數組一樣,通過對二維或多維數組元素的引用,二維或多維數組元素可與相同數據類型的普通變量一樣進行賦值、算術運算及輸入/輸出等操作。

2.二維數組元素在內存空間存放的次序

由于內存空間是一維的,因此需要搞清二維或多維數組元素在內存中存放的次序。在C++中,表示維數的方括號的次序高低是從右向左逐漸升高,類似于十進制數中的個位、十位、千位……的變化次序。在內存中依次存放的數組元素的下標序號總是從低維到高維順序變化。例如:

int  a[3][4];

則a在內存中存放的元素的次序按數組元素下標序號變化的次序順序排列,這樣若在程序中通過循環嵌套來引用二維或多維數組的元素,則是最方便的方法。此時,循環嵌套的層數應與數組維數相同。例如:

int a[3][4], i, j;
// 輸入二維數組a的元素值
for (i=0; i<3; i++)
    for (j=0; j<4; j++)
        cin>>a[i][j];
// 輸出二維數組a的全部元素
for (i=0; i<3; i++)
{
    for (j=0; j<4; j++)
        cout<<a[i][j]<< "\t";
    cout<<endl;
}

3.二維數組的初始化和賦值

在程序設計中,常將二維數組看成一個具有行和列的數據表,例如:

int  a[3][4];

由于它在內存空間的存放次序可以寫成:

a[0]:a[0][0],       a[0][1],       a[0][2],       a[0][3]   // 第0行
a[1]:a[1][0],       a[1][1],       a[1][2],       a[1][3]   // 第1行
a[2]:a[2][0],       a[2][1],       a[2][2],       a[2][3]   // 第2行

因此,可以認為在數組a[3][4]中,3表示行數,4表示列數。故在進行二維數組初始化時一般以“行”為單位。

在C++中,“行”的數據由“{}”構成,且每一對“{}”根據其書寫的次序依次對應二維數組的第0行、第1行、第2行……第i行。例如:

int  a[3][4]={{1,2,3,4},{5,6,7,8},{9,10,11,12}};

其中,{1, 2, 3, 4}是對第0行元素進行初始化,{5, 6, 7, 8}是對第1行元素進行初始化,{9, 10, 11, 12}是對第2行元素進行初始化。它們依次進行,行與行之間用逗號分隔。每對花括號里的數據個數均不能大于列數。它等價于:

int  a[3][4]={1,2,3,4,5,6,7,8,9,10,11,12};     // 依次對元素進行初始化

需要說明的是:

(1)可以只對部分元素賦初值,例如:

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

凡沒有明確列舉元素值的元素,其值均為0,即等同于:

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

又如:

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

此時數據中沒有花括號,則將其按元素在內存空間的存放次序依次賦初值,即a[0][0] = 1,a[0][1]= 2,a[0][2] = 3,其余各個元素的初值為0。

(2)對于多維數組來說,若有初始化,則定義數組時可以忽略最高維的大小,但其他維的大小不能省略。也就是說,在二維數組定義中,最左邊方括號的大小可以不指定,但最右邊方括號的大小必須指定。例如:

int b[][4] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
// 結果為b[3][4]
int b[][4] = {{1, 2, 3, 4}, {5, 6}, {7},{ 8, 9, 10, 11}, 12};
// 結果為b[5][4]
int b[][4]={1,2,3};                  // 結果為b[1][4]
int b[][4]={{1},2,3};                // 結果為b[2][4]

當定義的數組的數據類型為char時,該數組就稱為字符數組,字符數組的每個元素都是字符。由于字符數組存放的是一個字符序列,因而它跟字符串常量有著密切的關系。在C++中,可用字符串常量來初始化字符數組,或通過字符數組名來引用字符串等。

1.一維字符數組

對于一維字符數組來說,它的初始化有兩種方式。一是:

char  ch[]={'H','e','l','l','o','!','\0'};

二是使用字符串常量來給字符數組賦初值。例如:

char  ch[]={"Hello!"};

其中的花括號可以省略,即:

1.6.3 字符數組

char  ch[]="Hello!";

這幾種方式都是使ch[0]= 'H',ch[1]= 'e',ch[2]= 'l',ch[3]= 'l',ch[4]= 'o',ch[5]= '!',ch[6]= '\0'。

注意:

由于字符串常量總是以'\0'作為結束符,它雖不是字符串的內容,但卻占據了一個存儲空間。因此當字符數組用字符串常量方式進行初始化時,要注意數組的長度還應包含字符串的結束符'\0',一定要注意字符數組與其他數組的這種區別。

需要說明的是,如果指定的數組長度大于字符串中的字符個數,那么其余的元素將自動設定為'\0'。例如:

char ch[9]="Hello!";

因"Hello!"的字符個數為6,但還要包括一個空字符'\0',故數組長度至少是7,從ch[6]開始到ch[8]都等于空字符'\0'。

要注意,不能將字符串常量直接通過賦值語句賦給一個字符數組。例如,下列賦值語句是錯誤的:

char str[20];
str="Hello!";                      // 錯誤

因為這里字符數組名str是一個指針常量(以后還會討論),不能放在賦值運算符左邊。

2.二維字符數組

一維字符數組常用于存取一個字符串,而二維字符數組可存取多個字符串。例如:

char str[][20]={"How",  "are",  "you"};

這時,數組元素str[0][0]表示一個char字符,值為'H';而str[0]表示字符串"How",str[1]表示字符串"are" ,str[2]表示字符串"you"。由于省略了二維字符數組的最高維的大小,編譯會根據初始化的字符串常量,自動設為3。要注意,二維字符數組的最右邊的大小應不小于初始化初值列表中最長字符串常量的字符個數+1。

1.6.4 數組與函數

以前所討論的函數調用都是按實參和形參的對應關系將實際參數的值傳遞給形參,這種參數傳遞稱為值傳遞。在值傳遞方式下,函數本身不對實參進行操作,也就是說,即使形參的值在函數中發生了變化,實參的值也不會受到影響。但如果傳遞函數的參數是某個內存空間的地址,則對這一個函數的調用就是按地址傳遞的函數調用,簡稱傳址調用。由于函數形參和實參都是指向同一個內存空間的地址,形參值的改變也就是實參地址所指向的內存空間的內容改變,從而實參的值也將隨之改變。通過地址傳遞,可以由函數帶回一個或多個值。

數組也可作為函數的形參和實參,若數組元素作為函數的實參,則其用法與一般變量相同。當數組名作為函數的實參和形參時,由于數組名表示數組內存空間的首地址,因此是函數的地址傳遞。

例Ex_StrChange】 改變字符串中的內容

#include <iostream.h>
#include <string.h>
void change(char str1[20]);
int  main()
{
    char name[10] = "Ding";
    cout<<name<<endl;
    change(name);                      // 調用時,只需指定數組名
    cout<<name<<endl;
    return 0;
}
void change(char str1[20])
{
    strcpy( str1, "Zheng" );
}

代碼中,函數change的形參是一個字符數組,調用時只要將數組名作為實參即可。由于函數傳遞的是數組的地址,因此函數中對形參改變的內容,也同樣反映到實參中。

程序運行結果如下:

Ding

Zheng

需要說明的是:

(1)函數調用時,實參數組與形參數組的數據類型應一致,如不一致,結果將出錯。

(2)形參數組也可以不指定大小,在定義數組時數組名后面跟一個空的方括號。為了滿足在被調用函數中處理數組元素的需要,可以另設一個參數,傳遞數組元素的個數。例如:

float  ave(int data[],int n);
主站蜘蛛池模板: 若尔盖县| 临江市| 肥东县| 夹江县| 喜德县| 时尚| 左权县| 高雄县| 怀柔区| 行唐县| 叶城县| 中宁县| 舒城县| 独山县| 荣成市| 湖口县| 民丰县| 和林格尔县| 中山市| 南靖县| 岳普湖县| 镇江市| 资源县| 内江市| 泾源县| 新平| 始兴县| 吉林市| 伊春市| 双流县| 涞源县| 石门县| 磴口县| 铅山县| 平舆县| 会宁县| 朝阳县| 邵阳市| 滕州市| 上蔡县| 郸城县|