天天看點

C語言16進制字元串轉位元組位元組數組

C語言16進制字元串轉位元組位元組數組

文章目錄

  • ​​C語言16進制字元串轉位元組位元組數組​​
  • ​​簡述:​​
  • ​​問題:​​

簡述:

  • 我們知道1位元組占8bit; 0000000 ~ 11111111
  • 以char形式表示就是 -128 ~ 127; 至于為什麼回頭再補充!!!
  • 以byte表示的話就是 0 ~ 255 等同于unsigned char因為C語言本身沒有byte類型
  • 以十六進制表示的話就是 0x00 ~ 0xFF

問題:

  • 有時候我們會有這樣的需求, 給你一串字元, 但是要以16進制的方式使用, 這時候就需要将兩位元組放到一位元組中. 16進制時1位元組是使用兩個數字表示的, 以字元串形式的話就是占兩位元組. 這時候就需要轉換, 進階語言轉換起來會更簡單, 使用會更友善, 這裡以C語言形式來轉換, 通用性強會強一點
  • 16進制字元串, 即一串字元串(3132333435363738393a3b3c3d3e3f40)字元串形式的話占32位元組, 但是如果他們是16進制表示的話(0x31, 0x32 … 0x40), 那麼就是占16位元組, 那麼怎麼轉換成占16位元組大小的byte數組呢?
  • 思路: 首先第一組0x31, 轉換成十進制就是49, 那麼怎麼轉換呢, 一般會先轉換成2進制再轉換成10進制. 那用程式怎麼表示呢? 我們可以考慮一下, 3以2進制表示(簡寫)0000 0011, 1以2進制表示0000 0001, 那麼在記憶體中0x31怎麼存放的呢? 我們知道十六進制一個數字能表示的範圍時0~F, 是以要表示1位元組的話就需要兩個16進制數, 那麼0x31的存放就是一位元組的前4位表示3, 後四位表示1, 即0011 0001(十進制49), 那怎麼才能把字元3轉換成數字3, 并且再放到前四位, 用代碼表示就是
// 假如字元串 "31"; 拆開成字元就如下面
// 注意這裡我們是以數字舉例的, 如果有ABCDEF, 還需要另外考慮
char m = '3';
char n = '1';
unsigned char byte = 0; // 1位元組 待會存放0x31使用, C語言中沒有位元組類型, 這裡用unsigned char 代替, 一樣的效果
// 要先将字元 '3' 轉換成數字 3; 字元 '1' 轉換成數字 1
// 最簡單的就是 '3' - '0' 即 m = m - '0';
// 更好的辦法就是位運算(需要經驗才會習慣, 大神飄過), 如下
m = m & ~0x30; // 或者 m = m & ~'0'; m = m & ~48;
// 字元 '1' 同理, 那麼此時 m = 3, n = 1;接下來就是如何存放成1位元組了
// 将 3 向左移4位, 就是00000011變成00110000
// 再加上1(00000001)就行了, 代碼表示就是
m = m << 4;
byte = m | n;      
  • 那麼怎麼封裝一個函數來做這件事? 直接附上代碼
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int hexstringtobyte(char *in, unsigned char *out);
int hexstringtobyte(char *in, unsigned char *out) {
    int len = (int)strlen(in);
    char *str = (char *)malloc(len);
    memset(str, 0, len);
    memcpy(str, in, len);
    for (int i = 0; i < len; i+=2) {
        //小寫轉大寫
        if(str[i] >= 'a' && str[i] <= 'f') str[i] = str[i] & ~0x20;
        if(str[i+1] >= 'a' && str[i] <= 'f') str[i+1] = str[i+1] & ~0x20;
        //處理第前4位
        if(str[i] >= 'A' && str[i] <= 'F')
            out[i/2] = (str[i]-'A'+10)<<4;
        else
            out[i/2] = (str[i] & ~0x30)<<4;
        //處理後4位, 并組合起來
        if(str[i+1] >= 'A' && str[i+1] <= 'F')
            out[i/2] |= (str[i+1]-'A'+10);
        else
            out[i/2] |= (str[i+1] & ~0x30);
    }
    free(str);
    return 0;
}
int bytetohexstring(unsigned char *in, int len, char *out);
int bytetohexstring(unsigned char *in, int len, char *out) {
    for (int i = 0; i < len; i++) {
        if ((in[i] >> 4) >= 10 && (in[i] >> 4) <= 15)
            out[2*i] = (in[i] >> 4) + 'A' - 10;
        else
            out[2*i] = (in[i] >> 4) | 0x30;
        
        if ((in[i] & 0x0f) >= 10 && (in[i] & 0x0f) <= 15)
            out[2*i+1] = (in[i] & 0x0f) + 'A' - 10;
        else
            out[2*i+1] = (in[i] & 0x0f) | 0x30;
    }
    return 0;
}      
int main(int argc, const char * argv[]) {
    char *str = "fa32333435363738393a3b3c3d3e3f40";
    unsigned char temp[16] = {0};
    hexstringtobyte(str, temp);
    for (int i = 0; i < 16; i++) {
        printf("%d ", temp[i]);
    }
    printf("\n");
    char out[33] = {0}; // 多留了一位存放 '\0'
    bytetohexstring(temp, 16, out);
    printf("%s\n", out);
    return 0;
}      

繼續閱讀