本文提供一個 C++ 函數 num_to_str,可將 long 型整數轉換為任意進制 (2~36) 的字串表示。功能特色包括:
+,負數前綴 -。0 前綴,十六進制加 0x 或 0X。# 編譯
g++ -g -W -Wall -Wextra -o mytest main.cpp
# 執行
./mytest
// 2011年 11月 14日 星期一 09:46:47 CST
// author: 李小丹(Li Shao Dan) 字 殊恆(shuheng)
// K.I.S.S
// S.P.O.T
#include <iostream>
using namespace std;
#define LOW_CASE_NUM 0
#define UP_CASE_NUM 1
#define MAX_STR_SIZE 128
char *num_to_str(long, int, int, char *, size_t);
int main() {
char buf[MAX_STR_SIZE];
char *p;
// 輸出:16進制,小寫
if ((p = num_to_str(333, 16, LOW_CASE_NUM, buf, sizeof(buf))))
cout << p << endl;
// 輸出:16進制,大寫
if ((p = num_to_str(-333, 16, UP_CASE_NUM, buf, sizeof(buf))))
cout << p << endl;
// 輸出:8進制
if ((p = num_to_str(333, 8, LOW_CASE_NUM, buf, sizeof(buf))))
cout << p << endl;
// 輸出:2進制
if ((p = num_to_str(-333, 2, LOW_CASE_NUM, buf, sizeof(buf))))
cout << p << endl;
// 輸出:10進制
if ((p = num_to_str(-333, 10, LOW_CASE_NUM, buf, sizeof(buf))))
cout << p << endl;
return 0;
}
// 輔助函數:執行除法並回傳餘數
inline static long num_div(long &c, int b) {
long r = c % b;
c /= b;
return r;
}
// 核心轉換函數
// num: 輸入數值
// base: 目標進制 (2~36)
// cs: 字母大小寫 (0=大寫, 1=小寫)
// buf: 輸出緩衝區
// s: 緩衝區大小
// 回傳: 成功指向 buf,失敗回傳 0
char *num_to_str(long num, int base, int cs, char *buf, size_t s) {
if (base < 2 || base > 36)
return 0;
const char *ln = "0123456789abcdefghijklmnopqrstuvwxyz";
const char *un = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
const char *n = cs ? ln : un;
// 處理正負號
char sg = num < 0 ? (num = -num, '-') : '+';
char tmp[MAX_STR_SIZE];
int i = 0;
tmp[i++] = 0; // 佔位,稍後放入符號
// 將數值轉為對應進制字元 (逆序存入 tmp)
if (!num)
tmp[i++] = '0';
else
while (num) tmp[i++] = n[num_div(num, base)];
// 加入進制前綴
switch (base) {
case 16:
tmp[i++] = n[33]; // 'x' 或 'X'
case 8:
tmp[i++] = '0';
break;
}
// 放入正負號
tmp[i] = sg;
// 檢查緩衝區是否足夠
if (i > (int)s) return 0;
// 反轉字串寫入 buf (tmp 目前是逆序 + 符號在尾)
for (int j = 0; i >= 0; ++j, --i)
buf[j] = tmp[i];
return buf;
}
cs 參數選擇大寫或小寫字母表。-,正數記錄 +。num_div 反覆取餘數,將字元存入暫存陣列 tmp (此時為低位在前)。switch 的貫穿特性,為 16 進制加 x/X,8 進制加 0。tmp 逆序複製到 buf,完成字串組裝。+0x14d
-0x14d
+0515
-101001101
-333