【C语言十六进制编码(BASE16)的编码与解码】

C语言十六进制编码(BASE16)的编码与解码

十六进制(BASE16)编码

  • 将数据以4位二进制为一组进行编码,就是BASE16编码。
  • 2的4次方是16,4位二进制数可以表示16个字符,简单的说,BASE16编码,就是用16个字符,即:0-9, A-F来表示四位二进制数!!!
  • 用字符数组定义一个码表:static char bt[16] = “0123456789ABCDEF”;
  • 一个字节是八位二进制数,正好可以用两个字符表示,也就是一个字符变成两个十六进制字符!
  • 编码函数base16_encode,参数为输入的正常字符串指针,输出为字符串指针,用malloc分配内存,长度为原字符串长度的2倍加1,因为字符串结尾为0!!!
  • 先取字符的前四位(从左边开始),即右移四位,以这四位为索引,从码表中取出一个字符,将字符保存到分配好的内存中!!!
  • 再取字符的后四位,此时要将字符的前四位去掉,用位运符&,即按位与,前四位每一位都做与0运算,其结果均为0,后四位每一位都做与1运算,则完成保留后四位不变!!!
  • 按位与00001111,也就是 &0X0F,然后再以结果为索引,从码表中取出字符,将字符保存到分配好的内存中,如此即完成编码操作!!!
  • 输出的字符串指针是用malloc分配的内存,用完后一定要用free释放掉!!!

代码如下:

/* filename: base16.c */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

/**/
static char bt[16] = "0123456789ABCDEF";

/**/
char *
base16_encode (char *txt)
{
  int i = 0, j = 0, len = strlen (txt);
  char *buf = (char*) malloc (len * 2 + 1);
  memset (buf, 0, len*2+1);
  while (i < len)
    {
      char c = txt[i];
      unsigned char ia = c >> 4;
      char sa = bt[ia];
      unsigned char ib = c & 0x0F;
      char sb = bt[ib];
      buf[j] = sa; j++;
      buf[j] = sb; j++;
      i++;
    }
  return buf;
}

/**/
void
test_base16_encode (void)
{
  char *str = "Hello world!";
  char *code = base16_encode (str);
  printf ("Source : [%s]\n", str);
  printf ("Dest   : [%s]\n", code);
  free (code);
}

/**/
int
main (int argc, char *argv[])
{
  test_base16_encode ();
  return 0;
}
/* --(.^.)-- */

编译运行,结果如下:

songvm@ubuntu:~/works/xdn/woo$ gcc base16.c -o base16
songvm@ubuntu:~/works/xdn/woo$ ./base16
Source : [Hello world!]
Dest   : [48656C6C6F20776F726C6421]
songvm@ubuntu:~/works/xdn/woo$ 

解码函数base16_decode

  • 将上面的编码字符串复制到代码中,准备解码,验证一下!
  • 定义函数base16_get_index,取编码字符,对照码表获得索引!
  • 定义解码函数base16_decode,循环每次取两个索引,将两个索引合并成一个字符!
  • 编码右移,解码左移即可!!!
  • 同样要分配内存,用完后注意释放内存指针!!!
  • 将字符保存到内存指针中

代码如下:

/* filename: base16.c */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

/**/
static char bt[16] = "0123456789ABCDEF";

/**/
char *
base16_encode (char *txt)
{
  int i = 0, j = 0, len = strlen (txt);
  char *buf = (char*) malloc (len * 2 + 1);
  memset (buf, 0, len*2+1);
  while (i < len)
    {
      char c = txt[i];
      unsigned char ia = c >> 4;
      char sa = bt[ia];
      unsigned char ib = c & 0x0F;
      char sb = bt[ib];
      buf[j] = sa; j++;
      buf[j] = sb; j++;
      i++;
    }
  return buf;
}

/**/
static char
base16_get_index (char c)
{
  char idx;
  for (idx = 0; idx < 16; idx++)
    if (c == bt[idx]) return idx;
  return idx;
}

/**/
char *
base16_decode (char *code)
{
  int i = 0, j = 0, len = strlen (code);
  char *buf = (char*) malloc (len / 2 * sizeof(char) + 1);
  memset (buf, 0, len/2+1);
  while (i < len)
    {
      char ca = base16_get_index(code[i]); i++;
      char cb = base16_get_index(code[i]); i++;
      ca = ca << 4;
      char c = ca | cb;
      buf[j] = c; j++;
    }
  return buf;
}

/**/
void
test_base16_encode (void)
{
  char *str = "Hello world!";
  char *code = base16_encode (str);
  printf ("Source : [%s]\n", str);
  printf ("Dest   : [%s]\n", code);
  free (code);
}

/**/
void
test_base16_decode (void)
{
  char *code = "48656C6C6F20776F726C6421";
  char *txt  = base16_decode (code);
  printf ("Dest   : [%s]\n", code);
  printf ("Source : [%s]\n", txt);
  free (txt);
}

/**/
int
main (int argc, char *argv[])
{
  test_base16_decode ();
  return 0;
}
/* --(.^.)-- */

编译运行,结果如下:

songvm@ubuntu:~/works/xdn/woo$ gcc base16.c -o base16
songvm@ubuntu:~/works/xdn/woo$ ./base16 
Dest   : [48656C6C6F20776F726C6421]
Source : [Hello world!]
songvm@ubuntu:~/works/xdn/woo$
  • 达到预期目标!!!

试试中文字符

  • 将两个测试函数都写入主函数
  • 将helloworld注释掉
  • 换成char *str = “此心安处是吾乡”;

编译运行,结果如下:

songvm@ubuntu:~/works/xdn/woo$ gcc base16.c -o base16
songvm@ubuntu:~/works/xdn/woo$ ./base16 
Source : [Hello world!]
Dest   : [48656C6C6F20776F726C6421]
--------------------
Dest   : [48656C6C6F20776F726C6421]
Source : [Hello world!]
songvm@ubuntu:~/works/xdn/woo$ gcc base16.c -o base16
songvm@ubuntu:~/works/xdn/woo$ ./base16 
Source : [此心安处是吾乡]
Dest   : []
--------------------
Dest   : [48656C6C6F20776F726C6421]
Source : [Hello world!]
songvm@ubuntu:~/works/xdn/woo$ 
  • 很明显没有输出,出问题了!!!
  • 注意:C语言中,将一个数的各二进制位全部右移若干位,正数左补0,负数左补1,右边丢弃。
  • 代码用UTF8保存,中文字符是三个字节,且高位均为1,右移后还是负数,在码表中找不到对应的字符!!!
  • 改进方法,右移后,将左边四位去掉即可!!!
  • 将函数base16_encode代码加上 ia = ia & 0x0F; 去掉前四位!!!

代码如下:

unsigned char ia = c >> 4; ia = ia & 0x0F;

编译运行,结果如下:

songvm@ubuntu:~/works/xdn/woo$ gcc base16.c -o base16
songvm@ubuntu:~/works/xdn/woo$ ./base16 
Source : [此心安处是吾乡]
Dest   : [E6ADA4E5BF83E5AE89E5A484E698AFE590BEE4B9A1]
--------------------
Dest   : [48656C6C6F20776F726C6421]
Source : [Hello world!]
songvm@ubuntu:~/works/xdn/woo$ 
  • 编码结果出来了!!!
  • 将以上编码复制到测试函数,解码看一下结果:
songvm@ubuntu:~/works/xdn/woo$ gcc base16.c -o base16
songvm@ubuntu:~/works/xdn/woo$ ./base16 
Source : [此心安处是吾乡]
Dest   : [E6ADA4E5BF83E5AE89E5A484E698AFE590BEE4B9A1]
--------------------
Dest   : [E6ADA4E5BF83E5AE89E5A484E698AFE590BEE4B9A1]
Source : [此心安处是吾乡]
songvm@ubuntu:~/works/xdn/woo$

结果如预期,完整代码如下:

/* filename: base16.c */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

/**/
static char bt[16] = "0123456789ABCDEF";

/**/
char *
base16_encode (char *txt)
{
  int i = 0, j = 0, len = strlen (txt);
  char *buf = (char*) malloc (len * 2 + 1);
  memset (buf, 0, len*2+1);
  while (i < len)
    {
      char c = txt[i];
      unsigned char ia = c >> 4; ia = ia & 0x0F;
      char sa = bt[ia];
      unsigned char ib = c & 0x0F;
      char sb = bt[ib];
      buf[j] = sa; j++;
      buf[j] = sb; j++;
      i++;
    }
  return buf;
}

/**/
static char
base16_get_index (char c)
{
  char idx;
  for (idx = 0; idx < 16; idx++)
    if (c == bt[idx]) return idx;
  return idx;
}

/**/
char *
base16_decode (char *code)
{
  int i = 0, j = 0, len = strlen (code);
  char *buf = (char*) malloc (len / 2 * sizeof(char) + 1);
  memset (buf, 0, len/2+1);
  while (i < len)
    {
      char ca = base16_get_index(code[i]); i++;
      char cb = base16_get_index(code[i]); i++;
      ca = ca << 4;
      char c = ca | cb;
      buf[j] = c; j++;
    }
  return buf;
}

/**/
void
test_base16_encode (void)
{
  //char *str = "Hello world!";
  char *str = "此心安处是吾乡";
  char *code = base16_encode (str);
  printf ("Source : [%s]\n", str);
  printf ("Dest   : [%s]\n", code);
  free (code);
}

/**/
void
test_base16_decode (void)
{
  //char *code = "48656C6C6F20776F726C6421";
  char *code = "E6ADA4E5BF83E5AE89E5A484E698AFE590BEE4B9A1";
  char *txt  = base16_decode (code);
  printf ("Dest   : [%s]\n", code);
  printf ("Source : [%s]\n", txt);
  free (txt);
}

/**/
int
main (int argc, char *argv[])
{
  test_base16_encode ();
  printf ("--------------------\n");
  test_base16_decode ();
  return 0;
}
/* --(.^.)-- */

读一个文本文件,用BASE16重新编码,输出到另一个文本文件中

  • encode_file 函数,参数一为输入文件名,参数二为输出文件名
  • decode_file 函数,参数一为输入文件名,参数二为输出文件名

代码如下:

/* filename: base16f.c */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

/**/
static char bt[16] = "0123456789ABCDEF";

/**/
char *
base16_encode (char *txt)
{
  int i = 0, j = 0, len = strlen (txt);
  char *buf = (char*) malloc (len * 2 + 1);
  memset (buf, 0, len*2+1);
  while (i < len)
    {
      char c = txt[i];
      unsigned char ia = c >> 4; ia = ia & 0x0F;
      char sa = bt[ia];
      unsigned char ib = c & 0x0F;
      char sb = bt[ib];
      buf[j] = sa; j++;
      buf[j] = sb; j++;
      i++;
    }
  return buf;
}

/**/
static char
base16_get_index (char c)
{
  char idx;
  for (idx = 0; idx < 16; idx++)
    if (c == bt[idx]) return idx;
  return idx;
}

/**/
char *
base16_decode (char *code)
{
  int i = 0, j = 0, len = strlen (code);
  char *buf = (char*) malloc (len / 2 * sizeof(char) + 1);
  memset (buf, 0, len/2+1);
  while (i < len)
    {
      char ca = base16_get_index(code[i]); i++;
      char cb = base16_get_index(code[i]); i++;
      ca = ca << 4;
      char c = ca | cb;
      buf[j] = c; j++;
    }
  return buf;
}

/**/
void
encode_file (char *ifname, char *ofname)
{
  char c;
  FILE *fpi, *fpo;
  fpi = fopen (ifname, "r");
  fpo = fopen (ofname, "w+");

  c = fgetc (fpi);
  while (c != EOF)
    {
      char sa, sb;
      unsigned char ia, ib;
      ia = c >> 4; ia = ia & 0x0F;
      sa = bt[ia];
      fputc (sa, fpo);
      ib = c & 0x0F;
      sb = bt[ib];
      fputc (sb, fpo);
      c = fgetc (fpi);
    }

  fclose (fpi);
  fclose (fpo);
}

/**/
void
decode_file (char *ifname, char *ofname)
{
  char c;
  FILE *fpi, *fpo;
  fpi = fopen (ifname, "r");
  fpo = fopen (ofname, "w+");

  c = fgetc (fpi);
  while (c != EOF)
    {
      char ca, cb, cx;
      ca = base16_get_index(c); c = fgetc (fpi);
      cb = base16_get_index(c); ca = ca << 4;
      cx = ca | cb; fputc (cx, fpo);
      c = fgetc (fpi);
    }

  fclose (fpi);
  fclose (fpo);
}

/* ------------------------- */

/**/
void
test_base16_encode (void)
{
  //char *str = "Hello world!";
  char *str = "此心安处是吾乡";
  char *code = base16_encode (str);
  printf ("Source : [%s]\n", str);
  printf ("Dest   : [%s]\n", code);
  free (code);
}

/**/
void
test_base16_decode (void)
{
  //char *code = "48656C6C6F20776F726C6421";
  char *code = "E6ADA4E5BF83E5AE89E5A484E698AFE590BEE4B9A1";
  char *txt  = base16_decode (code);
  printf ("Dest   : [%s]\n", code);
  printf ("Source : [%s]\n", txt);
  free (txt);
}

/**/
void
test_base16 (void)
{
  test_base16_encode ();
  printf ("--------------------\n");
  test_base16_decode ();
}

/**/
void
test_file (void)
{
  encode_file ("ti.txt", "to.txt");
  //decode_file ("to.txt", "tz.txt");
}

/**/
int
main (int argc, char *argv[])
{
  test_file ();
  return 0;
}
/* --(.^.)-- */

运行encode_file函数,输入文件名为ti.txt,输出文件名为to.txt,编译运行,结果如下:

songvm@ubuntu:~/works/xdn/woo$ gcc base16f.c -o base16f
songvm@ubuntu:~/works/xdn/woo$ ./base16f
songvm@ubuntu:~/works/xdn/woo$ ls
b16a.c  base16.c  base16f.c   tia.txt  ti.txt~
b16.c   base16f   base16f.c~  ti.txt   to.txt
songvm@ubuntu:~/works/xdn/woo$ cat to.txt
E789A9E697A0E99D9EE5BDBCEFBC8CE789A9E697A0E99D9EE698AFE38082E887AAE5BDBCE58899E4B88DE8A781EFBC8CE887AAE79FA5E58899E79FA5E4B98BE38082E69585E69BB0EFBC9AE5BDBCE587BAE4BA8EE698AFEFBC8CE698AFE4BAA6E59BA0E5BDBCE38082E5BDBCE698AFE696B9E7949FE4B98BE8AFB4E4B99FE38082E899BDE784B6EFBC8CE696B9E7949FE696B9E6ADBBEFBC8CE696B9E6ADBBE696B9E7949FEFBC9BE696B9E58FAFE696B9E4B88DE58FAFEFBC8CE696B9E4B88DE58FAFE696B9E58FAFEFBC9BE59BA0E698AFE59BA0E99D9EEFBC8CE59BA0E99D9EE59BA0E698AFE38082E698AFE4BBA5E59CA3E4BABAE4B88DE794B1E8808CE785A7E4B98BE4BA8EE5A4A9EFBC8CE4BAA6E59BA0E698AFE4B99FE38082E698AFE4BAA6E5BDBCE4B99FEFBC8CE5BDBCE4BAA6E698AFE4B99FE38082E5BDBCE4BAA6E4B880E698AFE99D9EEFBC8CE6ADA4E4BAA6E4B880E698AFE99D9EEFBC8CE69E9CE4B894E69C89E5BDBCE698AFE4B98EE59389EFBC9FE69E9CE4B894E697A0E5BDBCE698AFE4B98EE59389EFBC9FE5BDBCE698AFE88EABE5BE97E585B6E581B6EFBC8CE8B093E4B98BE98193E69EA2E38082E69EA2E5A78BE5BE97E585B6E78EAFE4B8ADEFBC8CE4BBA5E5BA94E697A0E7A9B7E38082E698AFE4BAA6E4B880E697A0E7A9B7EFBC8CE99D9EE4BAA6E4B880E697A0E7A9B7E4B99FE38082E69585E69BB0EFBC9AE88EABE88BA5E4BBA5E6988EE380820A

运行decode_file函数,输入文件名为to.txt,输出文件名为tz.txt,编译运行,结果如下:

songvm@ubuntu:~/works/xdn/woo$ gcc base16f.c -o base16f
songvm@ubuntu:~/works/xdn/woo$ ./base16f
songvm@ubuntu:~/works/xdn/woo$ ls
b16a.c  base16.c  base16f.c   tia.txt  ti.txt~  tz.txt
b16.c   base16f   base16f.c~  ti.txt   to.txt
songvm@ubuntu:~/works/xdn/woo$ cat tz.txt
物无非彼,物无非是。自彼则不见,自知则知之。故曰:彼出于是,是亦因彼。彼是方生之说也。虽然,方生方死,方死方生;方可方不可,方不可方可;因是因非,因非因是。是以圣人不由而照之于天,亦因是也。是亦彼也,彼亦是也。彼亦一是非,此亦一是非,果且有彼是乎哉?果且无彼是乎哉?彼是莫得其偶,谓之道枢。枢始得其环中,以应无穷。是亦一无穷,非亦一无穷也。故曰:莫若以明。
songvm@ubuntu:~/works/xdn/woo$
  • 达到预期目标!!! 下一步,研究一下BASE32编码!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值