C Primer+Plus(十四)结构和其他数据形式
第14章 结构和其他数据形式
基础概念性的内容在谭浩强C的笔记里已经记录过,不再抄记。选出以下重点巩固:
1、结构的指定初始化项目
C99支持该功能;对于:
struct stu
{
char name[10];
int age;
float score;
}
可以在定义其结构变量时候初始化该变量的某几项数据,如下:
struct stu s1={.name[10]="Tommy",.score=97.5};
struct stu s2={.age=15};
2、结构数组
对于上述stu结构,创建其变量数组:
struct stu s[10];
成员的引用标识:
s[0].name[10];s[9].score;
3、指向结构的指针
对于上述stu结构,创建其指针变量:
struct stu *ps;
结构指针变量对成员的引用标识:
ps->name[10];ps->score;
若有:struct stu fx,s[10];
则可如下对结构指针变量进行初始化;
ps=&fx;
ps=&s[i];//0<=i<=9;
4、结构信息作为函数参数
(1)结构成员信息作为参数
(2)如下例:
a:以结构地址(指针)作为参数
struct stu { char name[10]; int age; float score; } //结构原型 struct stu *ps,s1; //结构变量和结构指针变量声明 s1={"tommy",15,87.5}; //结构变量赋值 ps=&s1; //结构指针变量赋值 void show_age(struct stu *); //函数声明 show_age(ps); void show_age(struct stu *p) { printf("age=%d.\n",p->age); } //函数原型
b:直接以结构作为参数
struct stu { char name[10]; int age; float score; } //结构原型 struct stu s1; //结构变量声明 s1={"tommy",15,87.5}; //结构变量赋值 void show_age(struct stu x); //函数声明 show_age(s1); void show_age(struct stu m) { printf("age=%d.\n",m.age); } //函数原型
5、结构变量之间的直接赋值
struct stu s1,s2;
s1={"wangming",16,99.0};
s2=s1; //可直接赋值整个结构
6、使用结构数组的函数
注意:结构变量名不等同于结构变量的首地址;而数组名等同于该数组首地址。
对于结构数组而言,其首先是一个数组,故结构数组名等同于该结构数组首地址。
7、联合(union)
联合是一个能在同一个存储空间内,但不同时,存储不同类型数据的数据类型。
如下联合模板例子:
union hold{
int digit;
double bigfl;
char letter;
}
关键词union限定该数据类型在一个时刻只能含有三个成员中的其中一个。
union hold A;
A.letter="R";
union hold B=A;
union hold C={88};
union hold D={.gibfl=118.2};
B.letter="A"; //可以更改值
B.digit=15; //也可以更换成员类型,此时内存消除之前的A字符,使用2字节存储15数字
B.bigfl=15.09; //此时消除15,使用4字节存储浮点数据15.09
8、枚举类型(enumerated type)
9、typedef
可以用typedef创建某一类型的名字,如:
type unsigned char Byte; //为unsigned char类型创建了Byte名称
Byte a; //创建Byte类型的变量a
10、指向函数的指针
void ToUpper(char *); //空返回值的函数
void (*pf)(char *); //指针,指向空返回值的函数
void *pf(char *);//函数,返回值是一个指针
void ToUpper(char *); void ToLower(char *); int round(double); void (*pf)(char *); void X1(int *);
pf=ToUpper; //合法,pf指向为空返回值和字符型参数的函数,符合ToUpper描述 pf=ToLower; //合法,同上原因 pf=X1; //不合法,参数不匹配
pf=round; //不合法,pf指向空返回值的函数,而round是一个返回值为整型的函数 pf=ToLower(); //不合法,pf是指针变量,ToLower()标识的是函数的返回值
综上,要使用一个指向函数的指针,首先要定义,在使用的时候,要使该指针指向某一函数,并且该函数的返回类型和参数类型均须与函数指针定义时候一致。
考虑下面这个函数:
void show(void (*pf)(char *),char *str);
函数show有两个参量:函数指针pf(指向一个空返回值和字符参量的函数)、字符指针str。
例14-16的另一种实现方案:
1 #include<stdio.h> 2 #include<string.h> 3 #include<ctype.h> 4 int showmenu(void); 5 typedef void(*V_fp)(char *); //自定义一个函数指针类型 6 void eatline(void); //读至行末 7 void show(V_fp fp,char *str); 8 void ToUpper(char *); //把字符串转为大写 9 void ToLower(char *); //把字符串转为小写 10 void Transpose(char *); //大小写置换 11 void Dummy(char *); //不改变 12 13 int main(void) 14 { 15 char line[81]; 16 char copy[81]; 17 int choice; 18 V_fp pfun; 19 V_fp x[4]={ToUpper,ToLower,Transpose,Dummy}; 20 puts("Enter a string(empty line to quit):"); 21 while(gets(line)!=NULL&&line[0]!='\0') //将输入赋给line 22 { 23 choice=showmenu(); 24 while(choice>=0&&choice<4) 25 { 26 strcpy(copy,line); 27 show(x[choice],copy); 28 choice=showmenu(); 29 } 30 puts("Enter a string(empty line to quit):"); 31 } 32 puts("Bye!"); 33 return 0; 34 } 35 36 int showmenu(void) 37 { 38 char ans; 39 int i; 40 puts("Enter menu choice:"); 41 puts("u)uppercase l)lowercase"); 42 puts("t)transposed case o)original case"); 43 puts("n)next string"); 44 ans=getchar(); 45 ans=tolower(ans); 46 eatline(); //消化缓冲区内字符 47 while(strchr("ulton",ans)==NULL) //若选项不在预设内 48 { 49 puts("please enter a u,l,t,o,or n:"); 50 ans=tolower(getchar()); 51 eatline(); 52 } 53 switch(ans) 54 { 55 case 'u':i=0;break; 56 case 'l':i=1;break; 57 case 't':i=2;break; 58 case 'o':i=3;break; 59 case 'n':i=4;break; 60 } 61 return i; 62 } 63 void eatline(void) 64 { 65 while(getchar()!='\n') 66 continue; 67 } 68 void ToUpper(char *str) 69 { 70 while(*str) 71 { 72 *str=toupper(*str); 73 str++; 74 } 75 } 76 void ToLower(char *str) 77 { 78 while(*str) 79 { 80 *str=tolower(*str); 81 str++; 82 } 83 } 84 void Transpose(char *str) 85 { 86 while(*str) 87 { 88 if(islower(*str)) 89 *str=toupper(*str); 90 else if(isupper(*str)) 91 *str=tolower(*str); 92 str++; 93 } 94 } 95 void Dummy(char *str) 96 { 97 } 98 void show(void(*fp)(char *),char *str) 99 { 100 (*fp)(str); 101 puts(str); 102 }