预计阅读本页时间:-
Borland C和浮点数
如果程序不使用浮点数,旧的Borland C编译器会使用小版本的scanf()以使程序更短小。然而,如果仅有的一个浮点数是在一个结构数组中,就像程序清单14.2那样,那么编译器(Borland C/C++3.1 for DOS之前的版本,而不是Borland C/C++4.0)就不能发现它的存在。结果,您会得到如下的一条消息:
一种解决方法是在程序中添加下面的代码:
这段代码促使编译器装载浮点数版本的scanf( )。
程序清单14.2 manybook.c程序
下面是一个运行示例:
广告:个人专属 VPN,独立 IP,无限流量,多机房切换,还可以屏蔽广告和恶意软件,每月最低仅 5 美元
首先,我们看看如何声明结构数组以及如何访问各个成员。然后,我们着重分析程序的两个方面。
14.4.1 声明结构数组
声明一个结构数组和声明其他任何类型的数组一样。
这条语句声明library为一个具有MAXBKS个元素的数组,数组的每个元素都是book类型的结构。因此,library[0]是一个book结构,library[1]是第二个book结构,依此类推。图14.2可以帮助您直观地理解这一点。library本身不是结构名,它是元素类型为struct book结构的数组名。
图14.2 一个结构数组
14.4.2 标识结构数组的成员
为了标识结构数组的成员,可以采用适用于各个结构的规则:在结构名后加一个点运算符,然后是成员名。
注意,数组下标紧跟library,而不是跟在成员名后面:
使用library[2].value的原因是library[2]是结构变量名,就像library[l]是另一个结构变量名一样。
顺便问一下,下面的表达式代表什么?
这是由第3个结构(library[2]部分)描述的书本的名称的第5个字符(title[4]部分)。在本例中即为字符B。这个例子指出,点运算符右边的下标作用于各个成员,而点运算符左边的下标作用于结构数组。
作为总结,我们看下面的序列:
接下来,我们完成对这个程序的解释。
14.4.3 程序讨论
相对于第一个程序的主要变化是,我们插入一个循环来读取多个输入项。循环是由下列while条件开始的:
表达式gets(library[count].title)读入一个字符串作为书名;如果gets()试图超出文件结尾读取字符,这个表达式的值为NULL。表达式library[count].title[0]!=‘\0’是检测字符串的第一个字符是否为空字符,也就是字符串是否为空。如果用户在输入行的开始就按了回车键,将输入空字符串,这将结束循环。我们还进行检查,以确保输入的书本数不超出数组大小的限制。
程序中有这样的几行:
在前面的章节中我们介绍过,scanf()函数忽略掉空格和换行符,这段代码弥补了这一不足。当您回答对书本价格的请求时,您可能会键入下列信息:
这个语句传送了下面的字符序列:
scanf()函数读入了 1、2、.、5和0,但把\n留在输入流中,等待下一个读入语句处理。如果没有前面那段预处理的代码,下一个读入语句gets(library[count].title)就会把留下来的换行符当作空行读入,程序会以为用户发出了一个停止信号。我们插入的那段代码会把后续字符全部丢弃,直到发现并丢掉一个换行符为止。除了把这些字符从输入队列中删除之外,它不会对它们进行任何处理。这样gets()就可以重新开始了。
现在,我们回过头来继续研究结构。