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

  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语言实现))