在项目开发中,比如网络开发,多媒体播放开发等,常常用到将接受数据和发送数据或者需要解析的数据,用打印方式呈现。方便自己定位问题。
在这个时候,printf难免没有满足我们的需要了。因为printf("bufdata =%s\n",bufdata),是用字符串方式输出,当碰到字符串中存在'\0'的时候,就会停止输出,造成打印不全,甚至打印死机(当字符串中没有'\0'结束符的时候,就会出现非法数据访问,造成死机)。下面介绍一种通用的16进制打印方式。简单易用。
/*
* 十六进制方式打印
* 应用场合:1)打印抓回来的网络包数据
* 2)打印多媒体码流数据
*/
#include <stdio.h>
//十六进制和ASCII码打印
extern int func_hex_printout(const char* tag , const char* buf ,unsigned int len , int wide);
//十六进制打印
extern int func_hex_printout2(const char* tag , const char* buf ,unsigned int len , int wide);
//ASCII码打印
extern int func_hex_printout3(const char* tag , const char* buf ,unsigned int len , int wide);
#define HEX_INFO(tag , buf , buf_len) func_hex_printout(tag , buf , buf_len ,16)
#define HEX_INFO2(tag , buf , buf_len) func_hex_printout2(tag , buf , buf_len ,16)
#define HEX_INFO3(tag , buf , buf_len) func_hex_printout3(tag , buf , buf_len ,16)
int main(int argc ,char *argv[])
{
char TAG[] = "DEBUG";
char buf[128] = "abcdefghijklmnopqrstuvwxyz\n\r\0\t123456789";
int len = sizeof(buf);
HEX_INFO(TAG , buf , len);
HEX_INFO2(TAG , buf , len);
HEX_INFO3(TAG , buf , len);
return 0;
}
/*重定义符合目前操作系统显示的打印函数*/
#define INFO_PRINT printf
/*
*函数功能:十六进制和ASCII码打印
*参数:tag 打印标签
buf 数据
len 数据buf长度
wide 字宽
*/
int func_hex_printout(const char* tag , const char* buf ,unsigned int len , int wide)
{
int i = 0 ;
int ret = 0;
int nTabs = 0;
int nlines = 0;
char msgbuf[128] = {0};
const char hex_char[] = "0123456789ABCDEF";
const unsigned char *ptr = (const unsigned char*)buf;
if ((NULL == tag) || (NULL == buf) || ((8 != wide) && (16 != wide)))
{
return ret;
}
//打印buf的内存地址和输出打印的长度。
INFO_PRINT("%s buf addr=%08lx, buf len=%ld bytes\n", tag, buf, len);
/* calculate how many prefixing Tab */
while ((*tag == '\r') || (*tag == '\n'))
{
tag++; // skip prefixing '\r' or '\n'
}
while (*tag++ == '\t')
{
nTabs++;
if (6 == nTabs)
{
break;
}
}
if (8 == wide)
{
nlines = (len + 0x07) >> 3;
}
else if (16 == wide)
{
nlines = (len + 0x0f) >> 4;
}
for (i = 0; i < nlines; i++)
{
int j = 0;
char *dst = msgbuf;
int nbytes = ((int)len < wide) ? len : wide;
for (j = 0; j < nTabs; j++)
{
*dst++ = '\t';
}
*dst++ = ' ';
*dst++ = ' ';
*dst++ = ' ';
*dst++ = ' ';
for (j = 0; j < nbytes; j++)
{
unsigned char ival = *ptr++;
//一个char型变量用16进制输出,然后再输出一个空格,共占用三个字符空间
*dst++ = hex_char[(ival >> 4) & 0x0F];
*dst++ = hex_char[ival & 0x0F];
*dst++ = ' ';
}
//输出一行数值后,输出三个空格,再输出该行数值的ASCII码字符
//若nbytes小于一行的长度,即小于8或16,则以三个空格代替一个数值输出
for (j = 0; j < wide - nbytes + 1; j++)
{
*dst++ = ' ';
*dst++ = ' ';
*dst++ = ' ';
}
ptr -= nbytes;
for (j = 0; j < nbytes; j++)
{
if ((*ptr >= 0x20) && (*ptr <= 0x7e))
{
*dst = *ptr;
}
else
{
*dst = '.';
}
ptr++;
dst++;
}
*dst = 0;
ret += INFO_PRINT("%s\n", msgbuf);
len -= nbytes;
}
return ret;
}
/*
*函数功能:十六进制打印
*参数:tag 打印标签
buf 数据
len 数据buf长度
wide 字宽
*/
int func_hex_printout2(const char* tag , const char* buf ,unsigned int len , int wide)
{
int i = 0 ;
int ret = 0;
int nTabs = 0;
int nlines = 0;
char msgbuf[128] = {0};
const char hex_char[] = "0123456789ABCDEF";
const unsigned char *ptr = (const unsigned char*)buf;
if ((NULL == tag) || (NULL == buf) || ((8 != wide) && (16 != wide)))
{
return ret;
}
//打印buf的内存地址和输出打印的长度。
INFO_PRINT("%s buf addr=%08lx, buf len=%ld bytes\n", tag, buf, len);
/* calculate how many prefixing Tab */
while ((*tag == '\r') || (*tag == '\n'))
{
tag++; // skip prefixing '\r' or '\n'
}
while (*tag++ == '\t')
{
nTabs++;
if (6 == nTabs)
{
break;
}
}
if (8 == wide)
{
nlines = (len + 0x07) >> 3;
}
else if (16 == wide)
{
nlines = (len + 0x0f) >> 4;
}
for (i = 0; i < nlines; i++)
{
int j = 0;
char *dst = msgbuf;
int nbytes = ((int)len < wide) ? len : wide;
for (j = 0; j < nTabs; j++)
{
*dst++ = '\t';
}
*dst++ = ' ';
*dst++ = ' ';
*dst++ = ' ';
*dst++ = ' ';
for (j = 0; j < nbytes; j++)
{
unsigned char ival = *ptr++;
//一个char型变量用16进制输出,然后再输出一个空格,共占用三个字符空间
*dst++ = hex_char[(ival >> 4) & 0x0F];
*dst++ = hex_char[ival & 0x0F];
*dst++ = ' ';
}
*dst = 0;
ret += INFO_PRINT("%s\n", msgbuf);
len -= nbytes;
}
return ret;
}
/*
*函数功能:ASCII码打印
*参数:tag 打印标签
buf 数据
len 数据buf长度
wide 字宽
*/
int func_hex_printout3(const char* tag , const char* buf ,unsigned int len , int wide)
{
int i = 0 ;
int ret = 0;
int nTabs = 0;
int nlines = 0;
char msgbuf[128] = {0};
const char hex_char[] = "0123456789ABCDEF";
const unsigned char *ptr = (const unsigned char*)buf;
if ((NULL == tag) || (NULL == buf) || ((8 != wide) && (16 != wide)))
{
return ret;
}
//打印buf的内存地址和输出打印的长度。
INFO_PRINT("%s buf addr=%08lx, buf len=%ld bytes\n", tag, buf, len);
/* calculate how many prefixing Tab */
while ((*tag == '\r') || (*tag == '\n'))
{
tag++; // skip prefixing '\r' or '\n'
}
while (*tag++ == '\t')
{
nTabs++;
if (6 == nTabs)
{
break;
}
}
if (8 == wide)
{
nlines = (len + 0x07) >> 3;
}
else if (16 == wide)
{
nlines = (len + 0x0f) >> 4;
}
for (i = 0; i < nlines; i++)
{
int j = 0;
char *dst = msgbuf;
int nbytes = ((int)len < wide) ? len : wide;
for (j = 0; j < nTabs; j++)
{
*dst++ = '\t';
}
*dst++ = ' ';
*dst++ = ' ';
*dst++ = ' ';
*dst++ = ' ';
for (j = 0; j < nbytes; j++)
{
if ((*ptr >= 0x20) && (*ptr <= 0x7e))
{
*dst = *ptr;
}
else
{
*dst = '.';
}
ptr++;
dst++;
}
*dst = 0;
ret += INFO_PRINT("%s\n", msgbuf);
len -= nbytes;
}
return ret;
}
PC终端运行效果如下: