📄 教学--第十二章 函数(一).htm
字号:
<P> do</P>
<P> {</P>
<P> cout << "继续吗?(Y/N)";</P>
<P> cin >> ch;</P>
<P> }</P>
<P> while(LowerToUpper(ch) == 'Y');</P>
<P> </P>
<P> 功能完全一样,但看上去更简洁。请大家进行对比,并理解后面的写法。</P>
<P> </P>
<P>本例中的“小写转换大写”的函数,虽然我们已经成功实现,但我们并没有将它的声明放到某个头文件,所以,如果在别的代码文件中,想使用这个函数,还是不方便。确实,我们很有必要为这个函数写一个头文件,在讲完函数后,我们将去做这件事。</P>
<P>实例二代表了一种函数的使用需求:我们将一些很多代码都要使用的某个功能,用一个函数实现。这样,每次需要该功能时,我们只需调用函数即可。这是函数的一个非常重要的功能:代码重用。通过函数,不仅仅是让你少敲了很多代码,而且它让整个程序易于维护:如果发现一某个功能实现有误,需要改正或改进,我们现在只需修改实现该功能的函数。如果没有函数?那将是不可想像的。</P>
<P> </P>
<P>但是,只有那些一直要使用到的代码,才有必要写成函数吗?并不是这样。有些代码就算我们可能只用一次,但也很有必要写在函数。请看下例。</P>
<H5><A name=12.3.2.2>12.3.2.2</A> 使用函数改写“统计程序”</H5>
<P><B>实例三:</B>使用函数改写第十章“<A
href="http://d2school.com/bcyl/bhcpp/newls/ls10.htm#10.2">可连续使用的统计程序</A>”。</P>
<P> </P>
<P>我们先把第十章的例子拷过来(只拷其中的main()函数部分):</P>
<P> </P>
<P>int main(int argc, char* argv[])
<P>{
<P> float sum,score;
<P> int num; //num 用于存储有几个成绩需要统计。
<P> int i; //i 用于计数
<P>
<P> char c; //用来接收用户输入的字母
<P>
<P> do
<P> {
<P><B> </B>//初始化:
<P> sum = 0;
<P> i = 1;
<P>
<P> cout << "====成绩统计程序====" <<
endl;<BR>
<P> //用户需事先输入成绩总数:
<P> cout << "请输入待统计的成绩个数:";
<P> cin >> num;
<P> cout << "总共需要输入"<< num
<< "个成绩(每个成绩后请加回车键):" << endl;
<P>
<P> while ( i <= num)
<P> {
<P> cout << "请输入第"
<< i << "个成绩:";
<P> cin >>
score;<BR>
sum +=
score;<BR>
i++;<BR>
}<BR><BR>
//输出统计结果:<BR> cout
<< "参加统计的成绩数目:" << num << endl;<BR>
cout << "总分为:" << sum <<
endl;
<P>
<P> //提问是否继续统计:
<P> cout <<"是否开始新的统计?(Y/N)?";
<P> cin >> c;
<P> }
<P> while( c == 'y' || c == 'Y');
<P>}
<P>//---------------------------------------------------------------------------<BR>
<P>我们将要对这段代码所作的改进是:将其中完成一次统计功能的代码,写入到一个单独的函数。
<P>
<P>//函数:实现一个学员的成绩统计:
<P>//参数:无
<P>//返回:无
<P>void ScoreTotal()
<P>{
<P> float sum,score;
<P> int num; //num 用于存储有几个成绩需要统计。
<P> int i; //i 用于计数
<P>
<P> sum = 0;
<P> i = 1;
<P>
<P> cout << "====成绩统计程序(Ver 3.0)====" << endl;
<P> //用户需事先输入成绩总数:
<P> cout << "请输入待统计的成绩个数:";
<P> cin >> num;
<P> cout << "总共需要输入"<< num <<
"个成绩(每个成绩后请加回车键):" << endl;
<P>
<P> while ( i <= num)
<P> {
<P> cout << "请输入第" << i <<
"个成绩:";
<P> cin >> score;
<P> sum += score;
<P> i++;
<P> }
<P>
<P> //输出统计结果:
<P> cout << "参加统计的成绩数目:" << num << endl;
<P> cout << "总分为:" << sum << endl;
<P> }
<P> //---------------------------------------------------------------------------<BR>
<P>我只是将一些代码从在原来的位置抽出来,然后放到ScoreTotal()函数体内。接下来,请看原来的main()函数内的代码变成什么:
<P>
<P>//---------------------------------------------------------------------------
<P>int main(int argc, char* argv[])
<P>{
<P> char c;
<P>
<P> do
<P> {
<P> //调用函数实现一次统计:
<P> ScoreTotal();
<P>
<P> //提问是否继续统计:
<P> cout <<"是否开始新的统计?(Y/N)?";
<P> cin >>
c;<BR> }
<P> while(c == 'Y' || c == 'y');
<P> }
<P>//---------------------------------------------------------------------------
<P>
<P>看,当实现统计一次的功能的代码交由ScoreTotal()处理之后,这里的代码就清晰多了。
<P>
<P>函数的另一重要作用:通过将相对独立的功能代码写成独立的函数,从而使整体程序增加可读性,同样有益于代码维护。这称为“模块化”的编程思想。“模块化”的思想并不与C++后面提倡的“面向对象”的编程思想相抵触。而函数正是C,C++中实现“模块化”的基石。
<P>实例三的演变过程也向我们展示了一种编写程序的风格:当一个函数中的代码看上去很长时,你就应该去检查这段代码,看看中间是否有哪些逻辑是可以独立成另外一个函数?在本例子中,main()函数中套了两层循环,但这两种循环相互间没有多大逻辑上的联系:内层用于实现一次完整的统计功能,外层则只负责是否需要继续下一次的统计。所以,把内层循环实现的功能独立“摘”出去,这是一个非常好的选择。
<P>我们阅读VCL的源代码时(用Pascal实现),发现尽管VCL是一套庞大的类库,但其内部实现仍保持了相当好的简约风格,很少有代码超过200行的函数。这的确可以作为我们今后编写软件的楷模。
<P>本例的完整请见相关例子文件。其中我还把前例的LowerToUpper()函数也加入使用。
<P>
<H5><A name=12.3.2.3>12.3.2.3</A> 求多种平面形状的面积</H5>
<P><B>实例四:</B>写一程序,实现求长方形,三角形,圆形,梯形的面积,要求各种形状分别用一个函数处理。
<P>
<P>程序大致的流程是:
<P>首先提问用户要求什么形状态的面积?然后根据用户的输入,使用一个switch语句区分处理,分别调用相应的函数。求不同形状态的面积,需要用户输入不同的数据,基于本程序的结构,我们认为将这些操作也封装到各函数比较合适。
<P>先请看main()函数如何写:</P><PRE>int main(int argc, char* argv[])
{
char ch;
do
{
cout << "面积函数" <<endl;
cout << "0、退出 "<< endl //<--没有分号!用一个cout输出多行,只是为了省事
<< "1、长方形" << endl
<< "2、三角形" << endl
<< "3、圆形" << endl
<< "4、梯形" << endl; //<--有分号
cin >> ch;
if(ch == '0')
break;
switch(ch)
{
case '1' : AreaOfRect(); break; //长方形
case '2' : AreaOfTriangle(); break; //三解形
case '3' : AreaOfRound(); break; //圆形
case '4' : AreaOfTrape(); break; //梯形
default :
cout << "输入有误,请在0~4之间选择。" << endl;
}
}
while(true);
}</PRE>
<P>函数main()的任务很清晰:负责用户可以连续求面积,这通过一个do...while实现,同时负责让用户选择每次要计算面积的形状,这通过一个switch实现。而具体的,每一个平面图形的面积计算,都通过三个自定义的函数来实现。尽管我们还没有真正实现(编写)这三个函数,但这并不影响我们对程序整体架构的考虑。
<P>当我们学会如何编写函数的时候,我们就必须开始有意识地考虑程序架构的问题。如果说变量,表达式等是程序大厦的沙子,水泥;而语句是砖头钢筋的话,那么函数将是墙,栋梁。仅仅学会写函数是不够的,还需要学习如何把一个大的程序分划为不同的功能模块,然后考虑这些模块之间的关系,最终又是如何组合为完整系统。
<P>实例四的目的在于向我们演示:当你写一个程序时,有时候你不必去考虑一些小函数的具体实现,相反,你就当
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -