字串操作是 C 語言基礎訓練核心項目。本文實作一個簡單函式:將字串 s2 插入到字串 s1 的**最前端**,並分析緩衝區安全、指標運算與標準庫替代方案。
len1 = strlen(s1)、len2 = strlen(s2)len1 + len2 + 1s1 內容騰出前 len2 空間s2 複製到開頭'\0'#include <stdio.h>
#include <string.h>
/* 將 s2 插入 s1 最前端,s1 必須有足夠空間 */
void insert_front(char *s1, const char *s2) {
size_t len1 = strlen(s1);
size_t len2 = strlen(s2);
/* 從後往前搬移 s1,避免覆蓋 */
for (size_t i = len1; i != (size_t)-1; --i) {
s1[i + len2] = s1[i]; /* 含結尾 '\0' */
}
/* 複製 s2 到開頭 */
for (size_t i = 0; i < len2; ++i) {
s1[i] = s2[i];
}
}
int main(void) {
char s1[100] = "World";
char s2[50];
printf("請輸入要插入的字串: ");
if (fgets(s2, sizeof(s2), stdin)) {
/* 移除 fgets 讀入的換行符 */
s2[strcspn(s2, "\n")] = '\0';
insert_front(s1, s2);
printf("結果: %s\n", s1);
}
return 0;
}
| 原碼問題 | 修正 |
|---|---|
gets() 不安全,已被 C11 移除 | 改用 fgets() + strcspn 去換行 |
函式回傳區域陣列指標 return s3; | 改為 void 直接在 s1 上操作 (呼叫端負責空間) |
| 迴圈邏輯錯誤:先複製 s2 再搬移 s1 會覆蓋 | **先搬移 s1 (從後往前),再寫入 s2** |
| 未檢查緩衝區容量 | 實務中應傳入 size_t capacity 並斷言 |
/* memmove 版:更簡潔、優化過 */
void insert_front_std(char *s1, const char *s2) {
size_t len1 = strlen(s1);
size_t len2 = strlen(s2);
memmove(s1 + len2, s1, len1 + 1); /* 含 '\0' 向後搬移 */
memcpy(s1, s2, len2); /* 寫入開頭 */
}
/* C++ std::string 版:安全、直觀 */
#include <string>
std::string insert_front_cpp(std::string s1, const std::string& s2) {
return s2 + s1;
}
/* 在 s1 的 pos 位置插入 s2 (0 ≤ pos ≤ len1) */
void insert_at(char *s1, const char *s2, size_t pos) {
size_t len1 = strlen(s1);
size_t len2 = strlen(s2);
if (pos > len1) pos = len1; /* 邊界修正 */
memmove(s1 + pos + len2, s1 + pos, len1 - pos + 1);
memcpy(s1 + pos, s2, len2);
}
memmove/memcpy 或 C++ std::stringgets()、strcat() 等不安全函式