结构体示例
结构体带来抽象的思维,即将一组关联的属性聚集起来,这引发的是设计思维的转变。
一个矩形
抽象的含义可能比较难以解释,我们从矩形开始,逐步领悟数据抽象的含义。一个画图程序要想绘制出矩形,就需要对矩形的概念有所认知,数学上有一个直角的平行四边形是矩形;而程序中矩形一种可能的表达方式是由左上角坐标、宽度、高度构成,由于这些数据全部是同一事物(矩形)相关的,用结构体将它们组织起来很自然。
struct RECT
{
int left; // 左
int top; // 上角坐标(假想的坐标系左上角为0,0点)
int width; // 宽度(水平方向)
int height; // 高度(垂直方向)
};
或许从另一角度考虑,这种记录 width、height 的RECT结构对于只需要坐标位置的图形绘制函数并不友好,此时矩形的另一种表达方式如下:
struct RECT
{
int left, top; // 左上角坐标
int right, bottom; // 右下角坐标
};
可以看出,对事物不同角度的理解,程序上就会形成不同的描述,这种从事物与需求形成的对数据的表达,就是数据抽象。再比如,我们需要用程序的语言去描述一个柜子,对于一个房屋订制软件,更多的需要宽度、高度、深度这样的试题信息,如:
struct CUPBOARD
{
float width;
float height;
float deep;
};
而对于一个三维建模软件,一个柜子可以描述为网格与材质的集合。
struct CUPBOARD
{
float *vertices; // 网格顶点数据
int *indices; // 顶点索引数据
int mtl; // 材质索引信息
};
所以,我们所说的抽象,是指数据抽象,就是从程序需求的角度出发,构造出对一个事物的数据描述。
一个歌单
这是一款音乐软件中的歌单图片,现在我们要以程序的手法构造这样的清单,会有怎样的设计呢?

首先我们将歌单看作是单一歌曲的集合;歌单中的每一首歌曲,都有相同的属性集合,如序号、歌名、演唱家、所属专辑、时长。整体设计上,我们可以抽象出一个单曲描述,最后由数组将它们组织起来即可。现在看看这个抽象需要哪些数据集合。
- 首先考虑一下序号属性是否需要,如果我们有一个曲目数组,完全可以借助循环索引来代替它,因而这一属性并不是必须的。
- 接下来是心形喜欢标志,这可以用一个bool变量描述。
- 后面的歌名、演唱家、所属专辑显然是字符串,可以使用char[]来描述。
- 最后一个要注意的就是时长,直观表述是使用float类型,但是这在输出上可能会比较麻烦。比如时长4分32秒,要求的输出是04:32而不是4.32,把浮点分解为两部分并格式化输出,稍显麻烦,那我们可以选择以秒或毫秒为单位的int值,输出时正确的格式化即可。
这样,我们的歌曲结构就像下面这样表达了。
struct MUSICINFO
{
char title[40]; // 歌名
char singer[40]; // 演唱家
char album[64]; // 专辑
int duration; // 时长
bool like; // 喜欢标志
};
格式化输出也很必要,将整个歌单通过一个函数输出,可以达到复用的目的。
void print_music_info(struct MUSICINFO infos[], int count)
{
char buffer[256];
printf("标题\t\t 收藏 \t 艺术家 \t 专辑 \t\t 时长\n");
printf("===============================================================\n");
for (int i = 0; i < count; i++)
{
struct MUSICINFO *mi = &infos[i];
int minutes = mi->duration / 60;
int seconds = mi->duration % 60;
sprintf(buffer, "%s\t %d\t %s\t\t %s\t %02d:%02d",
mi->title, mi->like,
mi->singer, mi->album,
minutes, seconds);
printf("%s\n", buffer);
}
}
最后通过主函数将这些驱动起来。
int main()
{
struct MUSICINFO mis[] =
{
{ "比目鱼的心事", "刘芮", "比目鱼的心事", 180 + 31, false },
{ "C语言情诗", "五音", "C语言情诗", 241, true },
};
print_music_info(mis, sizeof(mis) / sizeof(mis[0]));
return 0;
}

陕公网安备61011202001108号