跳轉到內容

C 程式設計/陣列和字串

來自華夏公益教科書,開放的書籍,開放的世界

C 中的陣列用於在單個變數名稱下使用索引(也稱為下標)儲存相關資料。最簡單的理解是將陣列視為相同型別變數的列表或有序分組。因此,陣列通常可以幫助程式設計師以有效且直觀的的方式組織資料集合。

稍後我們將考慮指標的概念,指標是 C 的基礎,它擴充套件了陣列的性質(陣列可以稱為常量指標)。現在,我們只關注它們的宣告和使用。

C 陣列以以下形式宣告

type name[number of elements];

例如,如果我們想要一個包含六個整數(或整數值)的陣列,我們在 C 中寫

int numbers[6];

對於一個名為 *letters* 的六個字元陣列,

char letters[6];

等等。

你也可以在宣告時進行初始化。只需將初始元素放在花括號中,用逗號隔開作為初始值

type name[number of elements]={comma-separated values}

例如,如果我們想用六個整數初始化一個數組,其中0, 0, 1, 0, 0, 0作為初始值

int point[6]={0,0,1,0,0,0};

雖然在這種情況下的陣列初始化時,可以省略陣列維度,並且陣列將自動調整大小以容納初始資料

int point[]={0,0,1,0,0,0};

這非常有用,因為陣列的大小可以透過簡單地新增或刪除初始化元素來控制,而無需調整維度。

如果指定了維度,但沒有初始化陣列中的所有元素,則剩餘元素將包含值為 0 的值。這非常有用,尤其是在我們有非常大的陣列時。

int numbers[2000]={245};

上面的示例將陣列的第一個值設定為 245,其餘設定為 0。

如果我們想訪問儲存在陣列中的變數,例如在上面的宣告中,以下程式碼將儲存一個 1 在變數中*x*

int x;
x = point[2];

C 中的陣列從 0 開始索引,而不是從 1 開始。上面陣列的第一個元素是*point[0]*。陣列中最後一個值的索引是陣列大小減 1。在上面的示例中,下標從 0 執行到 5。C 不保證對陣列訪問進行邊界檢查。編譯器可能不會對以下內容進行抱怨(雖然最好的編譯器會這樣做)

char y;
int z = 9;
char point[6] = { 1, 2, 3, 4, 5, 6 };
//examples of accessing outside the array. A compile error is not always raised
y = point[15];
y = point[-4];
y = point[z];

在程式執行期間,越界陣列訪問並不總是會導致執行時錯誤。你的程式可能在從 *point[-1]* 中檢索值後愉快地繼續。為了減輕索引問題,*sizeof()* 表示式通常用於編寫處理陣列的迴圈時。

許多人使用一個宏,該宏依次使用 *sizeof()* 來查詢陣列中的元素數量,這個宏被各種命名為 *“lengthof()”*,[1] *“MY_ARRAY_SIZE()”* 或 *“NUM_ELEM()”*,[2] *“SIZEOF_STATIC_ARRAY()”*,[3] 等等。

int ix;
short anArray[]= { 3, 6, 9, 12, 15 };
 
for (ix=0; ix< (sizeof(anArray)/sizeof(short)); ++ix) {
  DoSomethingWith("%d", anArray[ix] );
}

請注意,在上面的示例中,沒有明確指定陣列的大小。編譯器知道將其大小設定為 5,因為初始化列表中有五個值。向列表中新增一個額外的值會導致它的大小調整為六,並且由於 *sizeof* 表示式在*for*迴圈中,程式碼會自動適應此更改。良好的程式設計實踐是宣告一個變數 *size*,並將陣列中的元素數量儲存在其中。

*size = sizeof(anArray)/sizeof(short)*

C 也支援多維陣列(或者更確切地說,是陣列的陣列)。最簡單的型別是二維陣列。這將建立一個矩形陣列——每一行都具有相同數量的列。為了獲得一個包含 3 行和 5 列的字元陣列,我們在 C 中寫

char two_d[3][5];

要訪問/修改此陣列中的值,我們需要兩個下標

char ch;
ch = two_d[2][4];

two_d[0][0] = 'x';

類似地,可以像這樣初始化多維陣列

int two_d[2][3] = {{ 5, 2, 1 },
                   { 6, 7, 8 }};

必須明確說明列數;但是,編譯器將根據初始化列表找到適當的行數。

也有一些奇怪的表示法

int a[100];
int i = 0;
if (a[i]==i[a])
{
  printf("Hello world!\n");
}

*a[i]* 和 *i[a]* 指的是同一個位置。(這將在下一章中解釋。)

儲存在記憶體中的字串“Merkkijono”

C 沒有內建的字串處理功能;因此,字串被定義為字元陣列。C 允許字元陣列用字元字串而不是字元列表來表示,並且編譯器會自動在末尾新增空終止符。例如,要儲存字串“Merkkijono”,我們會寫

char string[11] = "Merkkijono";

char string[11] = {'M', 'e', 'r', 'k', 'k', 'i', 'j', 'o', 'n', 'o', '\0'};

在第一個示例中,字串將由編譯器在末尾自動附加一個空字元;按照慣例,庫函式期望字串以空字元結尾。後一種宣告表示各個元素,因此需要手動新增空終止符。

字串並不總是必須與顯式變數相關聯。正如你已經看到的,可以直接建立一個字元字串作為直接使用的未命名字串(如 *printf* 函式中)。

要建立一個超長的字串,你需要將字串分成多個部分,透過用引號關閉第一部分,並在下一行重新開始字串(也以引號開頭和結尾)

char string[58] = "This is a very, very long "
                "string that requires two lines.";

雖然字串也可以透過在行尾放置反斜槓字元來跨越多行,但這種方法已被棄用。

有一個有用的字串處理例程庫,你可以透過包含另一個頭檔案來使用它。

#include <string.h>  //new header file

這個標準字串庫允許對字串執行各種任務,在字串一章中進行了討論。

參考文獻

[編輯 | 編輯原始碼]


華夏公益教科書