c如何在枚举和变量间建立key value 关系

_Ryan_Wang 2016-01-21 04:57:06
如题,C环境 ,既想可以对结构体成员赋值,又想可以取得结构体成员的值。想优化

struct STR
{
u32 ulLocReportPolicy;
......
u16 ......
u8 ......
}
u8 arr[1000] = {0};
STR* pMTParamSetting = (STR*)&arr;
Enum E
{A,B,C,D,E,F,G,H,I,J,K......
}

void setParam(u16 uiParamId, u8* pParam)
{
switch(uiParamId)
{
case LOC_REPORT_POLICY:
pMTParamSetting->ulLocReportPolicy = ulParam;
break;
case A:
pMTParamSetting->ulLocReportPlan = ulParam;
break;
case B:
pMTParamSetting->ulUnlRepTInterval = ulParam;
break;
case C:
pMTParamSetting->ulAcOffRepTInterval = ulParam;
break;
case D:
pMTParamSetting->ulAcOnRepTInterval = ulParam;
break;
case E:
pMTParamSetting->ulEmptyRepTInterval = ulParam;
break;
case F:
pMTParamSetting->ulLoadRepTInterval = ulParam;
break;
case G:
pMTParamSetting->ulSleepRepTInterval = ulParam;
break;
case H:
pMTParamSetting->ulEmyRepTInterval = ulParam;
break;
case I:
pMTParamSetting->ulUnlRepDInterval = ulParam;
break;
case J:
pMTParamSetting->ulAcOffRepDInterval = ulParam;
break;
case K:
pMTParamSetting->ulAcOnRepDInterval = ulParam;
break;
case L:
pMTParamSetting->ulEmptyRepDInterval = ulParam;
break;
case M:
pMTParamSetting->ulLoadRepDInterval = ulParam;
break;
case N:
pMTParamSetting->ulSleepRepDInterval = ulParam;
break;
case O:
pMTParamSetting->ulEmyRepDInterval = ulParam;
break;
case P:
pMTParamSetting->ulConerSupAngle = ulParam;
break;
default:
setMultiMediaParam(uiParamId, pParam);
break;
}
}
代码为简单说明,楼主想过建表和hash的方式进行实现,但是表中都是常量与枚举配对,结构体中成员为变量,这时候如何简化switch呢,通过通用的for进行对结构体中成员进行访问,赋值呢??请朋友们解惑~
...全文
355 15 打赏 收藏 转发到动态 举报
写回复
用AI写文章
15 条回复
切换为时间正序
请发表友善的回复…
发表回复
赵4老师 2016-01-23
  • 打赏
  • 举报
回复
引用 7 楼 u012560967 的回复:
[quote=引用 3 楼 u012560967 的回复:]

void setParam(u16 uiParamId, u8* pParam)
{
   for(int i =0; i < sizeof(arr); ++i)
  {
    if(uiParamId = arr[i].id)
    {
      * (pMTParamSetting+arr[i].addr) = pParam;
    }
  }
}
写错了个地方。。。 另,
引用 6 楼 zhao4zhong1 的回复:
swith case 这个世界上唯一不变的就是变化。请拥抱变化。
赵老师的意思就是,我写300多个case是可以的么??[/quote] 就算你写30000个case,没准仍然比map效率高。
paschen 2016-01-22
  • 打赏
  • 举报
回复
引用 12 楼 u012560967 的回复:
[quote=引用 9 楼 paschen 的回复:] [quote=引用 2 楼 paschen 的回复:] 建立一个ENUM值与需要赋值的结体体成员在结构体中偏移量的关系
C语言结构体没问题,另外可以通过一个宏求得偏移量,而不用自己去数[/quote] 嗯。我也觉得自己数很麻烦,可是如果通过一个宏求得偏移量(类似sizeof()?)如何建立起类似id和addr的数组,如何通过id(而非地址)进行赋值和访问呢?
引用 6 楼 zhao4zhong1 的回复:
swith case 这个世界上唯一不变的就是变化。请拥抱变化。
谢谢,说的很对,这个帖子就是单纯的想对结构体成员赋值进行理解,只有用不同途径完成相同功能,理解的才能更深刻不是么?[/quote] #define FIELD_OFFSET(type, field) ((LONG)(LONG_PTR)&(((type *)0)->field)) type结构体类型名,field该结构体中的成员名字
_Ryan_Wang 2016-01-22
  • 打赏
  • 举报
回复
引用 9 楼 paschen 的回复:
[quote=引用 2 楼 paschen 的回复:] 建立一个ENUM值与需要赋值的结体体成员在结构体中偏移量的关系
C语言结构体没问题,另外可以通过一个宏求得偏移量,而不用自己去数[/quote] 嗯。我也觉得自己数很麻烦,可是如果通过一个宏求得偏移量(类似sizeof()?)如何建立起类似id和addr的数组,如何通过id(而非地址)进行赋值和访问呢?
引用 6 楼 zhao4zhong1 的回复:
swith case 这个世界上唯一不变的就是变化。请拥抱变化。
谢谢,说的很对,这个帖子就是单纯的想对结构体成员赋值进行理解,只有用不同途径完成相同功能,理解的才能更深刻不是么?
赵4老师 2016-01-22
  • 打赏
  • 举报
回复
不要低估编译器生成Release版switch语句时选择优化算法的智商。 理解讨论之前请先学会如何观察! 计算机组成原理→DOS命令→汇编语言→C语言(不包括C++)、代码书写规范→数据结构、编译原理、操作系统→计算机网络、数据库原理、正则表达式→其它语言(包括C++)、架构…… 对学习编程者的忠告: 多用小脑和手,少用大脑、眼睛和嘴,会更快地学会编程! 眼过千遍不如手过一遍! 书看千行不如手敲一行! 手敲千行不如单步一行! 单步源代码千行不如单步Debug版对应汇编一行! 单步Debug版对应汇编千行不如单步Release版对应汇编一行! 不会单步Release版对应汇编?在你想单步Release版C/C++代码片断的前面临时加一句DebugBreak();重建所有,然后在IDE中运行。(一般人我不告诉他!) VC调试时按Alt+8、Alt+7、Alt+6和Alt+5,打开汇编窗口、堆栈窗口、内存窗口和寄存器窗口看每句C对应的汇编、单步执行并观察相应堆栈、内存和寄存器变化,这样过一遍不就啥都明白了吗。 对VC来说,所谓‘调试时’就是编译连接通过以后,按F10或F11键单步执行一步以后的时候,或者在某行按F9设了断点后按F5执行停在该断点处的时候。 (Turbo C或Borland C用Turbo Debugger调试,Linux或Unix下用GDB调试时,看每句C对应的汇编并单步执行观察相应内存和寄存器变化。) 不要迷信书、考题、老师、回帖; 要迷信CPU、编译器、调试器、运行结果。 并请结合“盲人摸太阳”和“驾船出海时一定只带一个指南针。”加以理解。 任何理论、权威、传说、真理、标准、解释、想象、知识……都比不上摆在眼前的事实! 有人说一套做一套,你相信他说的还是相信他做的? 其实严格来说这个世界上古往今来所有人都是说一套做一套,不是吗? 不要写连自己也预测不了结果的代码!
赵4老师 2016-01-22
  • 打赏
  • 举报
回复
引用 7 楼 u012560967 的回复:
[quote=引用 3 楼 u012560967 的回复:]

void setParam(u16 uiParamId, u8* pParam)
{
   for(int i =0; i < sizeof(arr); ++i)
  {
    if(uiParamId = arr[i].id)
    {
      * (pMTParamSetting+arr[i].addr) = pParam;
    }
  }
}
写错了个地方。。。 另,
引用 6 楼 zhao4zhong1 的回复:
swith case 这个世界上唯一不变的就是变化。请拥抱变化。
赵老师的意思就是,我写300多个case是可以的么??[/quote] Why not !?
char* TransOperType(int nOperType) {
    switch (nOperType) {
    case OPER_UNKNOWN:              return "UNKNOWN";
    case OPER_PLAY:                 return "PLAY";
    case OPER_RECORD:               return "RECORD";
    case OPER_GETDIG:               return "GETDIG";
    case OPER_ACCEPTCALL:           return "ACCEPTCALL";
    case OPER_ANSWERCALL:           return "ANSWERCALL";
    case OPER_MAKECALL:             return "MAKECALL";
    case OPER_DROPCALL:             return "DROPCALL";
    case OPER_SETBILLING:           return "SETBILLING";
    case OPER_SENDMOREINFO:         return "SENDMOREINFO";
    case OPER_DLCACHE:              return "DLCACHE";
    case OPER_DLMEM:                return "DLMEM";
    case OPER_STOPCH:               return "STOPCH";
    case OPER_PUTEVT:               return "PUTEVT";
    case OPER_SYSNOTIFY:            return "SYSNOTIFY";
    case OPER_CST:                  return "CST";
    case OPER_GETTRCOUNT:           return "GETTRCOUNT";
    case OPER_XOIP_SETRESATTR:      return "OPER_XOIP_SETRESATTR";
    case OPER_XOIP_GETRESATTR:      return "OPER_XOIP_GETRESATTR";
    case OPER_XOIP_GETSSINFO:       return "OPER_XOIP_GETSSINFO";
    case OPER_XOIP_STARTMEDIA:      return "OPER_XOIP_STARTMEDIA";
    case OPER_XOIP_STOP:            return "OPER_XOIP_STOP";
    case OPER_XOIP_SENDDIGITS:      return "OPER_XOIP_SENDDIGITS";
    case OPER_XOIP_ENABLEEVENT:     return "OPER_XOIP_ENABLEEVENT";
    case OPER_XOIP_DISABLEEVENT:    return "OPER_XOIP_DISABLEEVENT";
    case OPER_XOIP_RECEIVEDIGITS:   return "OPER_XOIP_RECEIVEDIGITS";
    case OPER_XOIP_SENDRFC2833:     return "OPER_XOIP_SENDRFC2833";
    case OPER_SENDCPG:              return "OPER_SENDCPG";
    case OPER_CALLPROCEEDING:       return "OPER_CALLPROCEEDING";
    case OPER_CALLPROGRESS:         return "OPER_CALLPROGRESS";
    case OPER_SETUPACK:             return "OPER_SETUPACK";
    case OPER_SIP_SENDREINVITE:     return "OPER_SIP_SENDREINVITE";
    case OPER_SIP_SENDREINVITEACK:  return "OPER_SIP_SENDREINVITEACK";
    case OPER_SIP_SENDREGISTER:     return "OPER_SIP_SENDREGISTER";
    case OPER_XOIP_SWITCH_VF:       return "OPER_XOIP_SWITCH_VF";
    case OPER_SIP_SENDINFO:         return "OPER_SIP_SENDINFO";
    case OPER_SIP_SENDINFOACK:      return "OPER_SIP_SENDINFOACK";
    case OPER_NR_SCROUTE:           return "OPER_NR_SCROUTE";
    case OPER_NR_SCUNROUTE:         return "OPER_NR_SCUNROUTE";
    case OPER_SIP_SENDREGISTERACK:  return "OPER_SIP_SENDREGISTERACK";
    case OPER_SIP_SENDTRYING:       return "OPER_SIP_SENDTRYING";
    case OPER_DT_SETTSSIG:          return "OPER_DT_SETTSSIG";
    case OPER_DT_GETTSSIG:          return "OPER_DT_GETTSSIG";
    case OPER_SIP_SENDSUBSCRIBE:    return "OPER_SIP_SENDSUBSCRIBE";
    case OPER_SIP_SENDNOTIFYACK:    return "OPER_SIP_SENDNOTIFYACK";
    case OPER_GETCONFENERGY:        return "OPER_GETCONFENERGY";
    case OPER_ESTCONF:              return "OPER_ESTCONF";
    case OPER_ADDCONF:              return "OPER_ADDCONF";
    case OPER_REMCONF:              return "OPER_REMCONF";
    case OPER_DELCONF:              return "OPER_DELCONF";
    case OPER_SETCDE:               return "OPER_SETCDE ";
    case OPER_ESTCONF_EX:           return "OPER_ESTCONF_EX";
    case OPER_ADDCONF_EX:           return "OPER_ADDCONF_EX";
    case OPER_REMCONF_EX:           return "OPER_REMCONF_EX";
    case OPER_SETCDE_EX:            return "OPER_SETCDE_EX";
    case OPER_SETLMASKEX:           return "OPER_SETLMASKEX";
    case OPER_SS7_SENDEXT:          return "OPER_SS7_SENDEXT";
    case OPER_FXS_SEND:             return "OPER_FXS_SEND";
    case OPER_FXS_RECV:             return "OPER_FXS_RECV";
    case OPER_MO_SETHOOK:           return "OPER_MO_SETHOOK";
    case OPER_MO_DIAL:              return "OPER_MO_DIAL";
    case OPER_MS_GENRING:           return "OPER_MS_GENRING";
    case OPER_MS_WTRING:            return "OPER_MS_WTRING";
    case OPER_AG_SENDTONE:          return "OPER_AG_SENDTONE";
    case OPER_RECVFSK:              return "OPER_RECVFSK";
    case OPER_SENDFSK:              return "OPER_SENDFSK";
    case OPER_SIP_RECVUPDATE:       return "OPER_SIP_RECVUPDATE";
    case OPER_SIP_SENDUPDATE:       return "OPER_SIP_SENDUPDATE";
    case OPER_SIP_RECVUPDATEACK:    return "OPER_SIP_RECVUPDATEACK";
    case OPER_SIP_SENDUPDATEACK:    return "OPER_SIP_SENDUPDATEACK";
    case OPER_SIP_RECVACK:          return "OPER_SIP_RECVACK";
    case OPER_SIP_SENDACK:          return "OPER_SIP_SENDACK";
    case OPER_SIP_RECVPRACK:        return "OPER_SIP_RECVPRACK";
    case OPER_SIP_SENDPRACK:        return "OPER_SIP_SENDPRACK";
    case OPER_SIP_SENDPRACKACK:     return "OPER_SIP_SENDPRACKACK";
    case OPER_SIP_RECVPRACKACK:     return "OPER_SIP_RECVPRACKACK";
    default: break;
    }
    return "UNKNOWN";
}
paschen 2016-01-22
  • 打赏
  • 举报
回复
引用 2 楼 paschen 的回复:
建立一个ENUM值与需要赋值的结体体成员在结构体中偏移量的关系
C语言结构体没问题,另外可以通过一个宏求得偏移量,而不用自己去数
_Ryan_Wang 2016-01-22
  • 打赏
  • 举报
回复
引用 3 楼 u012560967 的回复:

void setParam(u16 uiParamId, u8* pParam)
{
   for(int i =0; i < sizeof(arr); ++i)
  {
    if(uiParamId = arr[i].id)
    {
      * (pMTParamSetting+arr[i].addr) = pParam;
    }
  }
}
写错了个地方。。。 另,
引用 6 楼 zhao4zhong1 的回复:
swith case 这个世界上唯一不变的就是变化。请拥抱变化。
赵老师的意思就是,我写300多个case是可以的么??
_Ryan_Wang 2016-01-22
  • 打赏
  • 举报
回复
void setParam(u16 uiParamId, u8* pParam) { for(int i =0; i < sizeof(arr)/sizeof(M); ++i) { if(uiParamId = arr[i].id) { * (pMTParamSetting+arr[i].addr) = pParam; } } }
赵4老师 2016-01-22
  • 打赏
  • 举报
回复
swith case 这个世界上唯一不变的就是变化。请拥抱变化。
_Ryan_Wang 2016-01-22
  • 打赏
  • 举报
回复
引用 4 楼 u012560967 的回复:
[quote=引用 2 楼 paschen 的回复:] 建立一个ENUM值与需要赋值的结体体成员在结构体中偏移量的关系
谢谢,这样的确是我需要的,但是用偏移量会不会有危险,结构体在内存中的地址是不是因为内存对齐导致不连续,如果使用这样的方法,需要注意什么呢,需不需要对结构体成员位置进行调整呢?[/quote] sorry,忘问了一句,这样写的话,是不是每次需要变更结构体的时候,都需要变更对应的枚举吧。
_Ryan_Wang 2016-01-22
  • 打赏
  • 举报
回复
引用 2 楼 paschen 的回复:
建立一个ENUM值与需要赋值的结体体成员在结构体中偏移量的关系
谢谢,这样的确是我需要的,但是用偏移量会不会有危险,结构体在内存中的地址是不是因为内存对齐导致不连续,如果使用这样的方法,需要注意什么呢,需不需要对结构体成员位置进行调整呢?
_Ryan_Wang 2016-01-22
  • 打赏
  • 举报
回复
引用 1 楼 jiqiang01234 的回复:
如果结构体中的变量长度都相同,可以使用偏移量直接赋值
谢谢1楼的回答,用偏移量赋值的确是我期望的那样,但是由于结构体中成员类型有不同,所以需要用3楼的方法建立一个枚举或者数组记录对应成员位置,由于我之前用的
Enum E
{A,B,C,D,E,F,G,H,I,J,K......
}
为协议中的ID值,所以需要建立一个

typedef struct Map
{
   int id;
   int addr;
}M;
Enum E
{A,B,C,D,E,F,G,H,I,J,K......
}
Enum Ad
{
  ONE = 0,TWO = 4...
};
M arr[1000] = {
{A, ONE},
{B, TWO},
{C,THREE}...
};
当我用的时候

void setParam(u16 uiParamId, u8* pParam)
{
   for(int i =0; i < sizeof(arr); ++i)
  {
    if(uiParamId = arr[i].id)
    {
      * (pMTParamSetting+arr[i].addr) = pParam;
    }
  }
}
_Ryan_Wang 2016-01-22
  • 打赏
  • 举报
回复
引用 13 楼 paschen 的回复:
[quote=引用 12 楼 u012560967 的回复:] [quote=引用 9 楼 paschen 的回复:] [quote=引用 2 楼 paschen 的回复:] 建立一个ENUM值与需要赋值的结体体成员在结构体中偏移量的关系
C语言结构体没问题,另外可以通过一个宏求得偏移量,而不用自己去数[/quote] 嗯。我也觉得自己数很麻烦,可是如果通过一个宏求得偏移量(类似sizeof()?)如何建立起类似id和addr的数组,如何通过id(而非地址)进行赋值和访问呢?
引用 6 楼 zhao4zhong1 的回复:
swith case 这个世界上唯一不变的就是变化。请拥抱变化。
谢谢,说的很对,这个帖子就是单纯的想对结构体成员赋值进行理解,只有用不同途径完成相同功能,理解的才能更深刻不是么?[/quote] #define FIELD_OFFSET(type, field) ((LONG)(LONG_PTR)&(((type *)0)->field)) type结构体类型名,field该结构体中的成员名字[/quote] 不错不错,多谢指教了~也感谢1楼和一直都语重心长的赵老师~
paschen 2016-01-21
  • 打赏
  • 举报
回复
建立一个ENUM值与需要赋值的结体体成员在结构体中偏移量的关系
jiqiang01234 2016-01-21
  • 打赏
  • 举报
回复
如果结构体中的变量长度都相同,可以使用偏移量直接赋值

69,373

社区成员

发帖
与我相关
我的任务
社区描述
C语言相关问题讨论
社区管理员
  • C语言
  • 花神庙码农
  • 架构师李肯
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧