//* book.c --仅包含一本书的图书目录V
#include<stdio.h>
#define MAXTITL 41 //*书名的最大长度+1 V
#define MAXAUTL 31 /*作者名的最大长度+1 */
#define MAXBKS 100 //*最多可以容纳的图书册数
struct book{ /*结构模板:标记为book */
char title[MAXTITL];
char author[MAXAUTL];
float value;
};/*结构模板结束*/
int main(void)
{
struct book library[MAXBKS]; /* 把 library 声明为 book 结构数组 */
int count=0;
int index;
printf("please enter the book title.\n");
printf("Press(enter)at the strat of a line to stop.\n");
while(count<MAXBKS&&gets(library[count].title)!=NULL&&library[count].title[0]!='\0')
{
printf("Now enter the author.\n");
gets(library[count].author);
printf("Now enter the value.\n");
scanf("%f",&library[count++].value);
while(getchar()!='\n')
continue;/*清空输入行*/
if(count<MAXBKS)
printf("Enter the next litle.\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;
}
运行结果:
声明结构数组
声明一个结构数组和声明其他任何类型的数组一样。
struct book library[MAXBKS];
这条语句声明library为一个具有MAXBKS个元素的数组,数组的每个元素都是book类型的结构。因此,libraiy[0]是一个book结构,library[1]是第二个book结构,依此类推。图14.2可以帮助您直观地理解 这一点。library本身不是结构名,它是元素类型为struct book结构的数组名。
标识结构数组的成员
为了标识结构数组的成员,可以采用适用于各个结构的规则:在结构名后加一个点运算符,然后是成员名。
library[0].value /*第1个数组元素的value成员*/
library[4].tiUe /*第5个数组元素的title成员*/
注意,数组K标紧跟library,而不足跟在成员名后®:
library.va〗uef2丨 // 错误 libraryUl.value // t确
使用library[2].value的原因是library[2]足结构变景名,就像library[1]是另一个结构变量名一样。
library[2]. title[4J
这是由第3个结构(丨ibrary[2]部分)描述的书本的名称的第5个字符(titie[4]部分)。在本例中即为 字符B(,这个例子指出,点运算符右边的下标作用于各个成员,而点运算符左边的下标作用于结构数组。 作为总结,我们看下面的序列:
library // book 结构数削
library [2] //数组元素,因此足一个book结构
library [2] .title // chdr 数纠(library [2 j 的 U t le 成员)
library[2] .tit!c[4] // title 成员数组屮的一个字符
程序讨论
相对于第一个程序的主要变化是,我们插入一个循环来读取多个输入项。循环是由下列while条件开始的:
while(count<MAXBKS&&gets(library[count].title)!=NULL&&library[count].title[0]!='\0')
表达式gets (librarylcount].title)读入一个字符串作为书名;如果gets ()试图超出文件结尾读取字符, 这个表达式的值为NULL。表达式library[count].titlet[0]!='\0’足检测字符串的第一个字符是否为空字符,也就是字符串是否为空。如果用户在输入行的开始就按了间车键,将输入空字符串,这将结束循环。我们还进行检杳,以确保输入的书本数不超出数组大小的限制。
程序中有这样的儿行:
while (getchar ( ) ! = ' \n') continue: /*淸屮输入行*/
在前面的章节中我们介绍过,scanf()函数忽略掉空格和换行符,这段代码弥补了这一不足。当您回 答对书本价格的请求时,您可能会键入下列信息:
12.50[enter]
这个语~传送了卜面的字符序列:
12.5tnn
scanf ()函数读入了 1、2、.、5和0, fti把\n留在输入流中,等待下一个读入语句处理。如果没有前面 那段预处理的代码,下一个读入语句gets (library[count].title)就会把留下来的换行符当作空行读入,程序会以为用户发出了一个停止信号。我们插入的那段代码会把后续字符全部丢弃,直到发现并丢掉个换行符为。除了把这些字符从输入队列中删除之外,它不会对它们进行任何处理。这样gets ()就可以重新开始了。 现在,我们回过头来继续研究结构。