高效率、灵活打印结构体串(C语言版)

原创 2015年11月20日 10:41:50

  C语言中很多时候把结构体当做字符串使用。

例如一个简单的报文协议:

命令类型 4字节      //通信测试报文  “1001”

        交易系统ID   2字节

        版本号     10字节

         MAC             8字节

         数据              20字节

那么我们根据不同的报文定义结构体:

typedef struct  
{
      char   TRXTYPE[TYPE_LEN];
      char    BUSID [BUSID_LEN];
      char    VER [VER_LEN];
      char   MAC[MAC_LEN];
      char   DATA[DATA_LEN];
}TEST_S;


下面是定义结构体,然后赋值发送。

       

   TEST_S test_s;
   spritf(test_s.TRXTYPE, "1001");
   spritf(test_s.BUSID, "FF");
    ………… //各种赋值
    SendBuff(&test_s, sizeof(test_s)); //发送数据

---------------------------------------------------------------------------------

   我们要如何打印这个结构体呢? 或者是接到的结构体

    一种简单的做法是根据不同的报文 拼接打印。

    比如打印测试报文:

void show1001(TEST_S *ptest_s){
	if(ptest_s == NULL)  //可增加打印信息
		return ;
	//showPrintf 增加打印介绍符
	printf("TRXTYPE        =[%s](%d)", showPrintf(ptest_s->TRXTYPE,TYPE_LEN) , TYPE_LEN);
	printf("BUSID          =[%s](%d)", showPrintf(ptest_s->BUSID, BUSID_LEN) , BUSID_LEN);      
	…………
}

这种打印有很多坏处,如果想修改打印样式需要修改每个打印函数,需要写很多冗余的代码,效率低下容易出错。

-----------------------------------------------------------------------------------------------------------------------------------------------------------

下面介绍一种使用通用打印函数加结构体属性的打印方法(原创,但肯定有雷同)

除了结构体定义外,在定义一个结构体属性;

以上面的TEST_S结构体为例,结构体属性为:

	/*************结构打印**************/
	
	typedef struct 
	{
		intfield_len;//域长度
		charfield_name[STRU_FIELD_NAME_LEN];//域名字
	}FIELD_PRO;
	
	typedef struct 
	{
		intfield_num;//域数量
		FIELD_PROfield_pro[STRU_MAX_NUM];//域属性
	}STRUCT_PUB_CONF;
	
	/*****定义test结构体属性****/
	STRUCT_PUB_CONF pri_1001_s =
	{
		5,
		{ 
			{ TYPE_LEN,     TRXTYPE_NAME    },    //自定义域名宏
			{ BUSID_LEN, 	BUSID_NAME	}, 
			{ VER_LEN,	VER_NAME	},
			{ MAC_LEN,	MAC_NAME	},
			{ DATA_LEN,	DATA_NAME	}
		}
	};


每个需要打印的结构体只需要定义一个这样的结构体就可以打印了,是不是比每个结构体写一个打印函数(void show1001(TEST_S *ptest_s))简单呢!

事实证明效率非常高。

下面是实现的核心,统一打印函数。

/*******************************************************************************
* 函数名称 :PriStruct
* 说明            :根据结构体属性,打印结构体内容
* 输入参数 :in_s - 结构体串
*           struct_pub_conf - 结构体属性,记录域长度 名称等
* 输出参数 : 打印结构体内容,可动态分配打印空间
* 返回值      : 无
* 修改历史 :
*                         
* 2015/11/18, lei.l create this function
*******************************************************************************/
void PriStruct(char *in_s, STRUCT_PUB_CONF *struct_pub_conf)
{
	int	i = 0, index = 0, field_len = 0;
	int	calloc_flag = 0;
	char	*pin_s = NULL;
	char	field_value[PRI_FIELD_DEL_LEN] = {0};
	char	*pfield_value = NULL;
	char	*pshow = NULL;
	FIELD_PRO	*pfield_pro = NULL;

	if (in_s == NULL || struct_pub_conf == NULL)
	{
		printf("PriStruct inparam error!\n");
		return ;
	}

	pin_s = in_s;

	//循环打印结构体
	for (i = 0; i < struct_pub_conf->field_num; i++)
	{
		calloc_flag = 0;

		pfield_pro = (FIELD_PRO *)&struct_pub_conf->field_pro[i];

		//域长度大于默认的打印buff长度,根据实际大小分配空间
        /*PRI_WIDHT_DEL * 3  是因为还要打印"() [] =" 等字符*/
        if ((pfield_pro->field_len + PRI_WIDHT_DEL*3) >= PRI_FIELD_DEL_LEN)
		{
			pfield_value = (char *)calloc(pfield_pro->field_len + PRI_WIDHT_DEL*3, 1);
			if (pfield_value == NULL)
			{
				printf("PriStruct calloc error!\n");
				return ;
			}
			calloc_flag = 1;
		}
		else{ //打印域长度小于PRI_FIELD_DEL_LEN 256 则不分配堆空间,提高效率
			memset(field_value, 0, sizeof(field_value));
			pfield_value = field_value;
		}

		memset(pfield_value, ' ', PRI_WIDHT_DEL);
		//获取到域的名字
		memcpy(pfield_value, pfield_pro->field_name, strlen(pfield_pro->field_name));

		field_len = pfield_pro->field_len;
		index = strlen(pfield_value);

		pshow = showPrintf(pin_s, field_len);
		if (pshow == NULL)
		{
			printf("PriStruct calloc error!");
			if (1 == calloc_flag)
			{
				free(pfield_value);
				pfield_value = NULL;
			}
			return;
		}
		sprintf(&pfield_value[index], "=[%s](%d)\n", pshow, strlen(pshow));

		printf(pfield_value);

		//下个域值得起始位置
		pin_s += field_len;

		if ( 1 == calloc_flag )
		{
			free(pfield_value);
			pfield_value = NULL;
		}

	}

	return ;
}
项目实使用效果:

 /*打印结构体*/
    PriStruct((char *)&Int_63Y0,&pri_63Y0_s);

输出:

2015-11-18 16:43:48.619 paycomponentsvrDlg.cpp:1696  [6516]  TRXTYPE           :[1001](4)
2015-11-18 16:43:48.620 paycomponentsvrDlg.cpp:1696  [6516]  MAC               :[FC8B67A1](8)
2015-11-18 16:43:48.622 paycomponentsvrDlg.cpp:1696  [6516]  BUSISYSID         :[EE](2)
2015-11-18 16:43:48.624 paycomponentsvrDlg.cpp:1696  [6516]  BUSITERNO         :[110000050080](12)
2015-11-18 16:43:48.626 paycomponentsvrDlg.cpp:1696  [6516]  MERCHCODE         :[32550440](8)
2015-11-18 16:43:48.629 paycomponentsvrDlg.cpp:1696  [6516]  ORDERNO           :[110000050080000001321118164348](30)
2015-11-18 16:43:48.631 paycomponentsvrDlg.cpp:1696  [6516]  ORDERDATE         :[20151118164348](14)
2015-11-18 16:43:48.633 paycomponentsvrDlg.cpp:1696  [6516]  PAYTYPE           :[02001003](8)
2015-11-18 16:43:48.634 paycomponentsvrDlg.cpp:1696  [6516]  ISSCODE           :[XXXX      ](10)
2015-11-18 16:43:48.635 paycomponentsvrDlg.cpp:1696  [6516]  MTYPE             :[156](3)
2015-11-18 16:43:48.637 paycomponentsvrDlg.cpp:1696  [6516]  PAYAMOUNT         :[000000000100](12)
2015-11-18 16:43:48.638 paycomponentsvrDlg.cpp:1696  [6516]  PAYOBJ            :[1000111100000077767           ](30)
2015-11-18 16:43:48.639 paycomponentsvrDlg.cpp:1696  [6516]  PAYACCOUNT        :[1000111100000008067           ](30)
2015-11-18 16:43:48.640 paycomponentsvrDlg.cpp:1696  [6516]  POSMSG            :[aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaassssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssssddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhjjjjjjjjjjjjjj](300)



版权声明:本文为博主原创文章,未经博主允许不得转载。

C语言结构体(struct)常见使用方法

结构体与函数: 关于传参,首先: void func(int); func(a.b.c); 把结构体中的int成员变量当做和普通int变量一样的东西来使用,是不用脑子就想到的一种方法。 另外两...
  • huqinweI987
  • huqinweI987
  • 2014年04月14日 01:51
  • 420837

UE(虚幻)4 蓝图可视化编程 04 结构体

结构体 Structure 新建, 打开 Content Browser  新建一个文件夹 有点单机或者Add New ,Blueprints ----> Structure, 重命名 点击修改 ...
  • qq_36848370
  • qq_36848370
  • 2017年06月15日 16:11
  • 577

kernel中用%pR来打印resource结构体

kernel中用struct resource *res;表示资源 struct resource {     resource_size_t start;     resource_size_t e...
  • tiantao2012
  • tiantao2012
  • 2017年03月30日 09:28
  • 810

c语言结构体及成员的互换,并且打印结构体地址和成员地址

#include #define offsetof(TYPE , MEMBER)((size_t) &((TYPE *)0)->MEMBER) //container_of是给定结构体某个成员的地址...
  • zhaoyong26
  • zhaoyong26
  • 2017年01月13日 17:45
  • 879

OC 打印结构体的内容

OC结构体(如NSRect,NSSize,NSPoint等)类型的结构体变量不是对象,所以要想整体打印他们内容。必须事先把它们转换为OC字符串类型,常用的方法就是直接使用NSStringFromXxx...
  • u013087513
  • u013087513
  • 2015年10月02日 21:12
  • 751

基础(printf 的用法 && 结构体重载运算符)

过基础过基础printf 输出浮点型 printf(“%.2lf”,a); 浮点型数字输出保留两位小数“2”“lf” 其他不说了,都知道(⊙o⊙)…结构体的重载运算符struct ss{ ...
  • l961983207
  • l961983207
  • 2017年10月13日 21:26
  • 93

ios 打印 结构体

我们经常会输出一些坐标尺寸信息之类的,比如view的frame,是CGRect类型的,用frame.oringial.x 和frame.size.width来做NSLog参数好麻烦,还好苹果对这些常用...
  • zuojinmin
  • zuojinmin
  • 2016年04月19日 13:39
  • 1095

如何快速输出C++结构体的成员名和其值

#include #include #define Name(X) #X #define Out(X) {string xname=Name(X);cout
  • u011937377
  • u011937377
  • 2016年04月14日 00:58
  • 4399

c++::获取结构体中某 个成员相对结构体起始位置的偏移

我们使用宏offsetof,这个宏具体是什么?怎么用? 接下来我来详细说明: 【offsetof的定义】:     在MSDN上是这样定义的:size_t offsetof( structNa...
  • lalu58
  • lalu58
  • 2016年12月17日 14:09
  • 1688

C语言基础六(结构体以及一些宏定义)

结构体字节对齐 结构体变量本身从4字节对齐的位置开始存放。 整个结构体所占空间还要是成员中‘占字节最大的基本数据类型’的整数倍,不够的在末尾补齐。 short类型从地址是2的倍数处开始存储,in...
  • liuliuliut
  • liuliuliut
  • 2017年12月27日 21:40
  • 65
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:高效率、灵活打印结构体串(C语言版)
举报原因:
原因补充:

(最多只允许输入30个字)