首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計疑難解答

C 語言字符串數組輸入排序輸出:動態內存分配與 gets 棄用指南

     編輯:程式設計疑難解答

C 語言處理字符串數組輸入排序是經典練習,但 gets() 不安全、未分配內存直接寫入導致崩潰是新手雙重陷阱。本文提供安全、標準的完整實現。

原代碼三大致命錯誤

  1. 未為字符串分配內存:char *name[5] 僅分配 5 個指針,指向隨機地址
  2. 使用棄用的 gets():無緩衝區長度檢查,極易緩衝區溢出,C11 標準已移除
  3. input() 邏輯錯:gets(name) 嘗試向指針數組首地址寫入,而非逐個字符串

正確完整實現


#include 
#include 
#include 

#define MAX_NAMES 5
#define MAX_LEN 100

void input(char *names[], int n) {
    for (int i = 0; i < n; i++) {
        // 1. 為每個字符串分配堆內存
        names[i] = (char *)malloc(MAX_LEN * sizeof(char));
        if (!names[i]) {
            fprintf(stderr, "內存分配失敗\n");
            exit(1);
        }
        // 2. 使用 fgets 安全讀取 (包含換行符)
        printf("請輸入第 %d 個字符串: ", i + 1);
        if (fgets(names[i], MAX_LEN, stdin) == NULL) {
            names[i][0] = '\0';
        } else {
            // 3. 移除末尾換行符
            size_t len = strlen(names[i]);
            if (len > 0 && names[i][len - 1] == '\n') {
                names[i][len - 1] = '\0';
            }
        }
    }
}

void sort(char *names[], int n) {
    for (int i = 0; i < n - 1; i++) {
        int k = i;
        for (int j = i + 1; j < n; j++) {
            if (strcmp(names[k], names[j]) > 0) { // 字典序升序
                k = j;
            }
        }
        if (k != i) {
            char *temp = names[i];
            names[i] = names[k];
            names[k] = temp;
        }
    }
}

void print(char *names[], int n) {
    printf("\n排序結果:\n");
    for (int i = 0; i < n; i++) {
        printf("%s\n", names[i]);
    }
}

void freeNames(char *names[], int n) {
    for (int i = 0; i < n; i++) {
        free(names[i]); // 釋放每個字符串內存
        names[i] = NULL;
    }
}

int main() {
    char *names[MAX_NAMES] = {NULL};
    
    input(names, MAX_NAMES);
    sort(names, MAX_NAMES);
    print(names, MAX_NAMES);
    freeNames(names, MAX_NAMES); // 關鍵:釋放內存
    
    return 0;
}

關鍵點解析

環節錯誤做法正確做法原因
內存分配無分配malloc 為每串分配指針需指向有效內存
輸入函數gets()fgets(buf, size, stdin)防緩衝區溢出,C11 標準
換行符處理忽略檢查並替換 \n 為 \0fgets 保留換行符
排序比較直接比較指針strcmp 比較內容指針地址無序關係
內存釋放無循環 free()防內存洩漏

進階優化:動態擴容


// 使用 realloc 支持任意長度輸入
char **names = NULL;
int capacity = 0, count = 0;
char line[MAX_LEN];

while (fgets(line, MAX_LEN, stdin)) {
    if (count >= capacity) {
        capacity = capacity ? capacity * 2 : 4;
        names = realloc(names, capacity * sizeof(char*));
    }
    line[strcspn(line, "\n")] = '\0'; // 移除換行
    names[count] = strdup(line); // 分配並複製
    count++;
}
// 排序、打印...
for (int i = 0; i < count; i++) free(names[i]);
free(names);

掌握 malloc/fgets/strcmp/free 組合拳,是 C 語言字符串處理的基本功。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved