结构是一个或多个变量的集合,变量可能是不同的类型。结构将一组相关的变量看成一个单元而不是各自独立的实体,因为在设计程序时更有用。
结构的定义:
struct point{ int x; int y; };
x和y是结构point的成员,point是结构标记。比如用结构去声明一个结构型的变量:struct point pt;其中pt即为一个结构变量。
赋值初始化:struct point mapt={320,240};当然除了赋值初始化外,可以用返回相对应类型结构的函数进行初始化。
成员的引用:pt.x,pt.y用来使用结构里的成员。
结构可以嵌套:比如我们想在平面上定一个矩形,那么我们定义两个点(左上角,右下角)即可!
struct rect{ struct point pt1; struct point pt2; };
至少有3种方法来将结构传递到函数中,一个分别传递结构的成员,二是传递整个结构,三是传递指向结构的指针。
第一种,通过x,y坐标构造一个点
struct point makepoint(int x,int y){ struct point temp; temp.x=x; temp.y=y; return temp; }
第二种,修正一个矩形,让右下角的点比左上角的点大
struct rect canonrect(struct rect r) { struct rect temp; temp.pt1.x=min(r.pt1.x,r.pt2.x); temp.pt1.y=min(r.pt1.y,r.pt2.y); temp.pt2.x=max(r.pt1.x,r.pt2.x); temp.pt2.x=max(r.pt1.y,r.pt2.y); return temp; }
第三种:指向结构的指针
struct point *pp;
引入结构里的成员时,(*pp).x和(*pp).y,可以用pp->x和pp->y.
下面我们分析一下几个优先级的问题:
struct { int len; char *str; } *p;
++p->len意思是将len的值+1,区别于(++p)->len。
*p->str,读取的是指针str所指向的对像的值。
*p->str++相当于*(p->str++)即先将指针加1,再取值
*p++->str先读取指针str指向的对象的值,再将p加1。
通过一个C语言关键字的统计程序来说明结构数组的用法。
每一个关键字,我们声明一个结构来存储它,一个成员为字符串用来存储关键字,另一个为整形,用来计数关键字出现的次数。
struct key{ char *word; int count; };
然后我们来声明一个结构数组,来保存C语言中的关键字:
struct key keytab[]={ "auto",0, "break",0, "case",0, /* …… */ "while",0 };
将6.3中的拆半查找中传递数组的方法,换成传递指针的方法。
定义拆半查找的函数原型:
struct key * binsearch(char *word,struct key *keytab,int n)
对比于数组形式的写法:
struct key * binsearch(char *word,struct key keytab[],int n)
下是关键字列表拆半查找的程序:
struct key * binsearch(char *word,struct key *keytab,int n) { int cond; struct key *low=keytab; struct key *high=low+n; struct key *mid; while(low<high) { mid=low+(high-low)/2; if(cond=strcmp(word,mid->word)>0) low=mid; else if(cond<0) high=mid; else { return mid; } } return NULL; }
还是用上面单词统计的例子,想统计每个出现的单词及出现的次数。
这里我们用一个树的结构来解决这个问题
定义一个树结点的结构
struct TreeNode { char *word; int count; struct TreeNode *lNode; struct TreeNode *rNode; };
下面这段代码是将一个单词插入到一个树结构中的代码部分:
char *strdup(char *); void addtree(struct TreeNode *p,char *w) { int cond; if(!p) { p=(struct TreeNode *)malloc(sizeof(struct TreeNode)); if(!p) exit(1); p->word=strdup(w); p->count=1; p->lnode=NULL; p->rnode=NULL; } else if((cond=strcmp(w,p->word))==0) p->count++; else if(cond>0) addtree(p->rnode,w); else addtree(p->lnode,w); }
typedef char *String;
上面的语句中,建立了一新的数据类型名String,用它来代表指向字符的指针,即声明一个字符串类型。
联合是为了让一个变量可以合法的保存多种数据类型中任一种变量类型。
union u_tag{ int ival; float fval; char * sval; }u;
下面是使用的例子:
if (utype==INT) printf("%d",u.ival); else if (utype==FLOAT) printf("%d",u.fval); else if (utype==STRING) printf("%s",u.sval); else printf("bad type!");