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

来源:互联网 发布:网络数据传输流程 编辑:程序博客网 时间:2024/06/18 11:14

  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){inti = 0, index = 0, field_len = 0;intcalloc_flag = 0;char*pin_s = NULL;charfield_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)



1 0