编程学习,从意外中收获

最后更新于:2022-04-01 14:38:07

提倡同学们积累代码行数,于是有了大量的编程练习。做下来是一个基本的要求,对个别同学而言,已经是轻松面对,他们在基本编程能力方面,已经有了保障,这为今后的学习和自学打下了好的基础。一些同学一路紧随,跟住了都不是易事,有些依然不能按时按量完成。心中想着要多做几个,但调试中遇到问题,难免急躁。   看到一位同学在博文最后写的一段话:“直接抓狂了,经过个人分析,应该是函数change24与changefrom0没有实现其功能,可是定义函数,函数的赋值及调用都与其他同学的相同,问题究竟出在哪里啊?求指点!”   这是C++第7周项目1 - 静态成员应用于时间类(见[http://blog.csdn.net/sxhelijian/article/details/8795951](http://blog.csdn.net/sxhelijian/article/details/8795951)) 的题目。目标是学会静态数据成员以及静态成员函数的用法。   下面是只涉及静态数据成员以及静态成员函数的用法的“缩略版”解答,当然,包含这位同学犯的错误。请读者先读完这段程序。 ~~~ #include <iostream> #include<string> using namespace std; class Time { public: Time(int=0,int=0,int=0); void show_time( ); //根据is_24和from0,输出适合形式-20:23:5/8:23:5 pm/08:23:05 pm static void change24(); //改变静态成员is_24,在12和24时制之间转换 static void changefrom0(); //改变静态成员from0,切换是否前导0 private: static bool is_24; //为true时,24小时制,如20:23:5;为flase,12小时制,显示为8:23:5 pm static bool from0; //为true时,前导0,8:23:5显示为08:23:05 int hour; int minute; int sec; }; Time::Time(int h,int m,int s) { hour=h; minute=m; sec=s; } bool Time::is_24=true; bool Time::from0=false; void Time::show_time( ) { int h=(is_24)?hour:hour%12; if (h<10&&from0) cout<<'0'; cout<<h<<':'; if(minute<10&&from0) cout<<'0'; cout<<minute<<':'; if(sec<10&&from0) cout<<'0'; cout<<sec; if(!is_24) cout<<((hour>12)? " pm":" am"); cout<<endl; } void Time::change24() { is_24=!is_24; } void Time::changefrom0() { from0=!from0; } int main( ) { Time t1(23,14,25),t2(8,45,6); cout<<"24小时制,不导0:"<<endl; t1.show_time(); t2.show_time(); cout<<"切换是否前导0:"<<endl; t1.changefrom0(); t2.changefrom0(); t1.show_time(); t2.show_time(); cout<<"换一种制式:"<<endl; t1.change24(); t2.change24(); t1.show_time(); t2.show_time(); } ~~~   这段程序的实际运行结果是:   ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-06-07_575640485279e.png)   可以发现,切换是否前导0,换制式,根本没有起作用。预期中的结果应该是:   ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-06-07_5756404874513.png)   面对运行中的问题,最直接的办法就是采用单步执行的办法,跟踪一下程序在执行过程中,相关变量的变化过程。显然,这位同学并没有这样做过。   一再强调的调程序的“利器”,就被藏在“兵器库”中,任由其闲置。这种技能就是要在实践中学会的,这是学会的最佳时刻。有些同学已经用得纯熟,有些还在躲避。同一个教室上课,差别怎么这么大。   不说这些了。其实,不用单步调试,这个事不好做,也真不好说。初学有关知识,都要靠着推理式的排查,这是更难的办法。   这个程序中包括main()函数在内一共5个函数。类的构造函数Time()和用于显示的函数Time::show_time()嫌疑不大,先放过。main()似乎中规中矩,也放下。Time::changefrom0()和Time::change24()与以前编程的程序中有点不一样,声明前加了个static,这时可以看书了,明确这叫做静态成员函数,静态成员函数是用来使用静态数据成员的,再看static bool is_24; 和static bool from0; ,这两个成员不一般,静态的,静态的有何特点?它不属于任何一个对象,属于类。然后看看讲义,老师讲过这个图:   ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-06-07_575640488ba72.png)   围绕着“静态”,找到main()函数中有这么两句,调用的是静态成员函数: ~~~ t1.changefrom0(); t2.changefrom0(); ~~~   这两个静态成员函数操作的将是同一个数据Time::from0,尽管t1.changefrom0()和t2.changefrom0()前面打着t1、t2人民的旗号,干得都是服务大众的工作。from0和hour等不一样,它是静态的。   于是明白了吧。t1.changefrom0()将from0由假为真,t2.changefrom0()又将from0由真为假,最后输出没有变化。   发生在is_24上的事情也是一样。   程序运行结果不在预期中,这是学习的最佳机会。   稀里糊涂走进来,明明白白走出去。这大概是积累代码行的路线中应该收获的,而其中需要的,是冷静,以及实践与看书的结合。   最后,还说,单步调试,闲着太可惜。
';