目次
1. 前言
數值的進位(基數)是什麼
在電腦世界中,數值以各種基數(進位)表示。我們日常使用的是十進位,但在 C 語言中,還廣泛使用十六進位、二進位、八進位等。特別是十六進位,常出現在記憶體位址、位元運算、嵌入式系統、顏色代碼的指定等情況。 例如,顏色代碼「#FFFFFF」是以十六進位表示的值,轉換成十進位後為「16777215」。因此,正確理解基數的轉換對於使用 C 語言非常重要。本文的目的
本文將以易於理解的方式說明在 C 語言中,從十進位轉換為十六進位,以及從十六進位轉換為十進位的方法。內容涵蓋從基礎知識到實作範例程式碼,讓初學者也能立即應用。2. C 語言將十進位轉換為十六進位的方法
使用 printf 函式的方法
C 語言中,使用printf
函式即可輕鬆將十進位轉換為十六進位並顯示。基本範例
#include <stdio.h>
int main() {
int number = 255; // 十進位
printf("%xn", number); // 小寫十六進位
printf("%Xn", number); // 大寫十六進位
return 0;
}
說明
%x
: 小寫十六進位表示%X
: 大寫十六進位表示
number = 255
時,輸出如下。%x
:ff
%X
:FF
對齊位數的方法
透過在格式指定子中指定位數,即可以固定位數顯示十六進位。#include <stdio.h>
int main() {
int number = 255;
printf("%04xn", number); // 以 4 位顯示
return 0;
}
輸出: 00ff
在前面加上 0,即使位數不足也能保持對齊的外觀。使用 sprintf 函式的方法
取代printf
函式,使用 sprintf
函式可將轉換結果存入字串。基本範例
#include <stdio.h>
int main() {
int number = 255;
char buffer[10];
sprintf(buffer, "%x", number);
printf("16進数: %sn", buffer); // 以字串形式輸出
return 0;
}
說明
buffer
會儲存十六進位的字串,之後可再次使用或傳遞給其他處理。藉此可製作更具彈性的程式。手動轉換(使用位元運算)
說明使用位元運算手動將十進位轉換為十六進位的方法。此方式有助於加深對進位轉換的理解。實例程式碼
#include <stdio.h>
#include <string.h>
int main() {
int number = 255;
char hex[10];
int i = 0;
while (number > 0) {
int remainder = number % 16;
hex[i++] = (remainder < 10) ? '0' + remainder : 'A' + (remainder - 10);
number /= 16;
}
hex[i] = '�';
// 反轉字串
for (int j = 0; j < i / 2; j++) {
char temp = hex[j];
hex[j] = hex[i - j - 1];
hex[i - j - 1] = temp;
}
printf("16進数: %sn", hex);
return 0;
}
說明
- 使用
number % 16
計算餘數,並將其轉換為對應的十六進位字元。 - 使用
number /= 16
更新商,以計算下一位。 - 最後將字串反轉,以正確順序輸出。
3. C語言將十六進位轉換為十進位的方法
使用 scanf 函式的方法
scanf
函式可以直接將十六進位的值讀取為十進位。基本範例
#include <stdio.h>
int main() {
int number;
printf("請輸入十六進位: ");
scanf("%x", &number); // 以十六進位輸入接收
printf("十進位: %dn", number); // 以十進位顯示
return 0;
}
說明
- 使用格式指定子
%x
可以接受十六進位輸入。 - 輸入的值會被轉換為十進位,並儲存於變數
number
中。 - 使用
printf
函式的%d
來顯示十進位的值。
執行範例
輸入:FF
輸出: 十進位: 255
注意事項
- 使用者輸入的值必須是十六進位格式(例如:
FF
、1A3
)。 - 即使在前面加上「0x」也能正常處理(例如:
0xFF
)。
使用 strtol 函式的方法
strtol
函式是一個可以指定基數將字串轉換為數值的便利函式。基本範例
#include <stdio.h>
#include <stdlib.h>
int main() {
char hexString[] = "FF"; // 十六進位字串
long number = strtol(hexString, NULL, 16); // 指定基數 16 進行轉換
printf("十進位: %ldn", number);
return 0;
}
說明
- 在
strtol
函式的第1個參數中,指定要轉換的字串(此處為hexString
)。 - 第2個參數是指向轉換後字串結尾的指標,這裡因未使用所以指定為
NULL
。 - 在第3個參數指定基數(此處為 16),即可將十六進位轉換為十進位。
執行範例
輸入:"FF"
輸出: 十進位: 255
包含錯誤處理的 strtol 使用方法
含錯誤處理的範例
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
int main() {
char hexString[] = "ZZZ"; // 無效的十六進位
char *endptr;
errno = 0; // 初始化錯誤
long number = strtol(hexString, &endptr, 16);
if (errno != 0 || *endptr != '�') {
printf("無效的輸入。n");
} else {
printf("十進位: %ldn", number);
}
return 0;
}
說明
endptr
指向轉換結束的位置。如果有未被轉換的字元,*endptr
就不會是'�'
。- 檢查
errno
可以偵測到溢位或其他錯誤。 - 若偵測到無效的輸入,則顯示錯誤訊息。
執行範例
輸入:"ZZZ"
輸出: 無效的輸入。
手動轉換方法
實例程式碼
#include <stdio.h>
#include <string.h>
#include <math.h>
int main() {
char hexString[] = "FF";
int length = strlen(hexString);
int decimal = 0;
for (int i = 0; i < length; i++) {
char digit = hexString[i];
int value;
if (digit >= '0' && digit <= '9') {
value = digit - '0';
} else if (digit >= 'A' && digit <= 'F') {
value = digit - 'A' + 10;
} else if (digit >= 'a' && digit <= 'f') {
value = digit - 'a' + 10;
} else {
printf("無效的字元。n");
return 1;
}
decimal += value * pow(16, length - i - 1);
}
printf("十進位: %dn", decimal);
return 0;
}
說明
- 逐一解析每個字元,將其轉換為對應的十進位值。
- 將位權(16 的次方)相乘後加總。
執行範例
輸入:"FF"
輸出: 十進位: 255
4. 實作範例程式碼
雙向轉換程式
程式概述
此程式可讓使用者選擇以下操作。- 十進制轉十六進制
- 十六進制轉十進制
程式碼範例
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
void decimalToHexadecimal() {
int decimal;
printf("請輸入十進制數字: ");
scanf("%d", &decimal);
printf("十六進制: %Xn", decimal);
}
void hexadecimalToDecimal() {
char hex[20];
printf("請輸入十六進制數字: ");
scanf("%s", hex);
// 檢查輸入字串的有效性
for (int i = 0; i < strlen(hex); i++) {
if (!isxdigit(hex[i])) {
printf("無效的十六進位數字。n");
return;
}
}
int decimal = (int)strtol(hex, NULL, 16);
printf("十進制: %dn", decimal);
}
int main() {
int choice;
while (1) {
printf("n請選擇轉換選項:n");
printf("1. 十進制轉十六進制n");
printf("2. 十六進制轉十進制n");
printf("3. 結束n");
printf("選擇: ");
scanf("%d", &choice);
switch (choice) {
case 1:
decimalToHexadecimal();
break;
case 2:
hexadecimalToDecimal();
break;
case 3:
printf("程式結束。n");
return 0;
default:
printf("無效的選擇。請再輸入一次。n");
}
}
return 0;
}
執行範例
案例1:十進制轉十六進制請選擇轉換選項:
1. 十進制轉十六進制
2. 十六進制轉十進制
3. 結束
選擇: 1
請輸入十進制數字: 255
十六進制: FF
案例2:十六進制轉十進制請選擇轉換選項:
1. 十進制轉十六進制
2. 十六進制轉十進制
3. 結束
選擇: 2
請輸入十六進制數字: FF
十進制: 255
案例3:無效的十六進制輸入請選擇轉換選項:
1. 十進制轉十六進制
2. 十六進制轉十進制
3. 結束
選擇: 2
請輸入十六進制數字: ZZZ
無效的十六進位數字。
錯誤處理要點
對無效輸入的對策
- 檢查十六進制輸入的有效性:
- 使用
isxdigit
函式,確認每個字元是否為有效的十六進位字元(0-9, A-F, a-f)。
- 十進制輸入的錯誤處理:
- 若輸入非數字,顯示錯誤訊息並提示重新輸入。
防止無限迴圈
如果程式未明確設定結束條件,可能會產生無限迴圈。本程式透過選項「3」正確結束。程式擴充建議
加入以下功能,可將程式擴充為更便利的工具。- 二進制與八進制的轉換功能
- 新增可選擇進位的選單。
- 指定位數以格式化轉換結果
- 加入以固定位數格式化輸出的選項。
- 記錄至日誌檔案
- 將轉換結果保存為檔案日誌。
總結
此範例程式提供十進制與十六進制的相互轉換,操作簡易。支援使用者輸入並考慮錯誤處理,讓初學者也能安心使用。
5. 注意點與最佳實踐
使用格式指定子的注意事項
對齊位數的輸出
printf
函式輸出十六進位時,透過適當設定格式指定子可以對齊位數或在前面補零。#include <stdio.h>
int main() {
int number = 255;
printf("4位的十六進位: %04Xn", number); // 輸出: 00FF
return 0;
}
%04X
: 輸出4位的大寫十六進位,不足的位元以0填補。- 使用此格式可使格式對齊,實現易於閱讀的輸出。
大寫與小寫的選擇
十六進位的輸出可使用大寫(%X
)或小寫(%x
)兩種形式。依需求切換,可得到符合外觀或用途的彈性輸出。輸入值的驗證
十進位的輸入
使用者可能輸入無效值,加入錯誤處理可提升程式的可靠性。#include <stdio.h>
int main() {
int number;
printf("請輸入十進位: ");
if (scanf("%d", &number) != 1) {
printf("無效的輸入。n");
return 1;
}
printf("輸入的值: %dn", number);
return 0;
}
十六進位的輸入
在接收十六進位字串作為輸入時,驗證輸入值是否有效非常重要。#include <ctype.h>
#include <stdio.h>
#include <string.h>
int isValidHex(const char *hex) {
for (int i = 0; i < strlen(hex); i++) {
if (!isxdigit(hex[i])) {
return 0; // 含有無效字元
}
}
return 1; // 有效的十六進位
}
int main() {
char hex[20];
printf("請輸入十六進位: ");
scanf("%s", hex);
if (!isValidHex(hex)) {
printf("無效的十六進位。n");
return 1;
}
printf("輸入的十六進位是有效的。n");
return 0;
}
負數與溢位的處理
負數的處理
處理負數時,取決於有號型別(int
或long
)。在十六進位輸出負數時,內部使用二的補數表示。#include <stdio.h>
int main() {
int number = -255;
printf("十六進位(負數): %Xn", number); // 輸出為二的補數表示
return 0;
}
避免溢位
處理大數值時,需要注意不要超過型別上限。C 語言可透過以下標頭檔確認型別範圍。#include <limits.h>
#include <stdio.h>
int main() {
printf("int 的最大值: %dn", INT_MAX);
printf("int 的最小值: %dn", INT_MIN);
return 0;
}
選擇適當的型別可降低溢位風險。例如,處理極大數值時,建議使用 long long
型別。提升可讀性與維護性的技巧
註解與命名規則
- 為函式與變數命名有意義的名稱,並適當加入註解,可提升程式碼的可讀性。
善用標準函式
- 手動的基數轉換對學習有益,但在實務上,優先使用標準函式(
printf
、strtol
等)可提升程式碼的可維護性。
程式測試
測試案例的重要性
製作基數轉換程式時,測試以下案例非常重要。- 正常的輸入(例:十進位
255
→ 十六進位FF
) - 無效的輸入(例:將字串
ABC
作為十進位輸入) - 邊界值(例:最大值
INT_MAX
、最小值INT_MIN
) - 負數或零的輸入
6. FAQ(常見問題)
printf函式在十六進位輸出前加上「0x」要怎麼做?
解答:
先在前面加上「0x」,需要在格式指定子前明確地加入「0x」字串。程式範例:
#include <stdio.h>
int main() {
int number = 255;
printf("十六進位(含0x): 0xXn", number); // 輸出: 0xFF
return 0;
}
補充說明:
「0x」是表示十六進位的標準前綴。例如,在處理顏色代碼或記憶體位址時常會使用。使用 strtol 函式嘗試轉換無效字串會發生什麼情況?</3>
解答:
strtol
函式即使字串無效也不會拋出錯誤,而是只轉換可處理的部分。當出現無法轉換的字元時,會忽略其後的字串。程式範例:
#include <stdio.h>
#include <stdlib.h>
int main() {
char hexString[] = "FFG12";
char *endptr;
long number = strtol(hexString, &endptr, 16);
printf("轉換後的值: %ldn", number);
printf("無法轉換的部分: %sn", endptr); // 輸出: G12
return 0;
}
輸出範例:
轉換後的值: 255
無法轉換的部分: G12
不使用 printf 函式將十進位轉換為十進位要怎麼做?
解答:
可以使用位元運算手動轉換。此方法有助於了解進位轉換的內部邏輯。程式範例:
#include <stdio.h>
void decimalToHex(int decimal) {
char hex[20];
int index = 0;
while (decimal > 0) {
int remainder = decimal % 16;
hex[index++] = (remainder < 10) ? '0' + remainder : 'A' + (remainder - 10);
decimal /= 16;
}
printf("十位: ");
for (int i = index - 1; i >= 0; i--) {
printf("%c", hex[i]);
}
printf("n");
}
int main() {
int number = 255;
decimalToHex(number);
return 0;
}
使用 scanf 函式限制位數以接收輸入要怎麼做?
解答:
scanf
函式的格式指定子指定位數即可限制輸入字元數。程式範例:
#include <stdio.h>
int main() {
char hex[5]; // 接收最多4位的輸入
printf("請輸入最多4位的十六進位數: ");
scanf("%4s", hex);
printf("輸入的值: %sn", hex);
return 0;
}
補充說明:
格式指定子%4s
設定為最多接受4個字元的字串輸入。其他進位(例如:二進位或八進位)的轉換?
解答:
使用printf
函式即可進行其他進位的轉換。依據進位使用適當的格式指定子或邏輯。程式範例:二進位轉換
#include <stdio.h>
void decimalToBinary(int decimal) {
char binary[32];
int index = 0;
while (decimal > 0) {
binary[index++] = (decimal % 2) + '0';
decimal /= 2;
}
printf("二進位: ");
for (int i = index - 1 i >= 0; i--) {
printf("%c", binary[i]);
}
printf("n");
}
int main() int number = 255;
decimalToBinary(number);
return 0;
}
將大寫十六進位轉換為小寫要怎麼做?
解答:
使用 C 語言標準函式庫中的tolower
函式即可將大寫十六進位轉換為小寫。程式範例:
#include <stdio.h>
#include <ctype.h>
#include <string.h>
void toLowercase(char *hex) {
for (int i = 0; i < strlen(hex); i++) {
hex[i] = tolower(hex[i]);
}
}
int main() {
char hex[] = "FF";
toLowercase(hex);
printf("小寫的十六進位: %sn", hex);
return 0;
}
輸出範例:
小寫的十六進位: ff
要以零填充的十六進位格式輸出要怎麼做?
解答:
使用printf
函式的格式指定子指定位數即可以零填充形式輸出。程式範例:
#include <stdio.h>
int main() {
int number = 15;
printf("零填充4位的十六進位: %04Xn", number); // 輸出: 000F
return 0;
}
7. 總結
在本文中,我們全面說明了使用 C 語言進行十進制與十六進制相互轉換的基礎、實作範例程式碼、注意事項與 FAQ。以下回顧重要重點。文章要點
基數(進位制)的基本概念
- 十進制是我們日常使用的數字表示方式,十六進制則常用於特定用途(例如:記憶體位址或顏色代碼)。
- 在 C 語言中,提供了靈活的方式來以各種進位制處理數值。
從十進制轉換為十六進制
- 使用
printf
或sprintf
函式,即可簡單且高效地進行轉換。 - 也介紹了利用位元運算的手動轉換方法,這對於理解進位制轉換的邏輯很有幫助。
從十六進制轉換為十進制
- 使用
scanf
或strtol
函式,可將字串形式的十六進制轉換為十進制。 - 加入對無效輸入與錯誤處理,可製作更穩健的程式。
實作範例程式
- 透過雙向轉換程式,處理使用者輸入,實現十進制與十六進制的相互轉換。
- 說明了加入錯誤處理以應對錯誤輸入的方法。
注意事項與最佳實踐
- 說明了格式指定子的使用方式、大小寫的選擇等,如何調整輸出的外觀。
- 提醒注意負數與溢位,並強調徹底檢查型別選擇與範圍的重要性。
常見問題(FAQ)
- 針對實務疑問(例如:在
printf
中加上「0x」的方法、無效輸入的處理方式),提供具體範例說明。 - 也提及了向其他進位制(二進制或八進制)應用的方法。
閱讀本文可獲得的收穫
閱讀本文後,讀者將學會以下內容並能實作。- C 語言中基數轉換的基本概念與應用
- 使用可執行程式碼實作進位制轉換
- 包含輸入驗證與錯誤處理的穩健程式開發
未來學習的建議
為了進一步深化理解,建議學習以下內容。- 其他進位制(二進制與八進制)的轉換方法
- 在非 C 語言的程式語言中實作基數轉換
- 與記憶體管理及二進位操作相關的知識