首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

C語言手寫 itoa:整數轉字串遞迴與迭代實作對比

     編輯:關於C語言

C語言手寫 itoa:整數轉字串遞迴與迭代實作對比

itoa (Integer to ASCII) 將整數轉為字串表示。雖非標準 C 庫函數(標準用 sprintf 或 snprintf),但手寫實作是理解「位權分解」、「遞迴展開順序」、「字串構建」的經典練習。本文對比遞迴版、迭代版、負數處理、緩衝區安全、基數擴展實作。

遞迴版(教學經典)

#include <stdio.h>

static int idx = 0;  // 全域索引 (教學用,非執行緒安全)

void itoa_recursive(int n, char s[]) {
    if (n < 0) {          // 處理負數
        s[idx++] = '-';
        n = -n;           // 注意 INT_MIN 溢位
    }
    if (n / 10) {         // 遞迴處理高位
        itoa_recursive(n / 10, s);
    }
    s[idx++] = (n % 10) + '0';  // 當前位轉字符
    s[idx] = '\0';              // 結束符
}

int main() {
    char s[20];
    int num = -12345;
    idx = 0;
    itoa_recursive(num, s);
    printf("%s\n", s);  // -12345
    return 0;
}

遞迴執行流程圖解

itoa(-12345)
  → s[0]='-', n=12345
  → itoa(1234)
      → itoa(123)
          → itoa(12)
              → itoa(1)
                  → n/10=0, 不遞迴
                  → s[1]='1'
              → s[2]='2'
          → s[3]='3'
      → s[4]='4'
  → s[5]='5'
  → s[6]='\0'
結果: "-12345"

迭代版(生產環境推薦)

#include <stdio.h>
#include <string.h>

void itoa_iterative(int n, char s[]) {
    int i = 0;
    bool negative = false;

    if (n == 0) { s[i++] = '0'; s[i] = '\0'; return; }

    if (n < 0) {
        negative = true;
        n = -n;  // INT_MIN 仍有溢位風險
    }

    // 從低位到高位存入
    while (n > 0) {
        s[i++] = (n % 10) + '0';
        n /= 10;
    }

    if (negative) s[i++] = '-';

    s[i] = '\0';

    // 反轉字串 (低位在前 → 高位在前)
    for (int left = 0, right = i - 1; left < right; left++, right--) {
        char tmp = s[left];
        s[left] = s[right];
        s[right] = tmp;
    }
}

安全版:緩衝區長度檢查 + INT_MIN 處理

#include <limits.h>
#include <stdbool.h>

// 回傳寫入字元數 (不含 \0),負值表示錯誤
int itoa_safe(int n, char *buf, size_t bufSize) {
    if (!buf || bufSize == 0) return -1;

    // 特殊處理 INT_MIN:-2147483648
    if (n == INT_MIN) {
        const char *minStr = "-2147483648";
        size_t len = strlen(minStr);
        if (bufSize <= len) return -2;  // 緩衝區太小
        strcpy(buf, minStr);
        return len;
    }

    int i = 0;
    bool neg = false;
    if (n < 0) { neg = true; n = -n; }

    // 計算所需位數 (含符號)
    int temp = n;
    int digits = 1;
    while (temp >= 10) { temp /= 10; digits++; }
    if (neg) digits++;

    if (bufSize <= digits) return -2;  // 空間不足

    // 寫入數字 (低位在前)
    do {
        buf[i++] = (n % 10) + '0';
        n /= 10;
    } while (n > 0);

    if (neg) buf[i++] = '-';
    buf[i] = '\0';

    // 反轉
    for (int l = 0, r = i - 1; l < r; l++, r--) {
        char t = buf[l]; buf[l] = buf[r]; buf[r] = t;
    }

    return i;
}

進階:任意基數 (2-36) 轉換

const char *digits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";

void itoa_base(int n, char *buf, int base) {
    if (base < 2 || base > 36) { *buf = '\0'; return; }

    int i = 0;
    bool neg = false;
    if (n < 0 && base == 10) { neg = true; n = -n; }

    do {
        buf[i++] = digits[n % base];
        n /= base;
    } while (n > 0);

    if (neg) buf[i++] = '-';
    buf[i] = '\0';

    // 反轉
    for (int l = 0, r = i - 1; l < r; l++, r--) {
        char t = buf[l]; buf[l] = buf[r]; buf[r] = t;
    }
}

三版本比較

維度遞迴版迭代版安全版
可讀性高 (符合數學定義)中低
執行效率函數呼叫開銷最快略慢 (檢查)
棧空間O(log n)O(1)O(1)
執行緒安全否 (全域 idx)是是
緩衝區保護無無完整
INT_MIN 處理錯誤錯誤正確
適用場景教學、面試一般用途庫函數、生產代碼

標準庫替代方案

// 推薦:snprintf (C99 標準、緩衝區安全、支援所有型別)
char buf[32];
snprintf(buf, sizeof(buf), "%d", -12345);  // "-12345"

// 任意基數:無標準函數,需手寫或用第三方庫

手寫 itoa 能深入理解「除基取餘得低位、反序輸出得正確順序」的核心邏輯,以及遞迴與迭代的時空權衡。建議實作安全版並納入個人工具庫,同時熟練使用 snprintf 解決實際開發需求。

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