这一章主要介绍C语言的结构和其他数据形式,是学习算法和数据结构的重点。
1.示例代码
/*book.c -- 仅包含一本书的图书目录*/ #include <stdio.h> #define MAXTITL 41 #define MAXAUTL 31 struct book { /* data */ char title[MAXTITL]; char author[MAXAUTL]; float value; }; int main(void) { struct book library; /* 把library声明为book类型的变量 */ printf("Please enter the book title.\n"); gets(library.title); printf("Now enter the author.\n"); gets(library.author); printf("Now enter the value.\n"); scanf("%f", &library.value); printf("%s by %s: $%.2f\n", library.title, library.author, library.value); printf("%s: \"%s\" ($%.2f)\n", library.author, library.title, library.value); printf("Done.\n"); return 0; }
这个示例代码展示了如何建立结构声明:并没有创建一个实际的数据对象,而是描述了组成这类对象的元素(类似C++中的模版)。实际上,book的结构声明创建了一个名为struct book的新类型。也就是说
struct book library;
等价于
struct book { char title[MAXTITL]; char author[MAXAUTL]; float value; } library;
也可以不用标记book,但是这样就只能使用一次该模版。结构数组表示如下。
struct book library[MAXBKS];
2.指向结构的指针
为什么要使用指向结构的指针:1.指向结构的指针通常比结构本身更容易操作;2.在一些早期的C实现中,结构不能作为参数被传递给函数,但是结构的指针可以;3.很多奇妙的数据表示都使用了包含指向其他结构的指针的结构。
/* friend.c -- 使用指向结构的指针 */ #include <stdio.h> #define LEN 20 struct name { /* data */ char first[LEN]; char last[LEN]; }; struct guy { /* data */ struct name handle; char favfood[LEN]; char job[LEN]; float income; }; int main (void) { struct guy fellow[2] = { {{"Ewen", "Villard"}, "grilled salmon", "personality coach", 58112.0 }, {{"Rodney", "Swillbelly"}, "tripe", "tabloid editor", 232400.0 } }; struct guy * him; /* 这是一个指向结构的指针 */ printf ("address #1: %p #2: %p\n", &fellow[0], &fellow[1]); him = &fellow[0]; printf ("pointer #1: %p #2: %p\n", him, him + 1); printf ("him->income is $%.2f: (*him).income is $%.2f\n", him->income, (*him).income); him++; printf ("him->favfood is %s: him->handle.last is %s\n", him->favfood, him->handle.last); return 0; }
看懂了上面的代码,基本就知道如何使用结构指针。需要注意的是,一个结构的名字不是该结构的地址,这个和数组不一样,必须使用&运算符。还一个就是,后跟->运算符的结构指针和后跟.(点)的结构名是一样的。
那我们是选择结构还是结构指针呢?两者各有优缺点。把指针当作参数既能工作早期C也能工作在较新的C,而且执行起来很快,每次只需要传递单个地址。缺点是缺少对数据的保护。不过我们可以用const限定词解决这个问题。而把结构作为参数传递比直接处理原数据安全,编程风格也更清晰。
3.另外三种处理数据的特性
这里简单说一下另外三种处理数据的特性:联合、枚举和typedef。
联合是一个能在同一个存储空间里(但是不同时)存储不同类型数据类型的数据类型。各个变量是“互斥”的——缺点就是不够“包容”;但优点是内存使用更为精细灵活,也节省了内存空间。
枚举型是一个集合,集合中的元素(枚举成员)是一些命名的整型常量,元素之间用逗号,隔开。本质上是int类型。
typedef是声明新的类型名来代替原有的类型名。