先看整体代码
//* book.c -- 一本书的图书目录 */
#include<stdio.h>
#include<string.h>
#define MaxTitle 41 /* 书名的最大长度 + 1 */
#define MaxAuthor 31/* 作者姓名的最大长度 + 1*/
char *s_gets(char *st,int n);
struct book{/* 结构模版:标记是 book */
char title[MaxTitle];
char author[MaxAuthor];
float value;
};
int main(void){
struct book library;/* 把 library 声明为一个 book 类型的变量 */
printf("Please enter the book title.\n");
s_gets(library.title,MaxTitle);/* 访问title部分*/
printf("Now enter the author.\n");
s_gets(library.author,MaxAuthor);
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;
}
char * s_gets(char *st,int n){
char *ret_val;
char *find;
ret_val =fgets(st,n,stdin);//char *fgets(char *string, int n, FILE *stream); 从流stream中读n个字符存入string中
if(ret_val){
find=strchr(st,'\n');//查找换行符
if(find){// 如果地址不是 NULL
*find ='\0';// 在此处放置一个空字符
} else{
while(getchar()!='\n') continue;//处理输入行中剩余的字符
}
}
return ret_val;
}
效果:
步骤:
一、为结构建立一个格式或样式;
该声明并未创建实际的数据对象,只描述了该对象由什么组成。〔有时,我们把结构声明称为模板,因为它勾勒出结构是如何储存数据的。
二、 声明一个适合该样式的变量;
如果把结构声明置于一个函数的内部,它的标记就只限于该函数内部使用。
struct book{/* 结构模版:标记是 book */
char title[MaxTitle];
char author[MaxAuthor];
float value;
};
int main(void){
struct book library;/* 把 library 声明为一个 book 类型的变量 */
}
如果把结构声明置于函数的外部,那么该声明之后的所有函数都能使用它的标记。
struct book {
char title[MAXTITL];
char author[AXAUTL];
float value;
} library; /* 声明的右右花括号后跟变量名*/
或者组合后的结构声明和结构变量定义不需要使用结构标记
struct { /* 无结构标记 */
char title[MAXTITL];
char author[MAXAUTL];
float value;
} library;
如果打算多次使用结构模板,就要使用带标记的形式;或者使用typedef。
注意:以上并未初始化结构变量
三、访问结构变量的各个部分。
- 用结构成员运算符——点(.)访问结构中的成员。
//结构体变量用 . 运算符来访问结构体的成员
s_gets(library.title,MaxTitle);/* 访问title部分*/
s_gets(library.author,MaxAuthor);
scanf("%f",&library.value);
本质上,.title、.author和.value的作用相当于book结构的下标。
- 指向结构体的指针 用->来访问其指向的结构体的成员
"."一般情况下读作"的”。
“->”一般读作"指向的结构体的"。
四、初始化结构
简单的初始化,就跟初始化数组一样
struct book library = {
"The Pious Pirate and the Devious Damsel",//title成员可以被初始化为一个字符串
"Renee Vivotte", //初始化列表中的值必须是常量表达式
1.95
};
可以按照任意顺序使用指定初始化器:
struct book gift = { .value = 25.99,
.author = "James Broadfool",
.title = "Rue for the Toad"};
根据结构体内变量定义的顺序,依次初始化
struct guy fellow = { // 初始化一个结构变量
{ "Ewen", "Villard" },
"grilled salmon",
"personality coach",
68112.00
};
五、声明结构数组
struct book library[MAXBKS];
library // 一个book 结构的数组
library[2] // 一个数组元素,该元素是book结构
library[2].title // 一个char数组(library[2]的title成员)
library[2].title[4] // 数组中library[2]元素的title 成员的一个字符
六、声明结构指针
struct guy * him;
如果barney是一个guy类型的结构,可以这样写:
him = &barney;
和数组不同的是,结构名并不是结构的地址,因此要在结构名前面加上&运算符。
七、typedef
- 利用typedef可以为某一类型自定义名称。这方面与#define类似,但是两者有3处不同:
typedef创建的符号名只受限于类型,不能用于值。
typedef由编译器解释,不是预处理器。
在其受限范围内,typedef比#define更灵活。
用typedef来命名一个结构类型时,可以省略该结构的标签:
typedef struct {double x; double y;} rect;
- typedef常用于给复杂的类型命名
typedef char (* FRPTC ()) [5];
//把FRPTC声明为一个函数类型,该函数返回一个指针,该指针指向内含5个char类型元素的数组
总结:结构体声明定义之后还要初始化哦