在程式設計過程中,我們經常需要處理一批相同類型的資料(例如:全班學生的成績、一週的氣溫記錄)。若逐一定義變數 int score1, score2, score3...,不僅程式碼冗長難維護,也無法靈活地進行迴圈處理。此時,「數組」便成為了不可或缺的資料結構。
類型說明符 數組名[常量表達式];
範例: int a[10]; 宣告一個可容納 10 個整數的數組。
0 ~ length-1,越界會導致未定義行為。float i, j[];(i為單精度變數,j為數組)。語法:數組名[下標表達式]。下標表達式可為任意整型表達式,但值必須為非負整數。
int a[5];
a[3] = 10; // 將第 4 個元素賦值為 10
#include <stdio.h>
int main() {
float score[10];
int i;
printf("請輸入 10 位學生的成績:\n");
for (i = 0; i < 10; i++) {
scanf("%f", &score[i]);
}
printf("\n成績單:\n");
for (i = 0; i < 10; i++) {
printf("第 %d 位學生:%.2f\n", i + 1, score[i]);
}
return 0;
}
提示: 迴圈條件嚴格使用 i < 10 而非 i <= 10,以防下標越界。
語法:類型 數組名[長度] = {值列表};
int a[3] = {1, 2, 3}; // 完全初始化
float f[3] = {1.0, 2.0}; // 部分初始化,剩餘元素自動補 0
int b[] = {1, 2, 3, 4}; // 完全初始化時可省略長度,編譯器自動推導
// 錯誤示範:
int c[4];
c = {1,2,3,4}; // 編譯錯誤!初始化列表僅能用於定義時,事後只能逐元素賦值。
需求:錄入 30 位學生成績,統計各分數段人數、計算優秀率(≥85)與及格率(≥60),並標記不及格學生。
#define N 30
#include <stdio.h>
int main() {
float score[N];
int count[4] = {0}; // 0:優秀 1:良好 2:及格 3:不及格
int i;
float excellent_rate, pass_rate;
// 輸入與同步統計
for (i = 0; i < N; i++) {
scanf("%f", &score[i]);
if (score[i] >= 85) count[0]++;
else if (score[i] >= 70) count[1]++;
else if (score[i] >= 60) count[2]++;
else count[3]++;
}
excellent_rate = (float)count[0] / N;
pass_rate = (float)(N - count[3]) / N;
printf("優秀(85-100): %d\n良好(70-84): %d\n及格(60-69): %d\n不及格(<60): %d\n",
count[0], count[1], count[2], count[3]);
printf("優秀率: %.2f%%, 及格率: %.2f%%\n", excellent_rate * 100, pass_rate * 100);
// 輸出明細並標記不及格
for (i = 0; i < N; i++) {
if (score[i] < 60)
printf("學號 %d: %.1f 【不及格】\n", i + 1, score[i]);
else
printf("學號 %d: %.1f\n", i + 1, score[i]);
}
return 0;
}
資料類型 數組名[常量表達式1][常量表達式2];
例如:int matrix[3][4]; 表示 3 行 4 列的整數矩陣。
語法:數組名[行下標][列下標]。存取時通常使用雙層 for 迴圈:外層控制行,內層控制列。
#define M 3
#define N 4
#include <stdio.h>
int main() {
int i, j, a[M][N];
printf("請輸入 %d x %d 矩陣元素:\n", M, N);
for (i = 0; i < M; i++)
for (j = 0; j < N; j++)
scanf("%d", &a[i][j]);
printf("矩陣內容:\n");
for (i = 0; i < M; i++) {
for (j = 0; j < N; j++)
printf("%4d", a[i][j]);
printf("\n");
}
return 0;
}
// 1. 一維展開賦值(按行優先順序)
int a[2][3] = {1, 2, 3, 4, 5, 6};
// 2. 分行分組賦值(推薦,結構清晰)
int b[2][3] = {{1, 2, 3}, {4, 5, 6}};
// 3. 部分初始化,剩餘補 0
int c[2][3] = {1, 2, 3, 4}; // 等價於 {{1,2,3}, {4,0,0}}
int d[3][3] = {{1}, {2}, {3}}; // 對角線為 1,2,3,其餘 0
// 4. 完全初始化時,第一維長度可省略,第二維必須指定
int e[][3] = {1,2,3,4,5,6}; // 編譯器推導為 2 行 3 列
| 場景 | 正確做法 | 常見錯誤 |
|---|---|---|
| 定義後整體賦值 | 逐元素賦值或 memcpy | a = {1,2,3}; 編譯錯誤 |
| 函數傳遞數組 | 傳遞指標 int *arr 或 int arr[],並額外傳長度 | 嘗試用 sizeof(arr) 計算長度(退化為指標後失效) |
| 二維數組做參數 | void func(int arr[][COLS], int rows) 第二維必須固定 | void func(int **arr) 類型不匹配 |
數組是 C 語言最高效、最基礎的聚合資料類型。掌握其記憶體佈局、初始化規則與邊界檢查,是寫出健壯 C 程式的關鍵第一步。