编程学习,从意外中收获
最后更新于: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上的事情也是一样。
程序运行结果不在预期中,这是学习的最佳机会。
稀里糊涂走进来,明明白白走出去。这大概是积累代码行的路线中应该收获的,而其中需要的,是冷静,以及实践与看书的结合。
最后,还说,单步调试,闲着太可惜。