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

C 語言遞歸計算字符串長度:指針判斷條件與 scanf 參數錯誤修正

     編輯:程式設計疑難解答

遞歸實現 strlen 時,兩個關鍵錯誤:遞歸終止條件判斷指針本身而非指向字符,以及 scanf 讀取字符串時錯誤使用 &s。

原始錯誤代碼

int leng(char *s) {
    if (s)                 // 錯誤:判斷指針是否為 NULL,而非字符是否為 '\0'
        return leng(s+1) + 1;
    return 0;
}

void main() {
    char s[100];
    scanf("%s", &s);       // 錯誤:&s 是 char(*)[100] 類型,不匹配 %s 期望的 char*
    int l = leng(s);
    printf("%d", l);
}

問題分析

  1. 遞歸基準錯誤:if (s) 檢查指針 s 是否非空。字符串結束標誌是 '\0'(即 *s == 0),而非指針變為 NULL。傳入 s+1 只會移動指針,永遠不會變成 NULL,導致無限遞歸訪問越界內存直到崩潰。
  2. scanf 參數類型不匹配:s 是數組名,本身已表示首元素地址(類型 char*)。&s 類型是 char(*)[100](指向整個數組的指針),雖然數值相同但類型不同,嚴格編譯器會警告,且語義不正確。

修正代碼

#include <stdio.h>

int leng(char *s) {
    if (*s)                // 正確:判斷當前字符是否非 '\0'
        return leng(s + 1) + 1;
    return 0;
}

int main() {
    char s[100];
    scanf("%s", s);        // 正確:直接用數組名 s
    int l = leng(s);
    printf("%d\n", l);
    return 0;
}

遞歸執行流程以 "abc" 為例

  1. leng("abc"):*'a' != 0 → leng("bc") + 1
  2. leng("bc"):*'b' != 0 → leng("c") + 1
  3. leng("c"):*'c' != 0 → leng("") + 1
  4. leng(""):*'\0' == 0 → 返回 0
  5. 層層返回:0+1+1+1 = 3

優化:尾遞歸與迭代版本

遞歸版本雖簡潔但有棧溢出風險(極長字符串)。尾遞歸優化需編譯器支援,通用做法用迴圈:

int strlen_iter(const char *s) {
    int len = 0;
    while (*s++) len++;
    return len;
}

標準庫 strlen 的實現技巧

現代 libc 多用字對齊 + SIMD 指令一次檢測多字節,極大提升性能,遠快於逐字節循環。

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