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编码!



773

被折叠的 条评论
为什么被折叠?



