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() 。
首先,我们学习如何声明结构数组和如何访问数组中的结构成员。然后,着重分析该程序的两个方面。