第14章 结构和其他数据形式 14.4 结构数组

本文解析了一个用C语言编写的程序,该程序能够管理一个包含多本书的图书目录。文章详细介绍了如何声明结构数组,并通过实例展示了如何访问结构数组中的各个成员。此外,文章还分析了程序的输入循环及如何正确处理用户输入。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

程序清单14.2  manybook.c程序

/*manybook.c 包含多本书的图书目录*/
#include <stdio.h>
#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];    /*把library声明为book结构数组*/
    int count=0;
    int index;

    printf("Please enter the book title.\n");
    printf("Please [enter] at the start 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 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;
}

首先,我们看看如何声明结构数组以及如何访问各个成员。然后,我们着重分析程序的两个方面。

14.4.1  声明结构数组

声明一个结构数组和声明其他类型的数组一样:

struct book library[MAXBKS];

这条语句声明library为一个具有MAXBKS个元素的数组,数组 的每个元素都是book类型的结构

library本身不是结构名,它是元素类型为struct book结构的数组名。

14.4.2  标识结构数组成员

为了标识结构数组的成员,可以采用适用于各个结构的规则:在结构名后加一个点运算符,然后是成员名。

library[0].value;  /*第1个数组元素的value成员*/
library[4].title;  /*第5个数组元素的title成员*/

使用library[0].value的原因是library[0]是结构变量名,就像library[4]是另一个结构变量名一样;

library[2].title[4];这个表达式代表什么?

这是由第3 个结构描述的书本的名称的第5个字符。这个例子指出,点运算符右边的下标作用于各个成员,点运算符左边的下标作用于结构数组。

作为结构,我们看下面的这个序列:

library             //book结构数组
library[2]          //数组元素,因此是一个book结构
library[2].title    //char数组(library[2]的title成员)
library[2].title[4] //title成员数组中的一个字符

14.4.3  程序讨论

相对于第一个程序的主要变化是,我们插入一个循环来读取多个输入项,循环是由下列的while条件开始的:

while(count<MAXBKS && gets(library[count].title)!=NULL && library[count].title[0]!='\0')

表达式gets(library[count].title)读入一个字符串作为书名;如果gets()试图超出文件结尾读取字符,这个表达式的值为NULL。表达式library[count].title[0]!='\0'是检测字符串的第一个字符是否为空字符,也就是字符串是否为空。如果用户在输入行的开始就按了回车键,将输入空字符串,这将结束循环。我们还进行限制,以确保输入的书本数不超出数组大小的限制。

程序中有这们的几行:

while(getchar()!='\n')
    continue;   /*清空输入行*/

在前面的章节我们介绍过,scanf()函数忽略掉空格和换行符,这段代码弥补了这一不足。当您回答对书本价格的请求时,您可能会键入下列的信息:

12.5[enter]

这个语句传送了下面的字符序列:

12.50 \n

scanf()函数读入了1、2、5、0,但是把\n留在了输入流中,等待下一个读入语句处理。如果没有前面那段预处理的代码,下一个读入语句gets(library[count].title)就会把留下来的换行符当作空行读入,程序会以为用户发出了一个停止信号。我们插入的那段代码会把后续所有字符丢掉,直到发现并丢掉一个换行符为止。除了把这些字符丢掉以外,它不会对它们进行任何处理。这样gets就可以重新开始 了。

转载于:https://my.oschina.net/idreamo/blog/858013

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值