在 C 語言中自由轉換十進位與十六進位!新手完整教學

目次

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;
}

說明

  1. 使用 number % 16 計算餘數,並將其轉換為對應的十六進位字元。
  2. 使用 number /= 16 更新商,以計算下一位。
  3. 最後將字串反轉,以正確順序輸出。
此程式碼示範了手動進行基數轉換的基本方法。
年収訴求

3. C語言將十六進位轉換為十進位的方法

使用 scanf 函式的方法

scanf 函式可以直接將十六進位的值讀取為十進位。

基本範例

#include <stdio.h>

int main() {
    int number;
    printf("請輸入十六進位: ");
    scanf("%x", &number); // 以十六進位輸入接收
    printf("十進位: %dn", number); // 以十進位顯示
    return 0;
}

說明

  1. 使用格式指定子 %x 可以接受十六進位輸入。
  2. 輸入的值會被轉換為十進位,並儲存於變數 number 中。
  3. 使用 printf 函式的 %d 來顯示十進位的值。

執行範例

輸入: FF 輸出: 十進位: 255

注意事項

  • 使用者輸入的值必須是十六進位格式(例如:FF1A3)。
  • 即使在前面加上「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;
}

說明

  1. strtol 函式的第1個參數中,指定要轉換的字串(此處為 hexString)。
  2. 第2個參數是指向轉換後字串結尾的指標,這裡因未使用所以指定為 NULL
  3. 在第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;
}

說明

  1. endptr 指向轉換結束的位置。如果有未被轉換的字元,*endptr 就不會是 '�'
  2. 檢查 errno 可以偵測到溢位或其他錯誤。
  3. 若偵測到無效的輸入,則顯示錯誤訊息。

執行範例

輸入: "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;
}

說明

  1. 逐一解析每個字元,將其轉換為對應的十進位值。
  2. 將位權(16 的次方)相乘後加總。

執行範例

輸入: "FF" 輸出: 十進位: 255

4. 實作範例程式碼

雙向轉換程式

程式概述

此程式可讓使用者選擇以下操作。
  1. 十進制轉十六進制
  2. 十六進制轉十進制

程式碼範例

#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
無效的十六進位數字。

錯誤處理要點

對無效輸入的對策

  1. 檢查十六進制輸入的有效性:
  • 使用 isxdigit 函式,確認每個字元是否為有效的十六進位字元(0-9, A-F, a-f)。
  1. 十進制輸入的錯誤處理:
  • 若輸入非數字,顯示錯誤訊息並提示重新輸入。

防止無限迴圈

如果程式未明確設定結束條件,可能會產生無限迴圈。本程式透過選項「3」正確結束。

程式擴充建議

加入以下功能,可將程式擴充為更便利的工具。
  1. 二進制與八進制的轉換功能
  • 新增可選擇進位的選單。
  1. 指定位數以格式化轉換結果
  • 加入以固定位數格式化輸出的選項。
  1. 記錄至日誌檔案
  • 將轉換結果保存為檔案日誌。

總結

此範例程式提供十進制與十六進制的相互轉換,操作簡易。支援使用者輸入並考慮錯誤處理,讓初學者也能安心使用。

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;
}

負數與溢位的處理

負數的處理

處理負數時,取決於有號型別(intlong)。在十六進位輸出負數時,內部使用二的補數表示。
#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 型別。

提升可讀性與維護性的技巧

註解與命名規則

  • 為函式與變數命名有意義的名稱,並適當加入註解,可提升程式碼的可讀性。

善用標準函式

  • 手動的基數轉換對學習有益,但在實務上,優先使用標準函式(printfstrtol 等)可提升程式碼的可維護性。

程式測試

測試案例的重要性

製作基數轉換程式時,測試以下案例非常重要。
  • 正常的輸入(例:十進位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 語言中,提供了靈活的方式來以各種進位制處理數值。

從十進制轉換為十六進制

  • 使用 printfsprintf 函式,即可簡單且高效地進行轉換。
  • 也介紹了利用位元運算的手動轉換方法,這對於理解進位制轉換的邏輯很有幫助。

從十六進制轉換為十進制

  • 使用 scanfstrtol 函式,可將字串形式的十六進制轉換為十進制。
  • 加入對無效輸入與錯誤處理,可製作更穩健的程式。

實作範例程式

  • 透過雙向轉換程式,處理使用者輸入,實現十進制與十六進制的相互轉換。
  • 說明了加入錯誤處理以應對錯誤輸入的方法。

注意事項與最佳實踐

  • 說明了格式指定子的使用方式、大小寫的選擇等,如何調整輸出的外觀。
  • 提醒注意負數與溢位,並強調徹底檢查型別選擇與範圍的重要性。

常見問題(FAQ)

  • 針對實務疑問(例如:在 printf 中加上「0x」的方法、無效輸入的處理方式),提供具體範例說明。
  • 也提及了向其他進位制(二進制或八進制)應用的方法。

閱讀本文可獲得的收穫

閱讀本文後,讀者將學會以下內容並能實作。
  1. C 語言中基數轉換的基本概念與應用
  2. 使用可執行程式碼實作進位制轉換
  3. 包含輸入驗證與錯誤處理的穩健程式開發

未來學習的建議

為了進一步深化理解,建議學習以下內容。
  • 其他進位制(二進制與八進制)的轉換方法
  • 在非 C 語言的程式語言中實作基數轉換
  • 與記憶體管理及二進位操作相關的知識
希望本文內容能成為學習 C 語言的初學者與處理基數轉換的程式設計師實用且有益的指南。請以此為參考,挑戰更進階的程式開發。