数据库存储了几乎所有的业务数据,而这些数据毕竟不是静态的,那么就必然需要我们来写程序完成数据的加工和整合,数据库仅仅保存我们加工整合后的结果,因此必然的,我们需要把数据库中的数据读到程序中,然后加工后再存入数据库,同样必然的,我们需要在程序中维持数据库表的结构,那么很显然,我们需要在程序中定义很多结构体或者联合体数组来保存数据库查询的结果,每个结构体代表了一个纪录,很多纪录就用结构体数组来表示,如此一来,程序就会显得很臃肿,比如会出现下列的结构体:
struct girl {
char *name
int age;
int sexy;
int height;
int weight;
...
}
结构体的大小完全取决于数据库表的列。这样虽然可行但不甚合理,如果我们换一种思路或许能让事情更简单,读了OpenSSL的d2i和i2d的代码,发现人家就没有采用这样臃肿的方式设计,虽然OpenSSL没有涉及数据库但是毕竟涉及到了格式化的文件,比如pem/der文件,我们当前讨论的意义上,这些格式化文件和数据库是一致的,OpenSSL的方式十分值得我们来思考。
我们可以不考虑数据库表的具体性质,仅仅将表的一列作为一个“名称-值”对,这样每一条纪录就可以被看作这样的“对”的数组,数组的大小就是列的数量,如上例的一条纪录{"LiLi",21,1000000...,175,100,...},我们可以以下这样定义{{name,"LiLi"},{age,21},{sexy,1000000...},{height,175},{weight,100},...},为了统一化,我们可以将诸如{name,"LiLi"}的项设计成一个结构体,就是“名称-值”的结构体:
struct abc {
char *name;
char *value;
}
我们看看这样是否合理,又没有改进的空间,...很合理,但是虽然从数据库中读出的结果都是字符串char*类型,但我们的程序需要将之转化为其合理的数据类型才能处理,也就是说value最终并不全是字符串类型,可能是任意类型,name显然就是列名了。既然value可以是任意类型,我们便需要将之定义成联合体:
struct abc {
char *name;
union {
char *db_char; //从数据库中读取的原始数据
int int_value; //如果是int型,则int_value为转为int型的数据,下同...
...
}value;
}
接下来我们看一下还有没有改进的空间,看看name字段,它仅仅表示列名,它真的必不可少吗?不!其实它仅仅起到一个索引的作用,帮助程序找到特定的列,既然我们准备将结构体abc按照纪录列设计成数组,那么数组的下标就能完成此任,再设计一个name字段就是冗余了,所以我们决定砍掉它:
struct abc {
union {
char *db_char; //从数据库中读取的原始数据
int int_value; //如果是int型,则int_value为转为int型的数据,下同...
...
}value;
}
那么数组下标如何索引数据库纪录列,毕竟它仅仅是一些毫无意义的数字,为了使程序有更强的可读性和可维护性,我们需要赋予无意义的数字以意义,于是想到了枚举,于是定义下列枚举:
enum {
GIRL_NAME = 0,
GIRL_AGE,
GIRL_SEXY,
GIRL_HEIGHT,
GIRL_WEIGHT,
...
TOTAL
}
于是我们只需要为每一条数据库纪录分配TOTAL个struct abc即可,然后直接用枚举类型来索引数组特定的元素。最终枚举和联合帮了大忙,枚举赋予了数字以意义,而联合则使得数据定义可以统一,今后写程序时可以借鉴一下这种方式,同时也感慨一下C语言真的很强大。
相关文章
- c语言 位运算符与赋值运算符可以组成复合赋值运算符;例如 a << =2相当于a = a << 2 1、左移运算符(< 左移运算符是用来将一个数的各二进制位左移若干位,移动的位数由右操作数指定(右操作数必须是非负值),其右边空出的位用0填补,高位左移溢出则舍弃该高位。 例如:将a的二进制数左移2位,右边空出的位补0,左边溢出的位舍弃。 若a=15,即00001111(2),左移2,位得00111100(2)。 左移1位相当于该数乘以2,左移2位相当于该数乘以2*2=4,15<<2=60,即乘了4。但此结论只适用于该数左移时被溢出舍弃的高位中不包含1的情况。 假设以一个字节(8位)存一个整数,若a为无符号整型变量,则a=64时,左移一位时溢出的是0,而左移2位时,溢出的高位中包含1。 2、右移运算符(>>) 右移运算符是用来将一个数的各二进制位右移若干位,移动的位数由右操作数指定(右操作数必须是非负值),移到右端的低位被舍弃,对于无符号数,高位补0。对于有符号数,某些机器将对左边空出的部分用符号位填补(即“算术移位”),而另一些机器则对左边空出的部分用0填补(即“逻辑移位”)。 注意:对无符号数,右移时左边高位移入0;对于有符号的值,如果原来符号位为0(该数为正),则左边也是移入0。如果符号位原来为1(即负数),则左边移入0还是1,要取决于所用的计算机系统。有的系统移入0,有的系统移入1。移入0的称为“逻辑移位”,即简单移位;移入1的称为“算术移位”。 例: a的值是八进制数113755: a:1001011111101101 (用二进制形式表示) a>>1: 0100101111110110 (逻辑右移时) a>>1: 1100101111110110 (算术右移时) 在有些系统中,a>>1得八进制数045766,而在另一些系统上可能得到的是145766。Turbo C和其他一些C 编译采用的是算术右移,即对有符号数右移时,如果符号位原来为1,左面移入高位的是1。 拓展资料 运算符含义描述 & 按位与 如果两个相应的二进制位都为1,则该位的结果值为1,否则为0 | 按位或 两个相应的二进制位中只要有一个为1,该位的结果值为1 ^ 按位异或 若参加运算的两个二进制位值相同则为0,否则为1 ~ 取反 ~是一元运算符,用来对一个二进制数按位取反,即将0变1,将1变0 << 左移 用来将一个数的各二进制位全部左移N位,右补0 >> 右移 将一个数的各二进制位右移N位,移到右端的低位被舍弃,对于无符号数,高位补0
- 【C语言】自定义类型——联合体和枚举
- 用C语言联合体和枚举描述数据库
- c语言基础(七)联合体和枚举
- c语言基础(七)联合体和枚举
- C语言关于自定义数据类型之枚举和联合体详解
- C语言自定义类型详解(结构体、枚举、联合体和位段)