结构体
/* book.c -- 一本书的图书目录 */
#include <stdio.h>
#include <string.h>
char * s_gets(char * st, int n);
#define MAXTITL 41 /* 书名的最大长度 + 1 */
#define MAXAUTL 31 /* 作者姓名的最大长度 + 1*/
struct book { /* 结构模版:标记是 book */
char title[MAXTITL];
char author[MAXAUTL];
float value;
}; // 结构模版结束
int main(void){
struct book library; //把 library 声明为一个 book 类型的变量
printf("Please enter the book title.\n");
s_gets(library.title, MAXTITL); /* 访问title部分*/
printf("Now enter the author.\n");
s_gets(library.author, MAXAUTL);
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");
}
char * s_gets(char * st, int n){
char * ret_val;
char * find;
ret_val = fgets(st, n, stdin);
if (ret_val) {
find = strchr(st, '\n'); // 查找换行符
if (find) // 如果地址不是 NULL,
*find = '\0'; // 在此处放置一个空字符
else
while (getchar() != '\n')
continue; //处理输入行中剩余的字符
}
return ret_val;
}
输出
Please enter the book title.
enter
Now enter the author.
retne
Now enter the value.
23
enter by retne: $23.00
retne: "enter" ($23.00)
Done.
定义
是一种既能包含字符串又能包含数字的数据形式;还要保持各种信息的独立
结构的含义
Ⅰ结构布局
结构布局告诉编译器如何表示数据,并未让编译器为数据分配空间
把library声明为一个使用book结构布局的结构变量;该变量的结构布局为book
解构成员可以是任意一种c的数据类型,也可以是其他结构
#include <stdio.h>
#define maxtitle 41
#define maxauthor 31
struct book{ //本质:book结构声明创建了一个名为struct book的新类型
char title[maxtitle];
char author[maxauthor];
float value;
};
int main(){
struct book library; //把library声明为一个使用book结构布局的结构变量 ;book称为标记
}
Ⅱ创建结构变量
struct book library;
struct book起的功能相当与int float;
可以定义两个struct book类型的变量甚至指针
struct book doyle,pan,*ptbook;
*简化
条件:只存在一个变量时
声明结构的过程和定义结构变量的过程可以组合成一个步骤。如下所示,组合后的结构声明和结构变量定义不需要使用结构标记:
struct { /* 无结构标记 */
char title[MAXTITL];
char author[MAXAUTL];
float value;
} library;
初始化
结构变量可初始化;各初始化项用逗号隔开,独占一行;对特定成员的最后一次赋值才是它实际获得的值
第一种
struct book library = {
"The Pious Pirate and the Devious Damsel",
"Renee Vivotte",
1.95
};
第二种
struct book gift= {.value = 18.90,
.author = "Philionna Pestle",
0.25
};
访问
使用结构成员运算符——点(.)访问结构中的成员
例如,library.value即访问library的value部分。可以像使用float类型变量一样使用
本质上.title、.author和.value的作用相当于book结构的下标
scanf(“%f”,…)需要一个float类型变量的地址,而&library.float正好符合要求
s_gets(library.title, MAXTITL);
scanf("%f", &library.value); //.比&的优先级高,因此这个表达式和&(library.float)一样
结构的指定初始化器使用点运算符和成员名(而不是方括号和下标)标识特定的元素
可以按照任意顺序使用指定初始化器;最后一次赋值为准
struct book surprise = { .value = 10.99};
嵌套结构
#include <stdio.h>
#define LEN 20
const char * msgs[5] =
{
" Thank you for the wonderful evening, ",
"You certainly prove that a ",
"is a special kind of guy. We must get together",
"over a delicious ",
" and have a few laughs"
};
struct names { // 第1个结构
char first[LEN];
char last[LEN];
};
struct guy { // 第2个结构
struct names handle; // 嵌套结构
char favfood[LEN];
char job[LEN];
float income;
};
int main(void){
struct guy fellow = { // 初始化一个结构变量
{ "Ewen", "Villard" },
"grilled salmon",
"personality coach",
68112.00
};
printf("Dear %s, \n\n", fellow.handle.first);
printf("%s%s.\n", msgs[0], fellow.handle.first);
printf("%s%s\n", msgs[1], fellow.job);
printf("%s\n", msgs[2]);
printf("%s%s%s", msgs[3], fellow.favfood, msgs[4]);
if (fellow.income > 150000.0)
puts("!!");
else if (fellow.income > 75000.0)
puts("!");
else
puts(".");
printf("\n%40s%s\n", " ", "See you soon,");
printf("%40s%s\n", " ", "Shalala");
}
//下面是该程序的输出:
//Dear Ewen,
//
// Thank you for the wonderful evening, Ewen.
//You certainly prove that a personality coach
//is a special kind of guy. We must get together
//over a delicious grilled salmon and have a few laughs.
//
// See you soon,
// Shalala
访问
printf("Dear %s, \n\n", fellow.handle.first);
结构数组
/* manybook.c -- 包含多本书的图书目录 */
#include <stdio.h>
#include <string.h>
char * s_gets(char * st, int n);
#define MAXTITL 40
#define MAXAUTL 40
#define MAXBKS 100 /* 书籍的最大数量 */
struct book { /* 建立 book 模板 */
char title[MAXTITL];
char author[MAXAUTL];
float value;
};
int main(void){
struct book library[MAXBKS]; /* book 类型结构的数组 */
int count = 0;
int index;
printf("Please enter the book title.\n");
printf("Press [enter] at the start of a line to stop.\n");
while (count < MAXBKS && s_gets(library[count].title, MAXTITL) != NULL
&& library[count].title[0] != '\0'){ //弥补了scanf函数遇到空格和换位符就结束读取的问题
printf("Now enter the author.\n");
s_gets(library[count].author, MAXAUTL);
printf("Now enter the value.\n");
scanf("%f", &library[count++].value);
while (getchar() != '\n')
continue; /* 清理输入行*/
if (count < MAXBKS)
printf("Enter the next title.\n");
}
if (count > 0){
printf("Here is the list of your books:\n");
for (index = 0; index < count; index++)
printf("%s by %s: $%.2f\n", library[index].title,
library[index].author, library[index].value);
}
else
printf("No books? Too bad.\n");
return 0;
}
char * s_gets(char * st, int n)
{
char * ret_val;
char * find;
ret_val = fgets(st, n, stdin);
if (ret_val){
find = strchr(st, '\n'); // 查找换行符
if (find) // 如果地址不是 NULL,
*find = '\0'; // 在此处放置一个空字符
else
while (getchar() != '\n')
continue; // 处理输入行中剩余的字符
}
return ret_val;
}
Please enter the book title.
Press [enter] at the start of a line to stop.My Life as a BudgieNow enter the author.Mack ZacklesNow enter the value.12.95Enter the next title.
...(此处省略了许多内容)...
Here is the list of your books:
My Life as a Budgie by Mack Zackles: $12.95
Thought and Unthought Rethought by Kindra Schlagmeyer: $43.50
Concerto for Financial Instruments by Filmore Walletz: $49.99
The CEO Power Diet by Buster Downsize: $19.25
C++ Primer Plus by Stephen Prata: $59.99
Fact Avoidance: Perception as Reality by Polly Bull: $19.97
Coping with Coping by Dr. Rubin Thonkwacker: $0.02
Diaphanous Frivolity by Neda McFey: $29.99
Murder Wore a Bikini by Mickey Splats: $18.95
A History of Buvania, Volume 8, by Prince Nikoli Buvan: $50.04
Mastering Your Digital Watch, 5nd Edition, by Miklos Mysz: $28.95
A Foregone Confusion by Phalty Reasoner: $5.99
Outsourcing Government: Selection vs. Election by Ima Pundit: $33.33
栈大小的潜在问题
声明结构数组
library为数组名,该数组中每个元素都是struct book类型的结构变量
struct book library[MAXBKS];
标识结构数组的成员
采用访问单独结构的规则
library[0].value;
library.value[2];//错误示范
library[2].value[4]; //第三个结构变量的title中的第5个字符
library[2]; //一个数组元素,为book结构
指向结构的指针
#include <stdio.h>
#define LEN 20
struct names {
char first[LEN];
char last[LEN];
};
struct guy {
struct names handle;
char favfood[LEN];
char job[LEN];
float income;
};
int main(void){
struct guy fellow[2] = {
{ { "Ewen", "Villard" },
"grilled salmon",
"personality coach",
68112.00
},
{ { "Rodney", "Swillbelly" },
"tripe",
"tabloid editor",
432400.00
}
};
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);
}
输出
address #1: 0x7fff5fbff820 #2: 0x7fff5fbff874
pointer #1: 0x7fff5fbff820 #2: 0x7fff5fbff874
him->income is $68112.00: (*him).income is $68112.00
him->favfood is tripe: him->handle.last is Swillbelly
好处
指向结构的指针通常比结构本身更容易操作;
传递指针通常更有效率;
一些用于表示数据的结构中包含指向其他结构的指针
声明和初始化
声明
该声明并未创造一个新的结构,指针him可以指向任意现有的guy类型结构
struct guy * him; //关键字 struct 结构标记guy
初始化
him=&barney; //结构变量名并不是结构变量的地址
him=&barney[0]; //barney为一个结构数组时可行
访问
第一种 ->
如果 him==&barney 那么 him->income 即是访问barney.income
如果 him==&fellow[0] 那么 him->income 即是访问fellow[0].income
P.S. 不能写成him.income
him->income为float类型的变量
第二种
fellow[0].income==(*him).income; //.比*优先级高
barney.income == (*him).income == him->income // 假设 him == &barney