📄 ls12.php
字号:
<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>实例四的目的在于向我们演示:当你写一个程序时,有时候你不必去考虑一些小函数的具体实现,相反,你就当它们已经实现了一样,然后把精力先集中在程序总体架构上。
<P>这种写程序的方法,我们称为“由上而下”型,它有助于我们把握程序主脉,可以及时发现一个程序中潜在的重要问题,从而使我们避免在开发中后期才发现一些致命问题的危险;同时也避免我们过早地在一些程序上的枝节深入,最终却发现这些枝节完全不必要。
<P>不过,当程序很庞大时,想一次性理清整个程序的脉胳是不可能的,很多同样是重要的方向性修改都必须在对具体的事情有了分析后,才能做出准确的调整。另外,采用“由上而下”的开发方法时,有时也会遇上开发到后期,发现某些枝节的难度大大超过来原来的预估,需要占用过多开工期,甚至可能根本无法实现的危险。所以,我们还得介绍反方向的方法“由下而上”法。
<P>采用“由下而上”时,我们会事先将各个需要,或者只是可能需要的细小功能模块实现出来,然后再由这些模块逐步组合成一个完整系统。采用由下而上的方法所写的代码还易于测试,因为这种代码不会过早地与其它代码建立关系,所以可以独立地进行测试,确保无误后,再于此基础上继续伸展。
<P>一个小实例子引出这个大话题,有些远了,只是希望学习我的教程学员,能比其它途径学习编程的人,多那么一点“前瞻”能力。
<P>最后,我给出AreaOfRect()函数的完整代码。另外几个函数,有劳各位自已在实例的源代码添加完整。
<P>
<P>void AreaOfRect()
<P>{
<P> int x,y;
<P>
<P> cout << "请输入长方形的长:";
<P> cin >> x;
<P> cout << "请输入长方形的宽:";
<P> cin >> y;
<P>
<P> cout <<"面积为:" << (x * y) << endl;
<P>}
<P>
<H3><A name=12.4>12.4 主函数</A></H3>
<P>
<P>C,C++被称为“函数式”的编程语言。意指用这门语言写成的程序,几乎都由函数组成,程序运行时,不是在这个函数执行,就是在那个函数内执行。整个程序的结构看上去类似:A函数调用B函数,B函数又调用C函数,而C函数则可能调用了D函数后又继续调用E函数……甚至一个函数还可以调用自身,比如A函数调用A函数,或A调用B,而B又反过来调用A等等……
<P>问题是最开始运行的,是哪个函数?
<P>最开始运行的那个函数,称为主函数。主函数在控制台或DOS应用程序中。为main()函数。在标准的Windows应用程序中,则为名为WinMain()。
<H4><A name=12.4.1>12.4.1</A> DOS程序的主函数</H4>
<P>
<P>控制台应用程序的主函数:main()我们已经很“熟悉”了,每回写程序都要用到它,只是我们没有专门讲到它。现在回头看看:
<P>int main(int argc, char* argv[])
<P>{
<P> ……
<P> return 0;
<P>}
<P>
<P>main函数的返回值数据类型为int,参数定义:int argc,char*
argv[]的具体含义我们暂不用关心,只需知道,DOS程序或控制台程序中,程序运行时的入口处就是main()函数。
<P>
<H4><A name=12.4.2>12.4.2</A> Windows程序的主函数</H4>
<P>我们先来创建一个Windows应用程序。请注意看课程,不要轻车熟路地生成一个“控制台”工程。
<P>请打开CB,(如果你正打开着CB,请先关闭原来的工程),然后选择主菜单File | New |
Application,如果是CB5,选择File | New Application。
<P>下一步请选择主菜单 Project | View
Source,该命令将让CB在代码窗口中打开工程源文件,主函数WinMain正是在该文件中。请你在工程源文件(默认文件名:Project1.cpp)中找到WinMain()。
<P>
<P>WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int)<BR>
<P>这行代码看上去很复杂,但无变不离其宗,你现在尽可以从位置上判断:函数名无疑是WinMain(),而WINAPI估计是“返回类型”,至于"HINSTANCE,
HINSTANCE, LPSTR,
int"则必是参数定义。尽管还有些细节需要确定,但我们现在能够看懂这些就已经是95%掌握了学习的重点。其它的且先放过。
<P>
<P>由于现在我们很少采用Windows程序来做来实例,所以有必要验证一番,WinMain是否真的是Windows应用程序运行时的第一个函数?
<P>还记得F8或F7吗?(有个女生站起,声音响亮:我记得F4!!!没听说要扩编为F8啊?)
<P>在调试程序时,F8或F7键可以让程序单
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -