float sales[3][8]; // 3行8列
int matrix[3][3] = {{1,2,3}, {4,5,6}, {7,8,9}}; // 分行初始化
int flat[3][3] = {1,2,3,4,5,6,7,8,9}; // 扁平初始化 (按行優先)
matrix[0][0] matrix[0][1] matrix[0][2] // 第0行連續 matrix[1][0] matrix[1][1] matrix[1][2] // 第1行連續 matrix[2][0] matrix[2][1] matrix[2][2] // 第2行連續 地址遞增順序:[0][0] → [0][1] → [0][2] → [1][0] → ...
int a[3][4];
a[i][j] // 標準下標
*(*(a + i) + j) // 指針解引用等價
*(a[i] + j) // 行指針 + 列偏移
int cube[2][3][4]; // 2層 × 3行 × 4列 = 24元素
cube[layer][row][col] // 邏輯結構
// 內存仍線性:layer主序 → row → col
⚠️ 維度過高 (>3) 代碼複雜度激增,建議扁平化為一維數組 + 索引計算:idx = (l*R + r)*C + c。
| 形式 | 定義 | 內存結構 | 修改性 |
|---|---|---|---|
| 二維字符數組 | char strs[10][20] | 連續塊,每行固定 20 字節 | 可修改內容 |
| 指針數組 | char *strs[10] | 指針數組 + 字符串字面量/堆內存 | 字面量不可修改 |
scanf vs gets vs fgets
// ❌ scanf 停於空白
char s[20];
scanf("%s", s); // 輸入 "hello world" → 只讀 "hello"
// ❌ gets 不安全 (已移除 C11),無緩衝區檢查
gets(s); // 危險!
// ✅ fgets 安全標準
fgets(s, sizeof(s), stdin); // 讀整行含換行符
// 移除換行符
s[strcspn(s, "\n")] = '\0';
\0"hello" 編譯器自動添加 \0。strlen 計數不含 \0,sizeof 含 \0。\0 結尾。string.h)| 函數 | 功能 | 返回值 | 注意 |
|---|---|---|---|
strlen(s) | 長度 (不含\0) | size_t | O(n) |
strcpy(dst, src) | 複製 | dst | 目標需足夠大,無長度檢查 |
strncpy(dst, src, n) | 複製前 n 字符 | dst | 若 src< n,補\0;否則不加\0 |
strcat(dst, src) | 追加 | dst | 目標需足夠大 |
strcmp(s1, s2) | 字典序比較 | <0,=0,>0 | 按 ASCII 值 |
strncmp(s1, s2, n) | 比較前 n 字符 | <0,=0,>0 | |
strchr(s, c) | 查找字符首次出現 | 指針/NULL | |
strstr(hay, needle) | 查找子串 | 指針/NULL |
#include
#include
#include
int cmp_str(const void *a, const void *b) {
return strcmp(*(const char**)a, *(const char**)b);
}
int main() {
char *names[] = {"Charlie", "Alice", "Bob", "David"};
int n = sizeof(names)/sizeof(names[0]);
qsort(names, n, sizeof(char*), cmp_str);
for (int i = 0; i < n; i++) puts(names[i]);
// Alice, Bob, Charlie, David
return 0;
}
char **read_lines(int *count) {
char **lines = NULL;
char buf[1024];
*count = 0;
while (fgets(buf, sizeof(buf), stdin)) {
buf[strcspn(buf, "\n")] = '\0';
lines = realloc(lines, (*count + 1) * sizeof(char*));
lines[*count] = strdup(buf); // strdup = malloc + strcpy
(*count)++;
}
return lines;
}
void free_lines(char **lines, int count) {
for (int i = 0; i < count; i++) free(lines[i]);
free(lines);
}
scanf("%s", s) 無長度限制 → 緩衝區溢出。用 fgets 或 scanf("%19s", s)。char *p = "abc"; p[0]='x'; → 崩潰。用數組 char p[] = "abc";。strcpy 目標空間不足 → 溢出。用 strncpy/snprintf 或動態分配。\0 結尾 → strlen/printf 越界讀取。malloc。多維數組按行優先連續存儲,指針算術自動縮放。字符串數組本質是指針數組,配合 string.h 標準函數高效處理。牢記 \0 結尾約定,優先使用安全函數 (fgets, strncpy, snprintf),動態場景採用指針數組 + 堆分配。掌握這些,字符串處理不再是痛點。