第十二章函数(一) 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 函数说明