C語言自動(dòng)生成enum值和名字映射代碼
這年頭好像繼續(xù)做C語言的人不多了,年輕人大多去互聯(lián)網(wǎng)和移動(dòng)應(yīng)用。確實(shí),那兩個(gè)領(lǐng)域現(xiàn)在來錢快,且總是供不應(yīng)求。就說剛剛在一個(gè)舊同事的微信群里,有人剛放出自己有團(tuán)隊(duì)可以做App幾分鐘,哇塞,好幾個(gè)人說有項(xiàng)目,要求加好友私聊。我也想過轉(zhuǎn)行,可惜人老珠黃,沒有互聯(lián)網(wǎng)或是應(yīng)用團(tuán)隊(duì)愿意接收。估計(jì)再過些年,C程序世界里就只有我這樣的小老頭們繼續(xù)自娛自樂了,羨慕死年輕人了!
平常工作中,經(jīng)常要做一些打印,或是日志。而這里面,enum類型的數(shù)據(jù)就很多,如果只是打印出它的整數(shù)值,顯然會(huì)讓測(cè)試人員很惱火,鬼知道那數(shù)字說的是什么。就算你給他個(gè)文檔對(duì)著看,也絲毫不能得到原諒。最后,都得乖乖的把這個(gè)enum對(duì)應(yīng)的名字打印出來才能平息。
今天說的這個(gè),就是幫忙搞定這個(gè)轉(zhuǎn)換問題的。
比如,有這么個(gè)example.h文件:
enum InfoStateE{
eInfoStateIdle,
eInfoStateIniting,
eInfoStateInited,
eInfoStateReady,
eInfoStateActive,
eInfoStateStandby,
eInfoStateRelease,
};
我們需要個(gè)函數(shù),把enum值翻譯成字符串;另外也要個(gè)函數(shù),能查找字符串對(duì)應(yīng)的enum值;可以提供名字的一部分。p_enum.pl就是做這個(gè)的,只需要執(zhí)行:
perl p_enum.pl example.h -o:example_map
p_enum.pl接受目錄,通配符,或是多個(gè)文件。-o:example_map是指定輸出的文件名。這里我們得到了example_map.h和example_map.c兩個(gè)文件:
/*
FILE: example_map.h
This file was created at Fri Dec 11 16:40:56 CST 2015
Auto-generated source. Don't change it manually.
Contact with hhao020@gmail.com for bug reporting and supporting.
*/
#ifndef EXAMPLE_MAP
#define EXAMPLE_MAP
#ifdef __cplusplus
extern "C" {
#endif
#include "zType_Def.h"
extern const char* InfoStateE2Name(dword_t e);
extern dword_t InfoStateE2Value(char* name, int bAppro);
extern int InfoStateEMapShow();
#ifdef __cplusplus
}
#endif
#endif /*EXAMPLE_MAP*/
/*
FILE: example_map.c
This file was created at Fri Dec 11 16:40:56 CST 2015
Auto-generated source. Don't change it manually.
Contact with hhao020@gmail.com for bug reporting and supporting.
*/
#define _GNU_SOURCE
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include "zAutoCodeApi.h"
#ifndef ENUM_PRIMARY_FUNCTIONS
static char *zEnum2Name(dword_t e, zEnum2NameMap_t arr[], int nSize)
{
int i;
for(i=0; i<nSize; i++)
{
if(arr[i].e == e) return arr[i].name;
}
return 0;
}
static int zName2Enum(char* name, zEnum2NameMap_t arr[], int nSize, int bAppro)
{
int i;
for(i=0; i<nSize; i++)
{
if(bAppro)
{
if(strcasestr(arr[i].name, name)) return arr[i].e;
}
else
{
if(!strcmp(arr[i].name, name)) return arr[i].e;
}
}
return -1;
}
static int zEnumMapShow(zEnum2NameMap_t arr[], int nSize)
{
int i;
for(i=0; i<nSize; i++)
{
printf("%3d %d-> %s \n", i, arr[i].e, arr[i].name);
}
return 0;
}
#endif /*ENUM_PRIMARY_FUNCTIONS*/
#include "example_map.h"
#include "example.h"
zEnum2NameMap_t InfoStateE_map_t[]=
{
{eInfoStateIdle, "eInfoStateIdle"},
{eInfoStateIniting, "eInfoStateIniting"},
{eInfoStateInited, "eInfoStateInited"},
{eInfoStateReady, "eInfoStateReady"},
{eInfoStateActive, "eInfoStateActive"},
{eInfoStateStandby, "eInfoStateStandby"},
{eInfoStateRelease, "eInfoStateRelease"},
}; /*InfoStateE_map_t*/
const char* InfoStateE2Name(dword_t e)
{
char* pName = zEnum2Name(e, InfoStateE_map_t, TBL_SIZE(InfoStateE_map_t));
if(pName) return pName;
return "*NA*";
}
dword_t InfoStateE2Value(char* name, int bAppro)
{
return zName2Enum(name, InfoStateE_map_t, TBL_SIZE(InfoStateE_map_t), bAppro);
};
int InfoStateEMapShow()
{
return zEnumMapShow(InfoStateE_map_t, TBL_SIZE(InfoStateE_map_t));
};
p_enum.pl是用了我自己做的lex和yacc庫。本來是學(xué)習(xí)編譯原理時(shí)的一些實(shí)驗(yàn)代碼,后來發(fā)現(xiàn)它對(duì)于文本提取還是很強(qiáng)大,于是有了enum相關(guān)的自動(dòng)生成工具。有興趣的,可以參考,或者有問題留言。
嗯,還有一點(diǎn),p_enum.pl不支持enum定義里包含編譯控制宏。如果你有這個(gè)需求,需要自己修改enum.lex和enum.yacc文件來支持。我非常厭惡編譯宏,因此不會(huì)做這個(gè)更新。
如何設(shè)置使用環(huán)境的補(bǔ)充說明:
linux環(huán)境,perl_zlib建議解壓在你的home目錄下。然后在你的用戶配置文件.bashrc(或是.profile,不同linux略有差別)里面添加zlib的路徑。我的配置里是這樣的:
export PATH="$HOME/perl/Debug:$PATH" export PERL5LIB="$HOME/perl/zLib:$HOME/perl5/lib/perl5" PERL_MB_OPT="--install_base \"$HOME/perl5\""; export PERL_MB_OPT; PERL_MM_OPT="INSTALL_BASE=$HOME/perl5"; export PERL_MM_OPT;
這當(dāng)中只有PERL5LIB里的zLib路徑是必須的。perl5是我用來裝額外的perl庫用的,一起貼出來供參考。
windows環(huán)境,需要先運(yùn)行zlib.bat來設(shè)置環(huán)境變量,然后才能運(yùn)行p_enum.pl。當(dāng)然,你還要確認(rèn)安裝了activeperl。
相關(guān)文章
C++基于消息隊(duì)列的多線程實(shí)現(xiàn)示例代碼
這篇文章主要給大家介紹了關(guān)于C++基于消息隊(duì)列的多線程實(shí)現(xiàn)的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用C++具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧2019-04-04
C++ 中 const和static readonly區(qū)別
這篇文章主要介紹了C++ 中 const和static readonly區(qū)別的相關(guān)資料,需要的朋友可以參考下2017-05-05
解析C++中的for循環(huán)以及基于范圍的for語句使用
這篇文章主要介紹了解析C++中的for循環(huán)以及基于范圍的for語句使用,是C++入門學(xué)習(xí)中的基礎(chǔ)知識(shí),需要的朋友可以參考下2016-01-01
C語言數(shù)組應(yīng)用實(shí)現(xiàn)三子棋游戲
這篇文章主要為大家詳細(xì)介紹了C語言數(shù)組應(yīng)用實(shí)現(xiàn)三子棋游戲,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-06-06
typedef和#define用法區(qū)別總結(jié)
在C還是C++代碼中,typedef都使用的很多,在C代碼中尤其多,typedef與#define有些相似,其實(shí)是不同的,特別是在一些復(fù)雜的用法上,下面這篇文章主要給大家介紹了關(guān)于typedef和#define用法區(qū)別總結(jié)的相關(guān)資料,需要的朋友可以參考下2023-06-06

