Skip to content

Instantly share code, notes, and snippets.

@lixingcong
Last active March 23, 2017 02:58
Show Gist options
  • Save lixingcong/5ed663dbb0343da563df10570370c878 to your computer and use it in GitHub Desktop.
Save lixingcong/5ed663dbb0343da563df10570370c878 to your computer and use it in GitHub Desktop.
读取结构体C
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#define is_char_num(c) ((c>='0')&&(c<='9'))
/*
* brief: 从字符串取出数字
* 注意str字符串结束符要有NULL,否则指针越界
* param: str 字符串指针
* offset 数字宽度
* return: int 数字
*/
int getIntNumFromString(char *str, int *offset){
int buf_i=0;
char buf[20],c_tmp;
*(offset)=0;
do{
c_tmp=*(str+(*offset));
buf[buf_i++]=c_tmp;
(*offset)++;
}while(is_char_num(c_tmp));
(*offset)--;
buf_i--;
buf[buf_i]=0; // NULL
return atoi(buf);
}
/*
* brief: 打印出结构体的成员
* 注意有的编译器默认启用4字节对齐。此时考虑对齐后的偏移量
* param: fmt 格式控制串
* 格式为 "偏移地址,输出格式,数据类型;"
* 例如 "400,%d,i;" 表示偏移400,输出格式是"%d",数据为int型
* 数据类型前加上数字可以表示重复次数
* 例如 "400,%d,6i;" 表示偏移400,输出格式是"%d",输出6个int型数据
* 不同格式可以串联使用
* 例如 "400,%d,6i;500,%s,s"
* data 输入结构体的指针
* return: void
*/
void print1(char *fmt, void *data){
#define PRINT_FORMAT_FLOAT 'f'
#define PRINT_FORMAT_DOUBLE 'd'
#define PRINT_FORMAT_INT 'i'
#define PRINT_FORMAT_UINT 'I'
#define PRINT_FORMAT_CHAR 'c'
#define PRINT_FORMAT_UCHAR 'C'
#define PRINT_FORMAT_SHORT 'h'
#define PRINT_FORMAT_USHORT 'H'
#define PRINT_FORMAT_STRING 's'
// 控制串
char fmt_printf[20]={0};
// 临时buffer
int i,char_num_offset;
// 全局串的下标
int index=0;
int offset_base,repeat,offset;
// for beautify output
printf("\r\n-------\r\n");
while(index<strlen(fmt)){
// 取出偏移
offset_base=getIntNumFromString(fmt+index,&char_num_offset);
index+=char_num_offset;
if(*(fmt+index)!=','){
return;
}
index++; // skip ','
// 取出printf格式符
i=0;
while(*(fmt+index)!=','){
fmt_printf[i++]=*(fmt+(index++));
}
fmt_printf[i]=0; // NULL
index++; // skip ','
// 取出重复次数
if(is_char_num(*(fmt+index))){
repeat=getIntNumFromString(fmt+index,&char_num_offset);
index+=char_num_offset;
}else{
repeat=1;
}
// 输出结果
for(i=0;i<repeat;i++){
// 取出数据类型
switch(*(fmt+index)){
case PRINT_FORMAT_FLOAT:
offset=offset_base+i*sizeof(float);
printf("offset=%d, data=",offset);
printf(fmt_printf,*(float *)(data+offset));
break;
case PRINT_FORMAT_DOUBLE:
offset=offset_base+i*sizeof(double);
printf("offset=%d, data=",offset);
printf(fmt_printf,*(double *)(data+offset));
break;
case PRINT_FORMAT_INT:
offset=offset_base+i*sizeof(int);
printf("offset=%d, data=",offset);
printf(fmt_printf,*(int *)(data+offset));
break;
case PRINT_FORMAT_UINT:
offset=offset_base+i*sizeof(unsigned int);
printf("offset=%d, data=",offset);
printf(fmt_printf,*(unsigned int*)(data+offset));
break;
case PRINT_FORMAT_STRING:
case PRINT_FORMAT_CHAR:
offset=offset_base+i*sizeof(char);
printf("offset=%d, data=",offset);
printf(fmt_printf,*(char *)(data+offset));
break;
case PRINT_FORMAT_UCHAR:
offset=offset_base+i*sizeof(unsigned char);
printf("offset=%d, data=",offset);
printf(fmt_printf,*(unsigned char*)(data+offset));
break;
case PRINT_FORMAT_SHORT:
offset=offset_base+i*sizeof(short);
printf("offset=%d, data=",offset);
printf(fmt_printf,*(short *)(data+offset));
break;
case PRINT_FORMAT_USHORT:
offset=offset_base+i*sizeof(unsigned short);
printf("offset=%d, data=",offset);
printf(fmt_printf,*(unsigned short*)(data+offset));
break;
default:
printf("data type error!");
return;
break;
}
printf("\n");
}
index++; // skip data type
if(*(fmt+index)!=';' || *(fmt+index)==0){
return;
}
index++; // skip ';'
}
}
#undef is_char_num
typedef struct{
int a;
float c;
unsigned char b,d;
}s1_t;
typedef struct{
int a;
unsigned char b,d;
float c;
}s2_t;
int main(int argc, char **argv) {
s1_t s1;
s2_t s2;
s2.a=s1.a=100;
s2.b=s1.b='b';
s2.c=s1.c=5.23;
s2.d=s1.d='d';
// 说明按4字节对齐
printf("s1:\n");
print1("0,%d,i;4,%f,f;8,%c,2c",&s1);
printf("s2:\n");
print1("0,%d,i;4,%c,2c;8,%f,f",&s2);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment