当前位置:嗨网首页>书籍在线阅读

08-结构数组

  
选择背景色: 黄橙 洋红 淡粉 水蓝 草绿 白色 选择字体: 宋体 黑体 微软雅黑 楷体 选择字体大小: 恢复默认

14.4 结构数组

接下来,我们要把程序清单14.1的程序扩展成可以处理多本书。显然,每本书的基本信息都可以用一个 book 类型的结构变量来表示。为描述两本书,需要使用两个变量,以此类推。可以使用这一类型的结构数组来处理多本书。在下一个程序中(程序清单14.2)就创建了一个这样的数组。如果你使用Borland C/C++,请参阅本节后面的“Borland C和浮点数”。

结构和内存

manybook.c 程序创建了一个内含100个结构变量的数组。由于该数组是自动存储类别的对象,其中的信息被存储在栈(stack)中。如此大的数组需要很大一块内存,这可能会导致一些问题。如果在运行时出现错误,可能抱怨栈大小或栈溢出,你的编译器可能使用了一个默认大小的栈,这个栈对于该例而言太小。要修正这个问题,可以使用编译器选项设置栈大小为10000,以容纳这个结构数组;或者可以创建静态或外部数组(这样,编译器就不会把数组放在栈中);或者可以减小数组大小为16。为何不一开始就使用较小的数组?这是为了让读者意识到栈大小的潜在问题,以便今后再遇到类似的问题,可以自己处理好。

程序清单14.2  manybook.c 程序

/* 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')
     {
          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 Budgie
Now enter the author.
Mack Zackles
Now enter the value.
12.95
Enter 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

Borland C和浮点数

如果程序不使用浮点数,旧式的Borland C编译器会尝试使用小版本的 scanf() 来压缩程序。然而,如果在一个结构数组中只有一个浮点值(如程序清单14.2中那样),那么这种编译器(DOS的Borland C/C++ 3.1之前的版本,不是Borland C/C++ 4.0)就无法发现它存在。结果,编译器会生成如下消息:

scanf : floating point formats not linked
Abnormal program termination

一种解决方案是,在程序中添加下面的代码:

#include <math.h>
double dummy = sin(0.0);

这段代码强制编译器载入浮点版本的 scanf()

首先,我们学习如何声明结构数组和如何访问数组中的结构成员。然后,着重分析该程序的两个方面。