
1.4 标准函数和EasyX库函数
C语言提供了大量标准函数,包括前面介绍过的getchar、putchar、printf、scanf等输入/输出函数,也包括各种数学计算函数。此外,许多开发公司和硬件厂商也提供众多函数库,使得程序设计开发人员可以直接使用这些库函数提供的科学计算、网络通信、图形处理和硬件设备的控制访问功能。
因此,实用软件的程序设计往往不是从零开始,而是尽可能利用现有支撑软件。鉴于C语言的用途广泛且历史悠久,各种支撑软件库中相当大的部分是C语言函数的形式提供的。因此,了解、掌握此类库函数的功能和使用方法已成为开发者必备的技能。
为了使用各种函数,C语言提供了函数调用的功能。函数调用是一种表达式,其描述方法如下:
<函数名>(<实参表>)
其中,实参表是用逗号分隔的若干个表达式。前面的程序实例的输出都是典型的 printf和 scanf 函数调用。鉴于函数调用本身也是表达式,因此,函数调用也可以作为其他函数的参数。例如:
printf("result=%lf", sin(45*3.14159));
其中,printf的函数调用中使用了三角函数sin的调用作为实参。程序执行时,首先计算实参,进行sin函数调用,并将结果作为该表达式的值返回;随后,传递给函数printf,进而完成结果的输出。
本节将介绍 C 语言提供的数学函数,同时介绍一个第三方厂家提供的图形处理函数库EasyX。
1.4.1 数学函数
表1-4列出了C语言中常用的数学函数。程序可以直接调用它们完成一些数学计算,从而免除了程序员编写相关算法的步骤。
表1-4 常用的数学函数

这些函数的原型都声明在 math.h 中,在使用之前需要使用编译预处理命令#include 将math.h嵌入到程序中。读者应该注意到函数原型的声明规定了函数参数的数据类型和返回值类型。例如,求绝对值的函数 fabs 规定了参数必须是 double 类型,而返回结果也是 double类型。如果使用其他类型的数据作为这些函数的参数,则系统将自动将其转换成规定的数据类型。【例1-8】为应用数学函数的实例。
【例1-8】 三角形面积的计算。
有一个三角形,如图1-21所示。其中,a、b和c是这个三角形的3条边长,A、B和C是三角形的3个顶角。下面是一个计算三角形面积的公式:


图1-21 三角形
〖问题分析〗
在这个公式中,出现了三次正弦函数,如果直接调用C函数库提供的标准函数sin就可以很方便地写出上述公式在C程序中的表达形式,即:
S = c*c*sin(A)*sin(B)/(2*sin((A+B)/ 180));
需要注意以下两点。
(1)C 函数库中提供的 sin 函数要求输入一个弧度值,而人们通常习惯使用角度,因此,需要将角度转换成弧度,然后再传递给 sin 函数。假设角度为 D,则对应的弧度应该是3.14159*D/180。
(2)从上面的计算公式可以发现:一个三角形的面积仅与两个顶角和一条边有关,所以在编写程序时,仅需要用户提供两个顶角、一条边就可以了。
于是,问题求解程序包含以下几个步骤:
(1)输入两个顶角和一条边,分别保存在变量a、b、c中;
(2)对于a、b和a+b完成角度到弧度的计算,结果保存于变量A、B和AB;
(3)按照上述公式,计算S;
(4)输出S。
下面是解决这个问题的程序源代码。
〖程序代码〗
#include <stdio.h> /* 引入输入/输出函数的声明 */
#include <math.h> /* 引入数学函数的声明 */
main( )
{
int a, b, c;
double S, A, B, AB;
printf("输入两个角度和一个边长:");
scanf("%d%d%d", &a, &b, &c); /* 输入两个角和一条边 */
A = 3.14159*a/180; /* 转换为弧度 */
B = 3.14159*b/180;
AB = 3.14159*(a+b)/180;
S = c*c*sin(A)*sin(B)/sin(AB)/2; /* 计算三角形面积 */
printf("\nS=%lf\n", S);
}
对于角度转换成弧度的需求,程序中设置了3个变量保存变换的结果。由于a和b等角度变量是int整型,而表示弧度的变量A和B是双精度实型,变换表达式的计算涉及类型转换问题。表达式中每个运算的执行都会检查操作数的类型,发现类型不一致,则自动加入类型转换。int整型变量a和实数常量3.141 59(双精度数)的乘法会得到双精度数,再和整数180相乘,得到双精度实数。
这里通过设置A和B等变量,将角度转换和三角形面积计算分布在不同语句,保持每步计算的独立性,以便于程序的阅读理解。此外,采用了c*c可以代替pow函数的使用,以求提高执行效率。
建议读者在Visual C++环境中自行运行这个程序。
1.4.2 EasyX图形处理函数库
EasyX是一个图形处理函数库,目前支持Visual Studio环境下的简易图形软件开发。借助于EasyX库函数提供的图形绘制、控制台输入等,开发者可以开发出简单的计算机游戏,同时熟悉比较复杂的控制流程和人机交互过程,为复杂软件的设计与实现打下技术基础。
EasyX函数库的使用有以下要求和规定。
(1)目前仅支持Visual Studio开发环境,没有支持Dev-C++环境的版本。
(2)所有函数工作于C++环境,因此源文件必须以.cpp为扩展名。
(3)所有图形处理函数的原型定义于graphics.h文件中,所有控制台输入/输出函数定义于conin.h文件中,使用前应该用#include命令嵌入到源程序文件中。
(4)在使用图形界面之前,必须用 initgraph函数进行初始化,指定屏幕的尺寸,使用结束后必须用closegraph函数进行关闭处理。
(5)图形的绘制采用平面坐标,X轴指向右方,Y轴指向下方。
EasyX库提供了许多绘图函数、颜色坐标访问函数和绘图属性访问函数。最常用的几个函数如表1-5所示。
表1-5 常用的EasyX函数

在这些函数原型中使用了几个特殊的类型。void类型常用于描述函数返回值,由于C语言缺省规定函数返回值的类型是 int 整型,对于无返回值的函数,C 语言提供了关键字 void来描述其返回值类型。符号 const 用于描述数据类型,说明这种数据类型的数据是常数,也就是不可修改的。在polygon函数定义中,const限定数组pts的内容是不可修改的,从而避免了错误的内容改写。
此外,由于EasyX函数库用于Windows操作系统的Visual Studio开发环境,采用了几个Windows系统内部的数据类型(不属于标准C语言);其中,HWND是标识窗口的句柄类型;POINT用于描述平面坐标点;COLORREF用于描述颜色,0表示黑色,WHITE(0xFFFFFF)表示白色;LPCTSTR 是通用字符串类型,适用于多种语言的字符串。相关详细内容参见附录F中的介绍。
下面通过一个简单的程序,介绍EasyX函数库的使用方法。
【例1-9】 中心圆的绘制。
在图形界面中,以坐标(200,150)为圆心,绘制一个半径为100的圆。EasyX绘图环境默认的坐标系采用X轴指向右方,Y轴指向下方的方式。
鉴于EasyX提供了画圆的函数circle,该任务可以通过以下代码来实现。
〖程序代码〗
#include <graphics.h> /* 引入图形处理函数的声明 */
#include <conio.h> /* 引入控制台输入/输出函数的声明*/
int main( )
{
initgraph(640, 480); /* 图形界面的初始化 */
circle(200, 150, 100); /* 在坐标(200,150)处,绘制一个半径为100的圆 */
_getch( ); /* 等待控制台输入任一键 */
closegraph( ); /* 关闭图形界面 */
return 0;
}
如上述程序中注释所示,按照 EasyX 的使用规定,程序嵌入(#include)了头文件graphics.h,并且以initgraph函数的调用完成初始化,设置了一个640×480的图形界面。随后,调用circle函数,指定圆心位置(200,15)和半径大小100,完成圆的绘制。随后,使用了一个控制台输入函数_getch,其本来的作用是读入键盘输入的字符。与用于标准输入流的 getchar函数不同,_getch函数不必等待换行符的输入,可以即时地获得输入字符。在本程序中,作为一个技巧,_getch函数用于暂停程序执行,等待键盘输入。因为如果没有这条语句,直接执行后面的图形关闭函数 closegraph,程序执行将立即结束。使用者将无法看到本程序画出的图形。为了看到绘制的图形,希望程序暂停执行。于是,这里_getch函数发挥了作用,它迫使程序等待用户输入,而它的使用要求事先引入头文件conio.h。程序的运行界面如图1-22所示。此时,点击任何键将使得图形界面消失。

图1-22 绘图的图形界面
由于该程序作为C++程序运行,main函数的定义必须提供返回值类型的声明。因此, main前面的int说明该函数的返回值必须是int整型,而函数中最后一句return 0; 用于结束函数 main 的执行,并返回 0 表示程序正常结束,符合这个要求。鉴于该程序运行于C++环境,编译中的语法检查较C语言更加严格,如果没有使用return,系统会给出警告提示。