高效率、灵活打印结构体串(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变量一样的东西来使用,是不用脑子就想到的一种方法。 另外两...

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

#include #include #define Name(X) #X #define Out(X) {string xname=Name(X);cout

结构体转化成字符数组

昨天晚上在解决通过socket发送结构体的问题的时候,知道了可以将结构体先转化成字符串的形式再发送,但今天之前一直有个疑问没有解决(为了方便描述,去掉socket部分),首先看下代码: #includ...
  • wonxxx
  • wonxxx
  • 2014年09月02日 11:07
  • 3244

linux驱动学习笔记(2.3) scull模块 init_MUTEX被废除

一、今天在编译ldd3上的scullc的时候,出现如下错误: 刚开始我以为没有包含头文件,然后我就去查2.6.39.1的源代码,结果在所有的符号中都没有发现init_MUTEX,后面在网站上发现...

linux 内核信号量 用户态信号量 详解

Linux  内核中的信号量使用和用户态的信号量使用有所不同, 1、内核信号量,由内核控制路径使用。 2、用户态信号量分为两种,一种为POSIX,另一种为 SYSTEM V 内核中信号量的构成以...
  • weed_hz
  • weed_hz
  • 2013年05月23日 16:44
  • 7431

c语言版数据结构(奇迹冬瓜)-串(定长顺序存储各项操作)

//-----头文件------ #include #include //------宏定义------ #define MAXSTRLEN 255 #define OVERFLOW -2 #def...

数据结构 - C语言版 - 串 所有基本操作

题目:要求输入两个字符串,实现字符串的连接,以及判断这两个串是否相等; #include #include #define MAXSIZE 255 typedef struct String...

学习笔记------数据结构(C语言版) 串的模式匹配

//KMP.cpp #include"predefined.h" #include"SequenceString.h" Status Index(SString S,SString T,int p...
  • CYTCHAN
  • CYTCHAN
  • 2016年02月15日 12:11
  • 311

数据结构c语言版串的操作

浙江中医药大学-《数据结构》(C语言版)-栈、队列、串、数组

浙江中医药大学-《数据结构》(C语言版)-栈、队列、串、数组
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:高效率、灵活打印结构体串(C语言版)
举报原因:
原因补充:

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