第十二章函数(一) 12.1函数的引入 12.2学会调用函数 12.2.1哪些函数可调用? 12.2.1.1库函数 12.2.1.2操作系统的API函数 12.2.1.3VCL库函数 12.2.2调用者必须能“找”得到被调用者 12.2.3调用者必须传递给被调用者正确的参数 12.2.4如何得到函数的运行结果 12.2.5调用库函数的实例 12.3自定义函数 12.3.1函数的格式 12.3.2自定义函数实例 12.3.2.1小写字母转换为大写字母的函数 12.3.2.2使用函数改写“统计程序 12.3.2.3求多种平面形状的面积 12.4主函数 12.4.1DOS程序的主函数 12.4.2 Windows程序的主函数 12.5小结 函数是C语言的一个重点和难点,我们此次将连续两章进行讲解。本章重点在于彻底理 解函数的作用,学会调用函数,学会自已编写函数 秉承我们“以人为本:)”的学习方法,我们学习函数第一件事就是问话:干嘛让我学习 函数?反过来说就是:函数能为一个程序员做些什么? 12.1函数的引入
第十二章 函数(一) 12.1 函数的引入 12.2 学会调用函数 12.2.1 哪些函数可调用? 12.2.1.1 库函数 12.2.1.2 操作系统的 API 函数 12.2.1.3 VCL 库函数 12.2.2 调用者必须能“找”得到被调用者 12.2.3 调用者必须传递给被调用者正确的参数 12.2.4 如何得到函数的运行结果 12.2.5 调用库函数的实例 12.3 自定义函数 12.3.1 函数的格式 12.3.2 自定义函数实例 12.3.2.1 小写字母转换为大写字母的函数 12.3.2.2 使用函数改写“统计程序” 12.3.2.3 求多种平面形状的面积 12.4 主函数 12.4.1 DOS程序的主函数 12.4.2 Windows 程序的主函数 12.5 小结 函数是C语言的一个重点和难点,我们此次将连续两章进行讲解。本章重点在于彻底理 解函数的作用,学会调用函数,学会自已编写函数。 秉承我们“以人为本:)”的学习方法,我们学习函数第一件事就是问话:干嘛让我学习 函数?反过来说就是:函数能为一个程序员做些什么? 12.1 函数的引入
家里地板脏了怎么办? 拿起扫帚,自个儿扫呗。当然,在扫之前要对地板上的各种“脏”东西定好数据类型, 针对不同的“数据类型”,我们需要进行不同的处理,比如是废纸,则无情地扫到垃圾桶 但若是在地上发现一张百元大钞,则应该脉脉含情地捡起放在胸口:“你让我找得好苦”。 在扫地的过程中,当然也无处不在使用“流程控制”。比如家里有三间房子,则应该是 个循环。而每一间房子的打扫过程也是一个循环过程:从某个角落的地板开始,向另 个角落前进,不断地重复扫把的动作。中间当然还需进行条件判断:比如前面所说的对地 面脏物的判断,再如:if(这一小块地面不脏),则 continue到下一块地面 我们学了“数据类型、常量、变量”,所以我们有了表达问题中各种数据的能力: 我们还学了“流程控制”,所以我们还会针对各个问题,用正确的流程组合解决问题的 步骤,从而形成解决问题的方法。 看起来我们已经拥有了从根本上解决任何问题的能力。但 家里电视坏了怎么办? 呃?这个,我不是学电器专业的。我只会看电视,我不会修理电视。 这时候我们的办法是:打一个电话请专业的修理师上门修理 还有很多问题的解决办法都是和修电视类似,即:我们自已没有这个能力,但我们可以 调用一个具备这一能力的人来进行 函数在程序中就相当于:具备某些功能的一段相对独立的,可以被调用的代码。是的, 函数也就是一段代码,代码也就是我们前面的学的“变量,常量,流程控制”等写成的一 行行语句。这些语句以一种约定形式存在着,等待我们去调用它 其实我们已经用过函数了:给你一个数:2.678,能帮我们求出它的正弦值吗?想起来了 吗?我们在上一章中学过sin(函数。 段用以被调用的代码,这是函数的本质。当然,使用函数在程序中还有许多其它的作 用,但我们将从这个最关键的地方讲起:怎样调用一个函数? 12.2学会调用函数
家里地板脏了怎么办? 拿起扫帚,自个儿扫呗。当然,在扫之前要对地板上的各种“脏”东西定好数据类型, 针对不同的“数据类型”,我们需要进行不同的处理,比如是废纸,则无情地扫到垃圾桶; 但若是在地上发现一张百元大钞,则应该脉脉含情地捡起放在胸口:“你让我找得好苦”。 在扫地的过程中,当然也无处不在使用“流程控制”。比如家里有三间房子,则应该是 一个循环。而每一间房子的打扫过程也是一个循环过程:从某个角落的地板开始,向另一 个角落前进,不断地重复扫把的动作。中间当然还需进行条件判断:比如前面所说的对地 面脏物的判断,再如:if (这一小块地面不脏),则 continue 到下一块地面…… 我们学了“数据类型、常量、变量”,所以我们有了表达问题中各种数据的能力; 我们还学了“流程控制”,所以我们还会针对各个问题,用正确的流程组合解决问题的 步骤,从而形成解决问题的方法。 看起来我们已经拥有了从根本上解决任何问题的能力。但-- 家里电视坏了怎么办? 呃?这个,我不是学电器专业的。我只会看电视,我不会修理电视。 这时候我们的办法是:打一个电话请专业的修理师上门修理。 还有很多问题的解决办法都是和修电视类似,即:我们自已没有这个能力,但我们可以 调用一个具备这一能力的人来进行。 函数在程序中就相当于:具备某些功能的一段相对独立的,可以被调用的代码。是的, 函数也就是一段代码,代码也就是我们前面的学的“变量,常量,流程控制”等写成的一 行行语句。这些语句以一种约定形式存在着,等待我们去调用它。 其实我们已经用过函数了:给你一个数:2.678,能帮我们求出它的正弦值吗?想起来了 吗?我们在上一章中学过 sin()函数。 一段用以被调用的代码,这是函数的本质。当然,使用函数在程序中还有许多其它的作 用,但我们将从这个最关键的地方讲起:怎样调用一个函数? 12.2 学会调用函数
这一节的任务是通过学会如何调用一个函数,从使用者的角度来了解函数各个重要知 识点。从而,也为下一节学习如何写一个函数打下基础。我们相信这样的安排是科学的 因为在生活中,我们也往往是先是一个“使用者”,然后才是一个“ 创造者”或“提供者” 12.2.1哪些函数可调用? 在学会如何调用函数之前,不妨先看看有哪些现成的函数可以调用。 12.2.1.1库函数 C++ Builder提供了数百个库函数。之所以称为“库”函数,是因为这些函数被集中在 个或几个文件里,这些文件就像存放函数仓库,当我们需要时,程序就可以从“库”中 调用。 库文件又分为两种形式 第一种是把不同的函数分门别类地放在不同的文件里。比如和数学计算有关的,放到 个文件,和I/O操作有关的,放到另一个文件。这样做的结果是:文件很多,但每个文 件都比较小。这种库我们称为“静态库”。 使用静态库的好处是:当我们的程序调用到某一库的函数是,C++ Builder可以将这个 库文件直接和我们的程序“合并”到一起。这样,我们提供给用户程序时,只需要提供 个可执行文件(比如叫:A.exe)。用户得到这个程序时,不用安装其它文件,就可以运行 使用静态库的坏处是:假如你需要向用户提供两个可执行文件,比如A.exe和B.exe, 两个文件可能都用到同一库文件,所以同一个库函数既被“合并”入A.exe,也被合并入 B.exe,造成了事实上的空间浪费。另外,虽然说每人静态库的文件都比较小,但如果一个 程序“合并”了不少库文件,那么这个程序的可执行文件体积仍然不可避免地变得比较大。 和静态库相对,另外一种库称为“动态库”。它的做法是:把所有函数不管三七二十 都放在一个文件里。这样做的结果:库文件只有一个,但体积很大
这一节的任务是通过学会如何调用一个函数,从使用者的角度来了解函数各个重要知 识点。从而,也为下一节学习如何写一个函数打下基础。我们相信这样的安排是科学的, 因为在生活中,我们也往往是先是一个“使用者”,然后才是一个“ 创造者”或“提供者”。 12.2.1 哪些函数可调用? 在学会如何调用函数之前,不妨先看看有哪些现成的函数可以调用。 1 2 .2.1.1 库函数 C++ Builder 提供了数百个库函数。之所以称为“库”函数,是因为这些函数被集中在 一个或几个文件里,这些文件就像存放函数仓库,当我们需要时,程序就可以从“库”中 调用。 库文件又分为两种形式: 第一种是把不同的函数分门别类地放在不同的文件里。比如和数学计算有关的,放到一 个文件,和I/O操作有关的,放到另一个文件。这样做的结果是:文件很多,但每个文 件都比较小。这种库我们称为“静态库”。 使用静态库的好处是:当我们的程序调用到某一库的函数是,C++ Builder 可以将这个 库文件直接和我们的程序“合并”到一起。这样,我们提供给用户程序时,只需要提供一 个可执行文件(比如叫:A.exe)。用户得到这个程序时,不用安装其它文件,就可以运行 了。 使用静态库的坏处是:假如你需要向用户提供两个可执行文件,比如 A.exe 和 B.exe, 两个文件可能都用到同一库文件,所 以同一个库函数既被“合并”入A.exe,也被合并入 B.exe,造成了事实上的空间浪费。另外,虽然说每人静态库的文件都比较小,但如果一个 程序“合并”了不少库文件,那么这个程序的可执行文件体积仍然不可避免地变得比较大。 和静态库相对,另外一种库称为“动态库”。它的做法是:把所有函数不管三七二十一, 都放在一个文件里。这样做的结果:库文件只有一个,但体积很大
使用动态库的坏处是:动态库不允许“合并”到你的程序中一一显然也不适于合并,因 为动态库太大了。所以若你使用动态库,在发布你的应用程序时,你必须向你的用户提供 动态库文件。 使用动态库的好处在于:如果你向用户提供的是一套程序,比如有 A.exe,B.exe,C.exe..,那么这些可执行文件都可以使用同一个动态库,所以尽管你需额 外提供一个很大的动态库,但你的各个应用程序却都很小。当然,采用动态库发布程序时, 般来说你还需要向用户提供一个安装程序,很多动态库要被安装到 Windows目录的 system system32子目录下。 什么时候使用静态库,什么时候使用动态库?当你只是写一个小小应用程序时,显然大 多数人喜欢只提供一个单独.exe文件。比如情人节到了,你觉得通过网络向你的 girlfriend 发一个电子贺卡太俗(前几年还很风雅呵:),同时也不能突显你作为一个程序员的实力 风水轮流转啊,前年搞网络的人还笑话程序员是“传统工业”一一所以你决定用C+← Builder写一个电子贺卡,这时你可不能用动态库啊,否则挤爆了女友的信箱,嘿嘿,这个 情人节就有你好受的了…… 相反,一个稍大点软件系统,你就应该采用动态库。大的如整个 Windows操作系统,就 彻头彻尾是使用动态库:再如一整套 MS Office,还有WPS,这些都是。一般地说(不绝对) 那些提供了安装程序的软件,都是使用动态库的。总之,使用动态库是专业程序的做法。 (又有人举手打断我的课程,说我们什么时候才能自已写个电子贺卡?回答是下一部教 程《白话 Windows编程》,顺便说说,下部教程很贵很贵的一一吓你的:) 不管使用动态或静态的库,写程序时都是一样的。只有在最后要链接程序时,我们通过 CB设置不同的选项即可。嗯?我说到了“链接”(1ink)这个词?对了,它就是我们一直 加引号的“合并”一词的专业说法。你可以把前面课程上所有的“合并”一词替换为链接 并且不用加引号了。 现在我们来看看CB主要提供哪些类别的库函数(以下内容仅供了解): 1、分类判断函数:
使用动态库的坏处是:动态库不允许“合并”到你的程序中--显然也不适于合并,因 为动态库太大了。所以若你使用动态库,在发布你的应用程序时,你必须向你的用户提供 动态库文件。 使用动态库的好处在于:如果你向用户提供的是一套程序,比如有 A.exe,B.exe,C.exe...,那么这些可执行文件都可以使用同一个动态库,所以尽管你需额 外提供一个很大的动态库,但你的各个应用程序却都很小。当然,采用动态库发布程序时, 一般来说你还需要向用户提供一个安装程序,很多动态库要被安装到Windows 目录的system 或 system32 子目录下。 什么时候使用静态库,什么时候使用动态库?当你只是写一个小小应用程序时,显然大 多数人喜欢只提供一个单独.exe 文件。比如情人节到了,你觉得通过网络向你的 girlfriend 发一个电子贺卡太俗(前几年还很风雅呵:),同时也不能突显你作为一个程序员的实力 --风水轮流转啊,前年搞网络的人还笑话程序员是“传统工业”--所以你决定用 C++ Builder 写一个电子贺卡,这时你可不能用动态库啊,否则挤爆了女友的信箱,嘿嘿,这个 情人节就有你好受的了…… 相反,一个稍大点软件系统,你就应该采用动态库。大的如整个 Windows 操作系统,就 彻头彻尾是使用动态库;再如一整套 MS Office,还有 WPS,这些都是。一般地说(不绝对), 那些提供了安装程序的软件,都是使用动态库的。总之,使用动态库是专业程序的做法。 (又有人举手打断我的课程,说我们什么时候才能自已写个电子贺卡?回答是下一部教 程《白话 Windows 编程》,顺便说说,下部教程很贵很贵的--吓你的:) 不管使用动态或静态的库,写程序时都是一样的。只有在最后要链接程序时,我们通过 CB设置不同的选项即可。嗯?我说到了“链接”(link)这个词?对了,它就是我们一直 加引号的“合并”一词的专业说法。你可以把前面课程上所有的“合并”一词替换为链接, 并且不用加引号了。 现在我们来看看 CB 主要提供哪些类别的库函数(以下内容仅供了解): 1、分类判断函数:
这类函数主要用对判断一个字符是什么类型的。就像我们上一章做的“判断用户输入字 符的类型”的例子。不使用函数,我们可以这样的条件判断一个字符是否为小写字母 if(ch>='a’&&ch<=’z’) cout<<ch<<"是一个小写字母。”<<endl 我们也可以直接使用相关的库函数 islower: if islower(ch)) cout<<ch<<"是一个小写字母。"<endl 2、控制台输入输出函数: 像我们总是使用的 getchar(,及 getche();这两个函数用来接受用户在控制台程序中的 按键输入。另外还有不和输入输出函数。当然,在输出方面,我们几乎都采用cout来往 屏幕输出内容。cin,cout这是C++的方法,如果写C程序(而不是C++),则输出更 常用的是 printf(;比如 printf( Hello world! 这行代码在屏幕上打出一行:" Hello world!"。 除了教学上,或其它一些特殊要求,我们几乎不写控制台式的程序了,我们最终目标是 写 Windows下的GUI(图形用户界面)程序,而这些控制台输入输出函数,都不能用在 GUI程序中。所以,当课程例中用到的某个控制台库函数,我会临时解释一下,其它的 大家就不必花时间了。 3、转换函数: 这类函数完成各种数据类型之间的转换,比如把字符串“123”转换数字123,或把小写 字母转换为大写字母等等。 5、目录管理函数: 目录就是我们现在常说的“文件夹”啦。这些函数可以建立,删除,切换文件夹 地,我们已经不再使用,转而使用 Windows提供的相关函数。请参看下面的 Windows ApI 函数说明
这类函数主要用对判断一个字符是什么类型的。就像我们上一章做的“判断用户输入字 符的类型”的例子。不使用函数,我们可以这样的条件判断一个字符是否为小写字母: if ( ch >= 'a' && ch <= 'z' ) cout << ch << "是一个小写字母。" << endl; 我们也可以直接使用相关的库函数 islower: if ( islower(ch) ) cout << ch << "是一个小写字母。" << endl; 2、控制台输入输出函数: 像我们总是使用的 getchar(),及 getche();这两个函数用来接受用户在控制台程序中的 按键输入。另外还有不和输入输出函数。当然,在输出方面,我们几乎都采用 cout 来往 屏幕输出内容。cin, cout 这是C++的方法,如果写C程序(而不是C++),则输出更 常用的是 printf();比如: printf("Hello world!"); 这行代码在屏幕上打出一行:"Hello world!"。 除了教学上,或其它一些特殊要求,我们几乎不写控制台式的程序了,我们最终目标是 写 Windows 下的GUI(图形用户界面)程序,而这些控制台输入输出函数,都不能用在 GUI程序中。所以,当课程例中用到的某个控制台库函数,我会临时解释一下,其它的, 大家就不必花时间了。 3、转换函数: 这类函数完成各种数据类型之间的转换,比如把字符串“123”转换数字 123,或把小写 字母转换为大写字母等等。 5、目录管理函数: 目录就是我们现在常说的“文件夹”啦。这些函数可以建立,删除,切换文件夹。一般 地,我们已经不再使用,转而使用 Windows 提供的相关函数。请参看下面的 Windows API 函数说明
6、数学函数: 例如我们前面说的sinO函数,其它的各种三角函数,还有求整,求绝对值,求随机数 求对数等 这些函数大都枯燥无味,其中的随机函数倒是有趣点。很多游戏程序都要使用到它。这 里粗略讲讲。 什么叫随机?大白话说就是:一件事情的结果有几种相同概率的可能。比如你扔一个硬 币到地上,可能是正面,也可能是反面朝上,两种可能的概率都是50%。但如果你要考虑 硬币还有“立”着在地上的可能,那么这种可能就不属于随机的范畴了。下面的程序随机 生成一个0~99的数,然后要求你输入一个0~99之间的数,如果这你输入的和它生成的数 相等(概率为1%),就表示你中奖了 //虽然属于数学类函数,但随机函数其实放在标准库( stdlib)里 #include #include int main(int argc, char* argv[) //在第一次调用随机数之前,要调用一次这个函数, //这个函数称为“随机种子函数” randomize o //随机函数: random(intn)的用法: //随机返回一个0~(n-1)之间的整数, //如:intx= random(100),则x值将是0到99之间的一个数。 int x random(100) in t
6、数学函数: 例如我们前面说的 sin()函数,其它的各种三角函数,还有求整,求绝对值,求随机数, 求对数等。 这些函数大都枯燥无味,其中的随机函数倒是有趣点。很多游戏程序都要使用到它。这 里粗略讲讲。 什么叫随机?大白话说就是:一件事情的结果有几种相同概率的可能。比如你扔一个硬 币到地上,可能是正面,也可能是反面朝上,两种可能的概率都是 50%。但如果你要考虑 硬币还有“立”着在地上的可能,那么这种可能就不属于随机的范畴了。下面的程序随机 生成一个 0~99 的数,然后要求你输入一个 0~99 之间的数,如果这你输入的和它生成的数 相等(概率为 1%),就表示你中奖了。 //虽然属于数学类函数,但随机函数其实放在标准库(stdlib)里: #include #include int main(int argc, char* argv[]) { //在第一次调用随机数之前,要调用一次这个函数, //这个函数称为“随机种子函数” randomize(); //随机函数:random(int n)的用法: //随机返回一个 0~ (n-1) 之间的整数, //如: int x = random(100),则 x 值将是 0 到 99 之间的一个数。 int x = random(100); int y;
cout>y if(x==y)//可能性为1% cout<<"恭喜!您中奖了!"<<endl else cout<<"谢谢使用。"<<end 7、字符串函数 我们在学习字符串时将用到 8、内存管理管理函数: 我们在学习内存管理时将用到 9、杂七杂八的其它函数。 这个且不说。 12.212操作系统的API函数 大家总该知道什么叫操作系统吧? Windows就是一套操作系统,另外如UNIX, Linux也是 当然我们最常用的是前者。操作系统有两个主要任务 第一是给普通用户提供一套界面,比如桌面啦,任务条啦,及任务条上的开始按钮,桌 面上的图标:还有资源管理器等等。这一些我们都称为“用户界面”。它的作用是让用户 “用”这台电脑。因此我们也可以称它为用户与电脑之间的“接口”。 第二就是给我们这些程序员的接口,我们所写的程序是运行在操作系统上,就必须和操 作系统有着千丝万缕的关系。比如我们想在屏幕上显示一个窗口,那么我们所做的事是“请 求操作系统为我们在屏幕上画一个窗口”,同样在有了窗口后,我们想在窗口上画一条直 线,那么也是“请求操作系统在座标(2,1)-(100,200)之间画一条直线” 那么,这些“请求”是如何实现的呢?其实也是调用函数,调用操作系统为我们准备的 各种函数。这些函数同样是放在库文件里,当然,由于这些库文件是操作系统提供的,每
cout > y; if( x == y) //可能性为 1% cout << "恭喜!您中奖了!" << endl; else cout << "谢谢使用。" << endl; } 7、字符串函数: 我们在学习字符串时将用到。 8、内存管理管理函数: 我们在学习内存管理时将用到。 9、杂七杂八的其它函数。 这个且不说。 1 2 .2.1.2 操作系统的 A PI 函数 大家总该知道什么叫操作系统吧?Windows 就是一套操作系统,另外如UNIX,Linux 也是, 当然我们最常用的是前者。操作系统有两个主要任务: 第一是给普通用户提供一套界面,比如桌面啦,任务条啦,及任务条上的开始按钮,桌 面上的图标;还有资源管理器等等。这一些我们都称为“用户界面”。它的作用是让用户 “用”这台电脑。因此我们也可以称它为用户与电脑之间的“接口”。 第二就是给我们这些程序员的接口,我们所写的程序是运行在操作系统上,就必须和操 作系统有着千丝万缕的关系。比如我们想在屏幕上显示一个窗口,那么我们所做的事是“请 求操作系统为我们在屏幕上画一个窗口”,同样在有了窗口后,我们想在窗口上画一条直 线,那么也是“请求操作系统在座标(2,1)-(100,200)之间画一条直线”。 那么,这些“请求”是如何实现的呢?其实也是调用函数,调用操作系统为我们准备的 各种函数。这些函数同样是放在库文件里,当然,由于这些库文件是操作系统提供的,每
一台装有相同操作系统的电脑都有这些库,所以它不用安装,所以它当然采用了动态库的 形式。对于我们正在用的 Windows,这些库一般都放在 Windows的安装目录: Windows,主 要是 Windows\System或 System32下。那里有一堆的.dll,其中有不少文件就是操作系统 的动态库文件。 我们写的程序,一般称为“应用程序”( Application program),所以 Windows为我们提 供的库函数也就称为“应用程序接口”( Application Program Interface),缩写即:API。 在本部教程,我们主要学习C++语言本身,只有学好C、C++语言,才有可能学会用C、 C++语言来和操作系统打交道。要知道所有在API函数都声明为C语言的形式,这是因为 Windows本身也是主要用C语言写成的。结论是:学习C、C+语言非常重要,并且,如果 想在操作系统上写程序,那么学习C、C++当然最合算! 12.2.1.3VCL库函数 VCL意为:可视化控件库( Visual Component library),事事都直接和 Windows的API 打交道,编程效率将非常的低。主要表现两个方面:第一,由于使用API编程是非可视化 的,我们将不得不花费非常冗长的时间在处理界面显示的事务上,而界面显示其实不是我 们程序的主要逻辑。第二,有关显示等工作的大量代码事实上有很大的相似性,大量重复。 我们要么仍受每写一个程序就重复写一堆千篇一律的代码,要么像早期的 Windows程序员 样自已动手写一套的类库用来“包装”这段代码,以求每次可以得重复利用。但这是件 庞大而灵活的工作,显然我们不值得这样做,事实上也不具备这样的能力。笔者在 Windows3.1下写程序时,曾经购买过国人高手写的一套这种类库,事实上钱花得不值。很 快笔者转向了当时 Borland提供的类库:OWL和微软的MFC VCL提供的也主要是类库,我们暂未学到“类”的概念,所以这时且不详谈。 12.2.2调用者必须能“找”得到被调用者 调用函数前提之一:调用者必须能看到被调用者
一台装有相同操作系统的电脑都有这些库,所以它不用安装,所以它当然采用了动态库的 形式。 对于我们正在用的 Windows,这些库一般都放在 Windows 的安装目录:Windows,主 要是 Windows\System 或 System32 下。那里有一堆的.dll,其中有不少文件就是操作系统 的动态库文件。 我们写的程序,一般称为“应用程序”(Application Program),所以 Windows 为我们提 供的库函数也就称为“应用程序接口”(Application Program Interface),缩写即:API。 在本部教程,我们主要学习 C++语言本身,只有学好 C、C++语言,才有可能学会用 C、 C++语言来和操作系统打交道。要知道所有在 API 函数都声明为 C 语言的形式,这是因为, Windows 本身也是主要用 C 语言写成的。结论是:学习 C、C++语言非常重要,并且,如果 想在操作系统上写程序,那么学习 C、C++当然最合算! 1 2 .2.1.3 V CL 库函数 VCL 意为:可视化控件库(Visual Component Library),事事都直接和 Windows 的 API 打交道,编程效率将非常的低。主要表现两个方面:第一,由于使用 API 编程是非可视化 的,我们将不得不花费非常冗长的时间在处理界面显示的事务上,而界面显示其实不是我 们程序的主要逻辑。第二,有关显示等工作的大量代码事实上有很大的相似性,大量重复。 我们要么仍受每写一个程序就重复写一堆千篇一律的代码,要么像早期的 Windows 程序员 一样自已动手写一套的类库用来“包装”这段代码,以求每次可以得重复利用。但这是件 庞大而灵活的工作,显然我们不值得这样做,事实上也不具备这样的能力。笔者在 Windows3.1 下写程序时,曾经购买过国人高手写的一套这种类库,事实上钱花得不值。很 快笔者转向了当时 Borland 提供的类库:OWL 和微软的 MFC。 VCL 提供的也主要是类库,我们暂未学到“类”的概念,所以这时且不详谈。 12.2.2 调用者必须能“找”得到被调用者 调用函数前提之一:调用者必须能看到被调用者
个“者”字,可能让你以为这里说的是“人”,其实不是,这里说的调用者指的是当 前程序,而被调用者当然是“将被调用”的函数 不过,确实,这里拿人来比喻是再合适不过了。 就拿前面说的“找电视修理工”的例子来说 要修电视,显然要能找到电视修理工。这个道理很明显。 所以本小节的重点其实是:程序如何才能找到要调用的函数呢? 有三种方法: 第一种、将被调用的函数写在当前代码前面 修理工正在我家喝茶呢!是啊,我有个朋友是干这活的,有一天他来我家串门,而我家 电视正好坏了 下面我先写一个函数,这个函数的大部分代码我没有写出来一一根本写不出来。我只是 要用它表示一个叫“修理电视”的功能。 //本函数实现“修理电视” void XiuliDianshio 尽管我们稍后才能学如何自已写函数,但你现在要记住了,上面那几行代码就是一个函 数,它的函数名为: Xiaolidianshi,意为“修理电视” 好!有了“修理电视”的函数了,如何调用它呢?下图表示的是正确的情况:
一个“者”字,可能让你以为这里说的是“人”,其实不是,这里说的调用者指的是当 前程序,而被调用者当然是“将被调用”的函数。 不过,确实,这里拿人来比喻是再合适不过了。 就拿前面说的“找电视修理工”的例子来说: 要修电视,显然要能找到电视修理工。这个道理很明显。 所以本小节的重点其实是:程序如何才能找到要调用的函数呢? 有三种方法: 第一种、将被调用的函数写在当前代码前面 修理工正在我家喝茶呢!是啊,我有个朋友是干这活的,有一天他来我家串门,而我家 电视正好坏了。 下面我先写一个函数,这个函数的大部分代码我没有写出来--根本写不出来。我只是 要用它表示一个叫“修理电视”的功能。 //本函数实现“修理电视” void XiuliDianshi() { ...... } 尽管我们稍后才能学如何自已写函数,但你现在要记住了,上面那几行代码就是一个函 数,它的函数名为:XiaoliDianshi,意为“修理电视”。 好!有了“修理电视”的函数了,如何调用它呢?下图表示的是正确的情况:
void XiuliDianshio 后面的代码 看得见 前面的函数 Xiuli Dianshio 正确:在后面的代码中调用 iul iDi anShi(函数。 当我们写程序要调用一个函数,而这个函数位于我们现在在写的代码前面时,我们就可 以直接调用它,这就像修理工就在我们家里一样。注意这里的前面并非仅限于“跟前” 如果你的代码很多行,这个函数在“很前面”,也不妨碍我们调用它。 要注意的是另一面:当函数在我们的代码后面时,代码就“看”不见这个函数了。下面 即为这种错误情况: 错误:要调用的函数在当前代码后面,“看不到”。 XiuliDianshi0; 前面的代码不能看到后面的 void XiuliDianshio 第二种、将被调用的函数声明写在当前代码前面 修理工不在我家,不过,他曾经留给我一张名片,名片上写着:“张三,电视修理工 Tel:1234567,住址:…”。所以我们也能知道他会修理电视,并且知道他的电话和住址, 这样就不愁找不到他了,对不?
当我们写程序要调用一个函数,而这个函数位于我们现在在写的代码前面时,我们就可 以直接调用它,这就像修理工就在我们家里一样。注意这里的前面并非仅限于“跟前”, 如果你的代码很多行,这个函数在“很前面”,也不妨碍我们调用它。 要注意的是另一面:当函数在我们的代码后面时,代码就“看”不见这个函数了。下面 即为这种错误情况: 第二种、将被调用的函数声明写在当前代码前面 修理工不在我家,不过,他曾经留给我一张名片,名片上写着:“张三,电视修理工, Tel:1234567,住址:……”。所以我们也能知道他会修理电视,并且知道他的电话和住址, 这样就不愁找不到他了,对不?