循序渐进Forcal例程
目 录
1 概述 2 预备知识 3 最简单的例子 4 安全的例子及Forcal扩展动态库的用法 5 完整的例子 | 6 添加常量和二级函数 7 能计算多个表达式的例子 8 结语 |
1 概述 [返回页首]
如果你喜欢Forcal,想用Forcal编程而又无从下手,那么本文的例子将会对你有所帮助。
本文所有的例子均在VS C++ 2008环境下编译通过,编译时请将活动解决方案配置为“Release”,项目属性中的字符集设置为“未设置”。这都是些完整的例子,复制下来直接编译运行即可。为了减少代码,这些例子都是控制台应用程序,简单地加以改写,将它应用到实用的Windows程序中去是不难的。
第一个例子是最简单的,其他的例子基本上都是在前面例子的基础上添加代码实现的。认真地完成每个例子后的习题将有助于加深对的Forcal理解。
本文没有穷尽Forcal的所有用法和功能,而且还很不够。如果你还有什么不明白的,可以直接与我联系:forcal@sina.com 。
2 预备知识 [返回页首]
使用Forcal的预备知识并不多,只要你会加载和卸载动态库(dll),而且懂一点多线程编程的知识就可以了。
2.1 加载和卸载Forcal
应用程序可调用LoadLibrary直接加载Forcal32.dll。
HANDLE hForcal; //动态库模块句柄;
hForcal=LoadLibrary("forcal32.dll"); //加载动态库Forcal32.dll;
加载Forcal32.dll成功后,需调用函数GetProcAddress获取Forcal输出函数的地址。例如:
fcInitForcal pInitForcal; //fcInitForcal 在头文件forcal32.h中定义,为初始化Forcal的函数指针;
pInitForcal=(fcInitForcal) GetProcAddress(hForcal,"InitForcal");
该函数获得了初始化Forcal的函数地址,保存在指针pInitForcal中。
当程序不再需要访问Forcal32.dll时,应调用函数FreeLibrary将其卸载。
FreeLibrary(hForcal); //释放动态库Forcal32.dll;
2.2 在多线程中使用Forcal
Forcal可以用在单线程程序中,但不能及时退出漫长的计算过程或无限循环。没人愿意使用一个经常失去响应的程序。
为了安全地使用Forcal,应用程序至少有两个线程,一个用于Forcal计算,另一个用于监视Forcal运行。
也许你会感到奇怪,本文所有的例子好像都是单线程的。确实,本文的例子中没有关于多线程的函数或语句。但除了第一个例子,从第二个例子开始,都加载了一个Forcal扩展动态库QuitFc32.dll,该库中启动了一个线程,专门用于监视Forcal运行。
多线程是一个更高级的概念,本文作为使用Forcal的引玉之砖,没有提供这方面的例子。
3 最简单的例子 [返回页首]
从这一节开始给出使用Forcal的例子,这是最简单的。
这个例子有三个函数:加载并初始化Forcal的函数InitForcal,释放Forcal的函数FreeForcal和主函数main,主函数编译并计算了一个实数表达式的值。前两个函数的内容完全可以并入主函数,但分开写显得更清晰一些。
这个例子只用到了Forcal的四个输出函数:初始化Forcal的函数InitForcal,释放Forcal的函数FreeForcal,编译实数表达式的函数RealCom和计算实数表达式的函数RealCal。例子的完整源代码如下:
习题:
(1)更换不同的字符串表达式ForStr,重新编译运行程序,观察计算结果。
(2)将本例计算实数表达式改为计算整数表达式或复数表达式的例子。
4 安全的例子及Forcal扩展动态库的用法 [返回页首]
在第一个例子中,如果计算表达式"while[1,1]",程序将陷入无限循环,这在实用程序中是不能容忍的。将Forcal程序设计成多线程程序可以避免这一点。为了简单,本例中将加载一个Forcal扩展动态库QuitFc32.dll,该库中启动了一个线程,专门用于监视Forcal运行。另外更重要的是,通过本节可以学习到Forcal扩展动态库的用法,这是Forcal进行功能扩展的最主要的方式。
Forcal扩展动态库只有一个输出函数ForcalDll。用法相当简单,以QuitFc32.dll为例:(1)加载QuitFc32.dll;(2)使用函数ForcalDll对动态库初始化;(3)用完后仍然用函数ForcalDll释放动态库;(4)卸载动态库。具体应用详见程序中的红字部分。
程序中的红字部分是在前一个例子的基础上新添加的内容,后面的例子中亦是如此,不再特别说明。
例子的完整源代码如下:
习题:
(1)更换字符串表达式ForStr的内容为"while[1,1]"或者其他可长时间运行的内容,重新编译运行程序,在QuitFc窗口中按Esc键中断Forcal运行,观察运行结果。
(2)在本例的基础上,改为能加载软件包中FcConst.dll的例子。然后将ForStr的内容改为"Key_RealFunction"或者FcConst.dll中的其他常量,重新编译运行程序,观察计算结果。
(3)在本例的基础上,改为能加载软件包中Example.dll的例子。然后将ForStr的内容改为"GetRunTime()"或者"(:i,k)=SetRunTime(),{i=0,k=0,while{i<=1000000,k=k+i,i++},k},GetRunTime()",重新编译运行程序,观察计算结果。
5 完整的例子 [返回页首]
在前面的例子中,程序的计算结果有些是错误的。因为Forcal在遇到运行错误时,就会停止计算而退出,其计算结果是不正确的。
在这个例子中,我们将添加运行错误检测功能。为此,只需要增加Forcal的一个输出函数GetRunErr就可以了。
到这里为止,我们的程序能够计算,能够退出无限循环,能够检测运行错误,因此称之为完整的例子。
本例的完整源代码如下:
习题:
(1)更换字符串表达式ForStr的内容为"while[1,1]",重新编译运行程序,观察计算结果。
(2)更换字符串表达式ForStr的内容为"which[0,1]",重新编译运行程序,观察计算结果。
6 添加常量和二级函数 [返回页首]
在这个例子中,我们将往Forcal中添加常量和二级函数。
使用Forcal的输出函数SetConst可以往Forcal中添加常量,本例中只添加了一个实型常量PI。
使用Forcal的输出函数SetFunction可以往Forcal中添加二级函数,本例中只添加了一个实型二级函数add。
本例的完整源代码如下:
习题:
(1)在本例的基础上再添加一个实型常量_E=2.718,更换字符串表达式ForStr的内容为"_E",重新编译运行程序,观察计算结果。
(2)在本例的基础上再添加一个实型二级函数average,该函数已在下面给出。这稍稍提高了一点难度,因为你要同时添加Forcal的两个输出函数TestRunErr和SetRunErr,否则编译是不能通过的。不要忘了更换字符串表达式ForStr的内容为"average(1,2,3)",以便检查运行效果。
(3)在本例的基础上再添加一个实型二级函数PrintStr,该函数已在下面给出。这也是提高了一点难度的,你需要同时添加Forcal的一个输出函数GetForStr以使编译通过。记着更换字符串表达式ForStr的内容为"PrintStr(/"hello forcal!/")",观察运行效果。
7 能计算多个表达式的例子 [返回页首]
在本例中,我们将使程序能计算10个表达式,程序输出的信息更详细,以便我们能输入更复杂的表达式进行检验。
注意:本例不是在上一例的基础上添加新内容,而是对上一例的主函数进行了改写。
本例的完整源代码如下:
习题:
(1)程序运行时,第6个表达式"a(x,y)=8";没有语法错误,为什么编译不能通过?
(2)程序运行时,第9个表达式"";为空,不能通过编译,提示你在设计程序时注意什么?
(3)在本例的基础上修改程序,使之能计算20个表达式。
(4)在本例的基础上修改程序,使之在编译出错时直接给出错误提示而不是错误代码。
(5)在本例的基础上再添加实型二级函数PrintStr和CalFor,这两个函数已在下面给出。这有一点难度,你需要同时添加Forcal的四个输出函数TestRunErr、SetRunErr、GetForStr和GetFor以使编译通过。同时在字符串表达式ForStr中包含以下内容,检查运行情况。
aa(x)=x+8;
calfor["aa",7];
.
.
.
SetRealStackMax(1000); //设置实数堆栈为1000;
a(x)=PrintStr["a..."],if(x<1,return[x]),CalFor["b",x-1]; //a(...)函数中调用了b(...)函数;
b(x)=PrintStr["b..."],if(x<1,return[x]),CalFor["a",x-1]; //b(...)函数中调用了a(...)函数;
a[10]; //启动递归程序;
.
.
.
8 结语 [返回页首]
虽然还可以添加更多的例子,但是作为一个入门教程,就先写到这儿了。
如果你对本文有什么意见或建议,请给我发E-mail:forcal@sina.com 。
版权所有© Forcal数学软件 2002-2008,保留所有权利
E-mail: forcal@sina.com QQ:630715621
最近更新: <!--webbot bot="Timestamp" S-Type="EDITED" S-Format="%Y年%m月%d日" startspan -->2008年10月30日<!--webbot bot="Timestamp" i-CheckSum="1411" endspan -->