C++实现简单的计时器

来源:互联网 发布:mac 搜狗五笔偏好设置 编辑:程序博客网 时间:2024/05/21 05:37

C++实现简单的计时器

http://blog.csdn.net/gybshen/article/details/51058100
    最近闲着无聊就想着用C++写点什么东西,仔细想了想其实自己的C++学的也不怎么好,写个简单的计时器吧!微笑

    首先我们先分析一下计时器的一些功能,简单一点的计时器包括开始、暂停、停止和显示基本功能,这些功能以C++面向对象的编程思想(OOP)进行抽象,就是计时器类(Timer)的4个成员函数,当然我们要把这些函数作为公有的,因为它们是留给外部的接口(interface)。

    然后我们再分析一下计时器的三种状态:停止,正在运行,暂停(注意:暂停不是停止),那么怎么记录计时器的三种状态呢?这里我们用布尔类型的变量记录计时器的三种状态,分别为bool is_pause,bool is_stop,在这里一定要注意变量的命名,就像这样见名知意。吐舌头当然为了体现C++类的封装性,要把这两个bool变量作为计时器类(Timer)的私有成员。

    重要的问题来了,我们怎么实现计时呢?呐,你们知道time()函数吗?简单的说一下time函数:这个函数在time.h头文件中,它返回自 Unix 纪元(January 1 1970 00:00:00 GMT)起的当前时间的秒数,是一个长整形(long)。这样我们在计时器开始的时候获取一个time函数的返回值,保存到一个变量中,在用一个变量保存暂停时的时间。当我们开始计时的时候,进入一个死循环,始终用time()-开始的时间,就是当前计时器的时间。(不要急,具体实现往下看)。此时为了保存开始和暂停时刻的时间,必须在计时器类(Timer)中增加两个长整形(long)变量:start_time,pause_time,当然作为私有变量。

     好像还少点什么......为了让外部获取当前计时器的状态,我们还需要两个函数返回计时器的状态,is_pause()计时器是否处于暂停,is_stop()计时器是否处于停止状态,返回值的类型为bool。

   惊讶别忘了Timer的构造函数,用来做一些初始化的工作!

     好了,至此我们的计时器类设计完成了(prefect),代码在下面:

[cpp] view plain copy
  1. class Timer  
  2. {  
  3.     private:  
  4.         long start_time;  
  5.         long pause_time;  
  6.         //两个bool值标记四种状态   
  7.         bool is_pause; //记录计时器的状态 (是否处于暂停状态)  
  8.         bool is_stop;//是否处于停止状态   
  9.     public:  
  10.         Timer();  
  11.         bool isPause(); //返回计时器状态   
  12.         bool isStop();  
  13.         //计时器的三种动作(功能)   
  14.         void Start();   
  15.         void Pause();  
  16.         void Stop();  
  17.         inline long getStartTime() {return start_time;}  
  18.         void show();  
  19. };  
   接下来的任务就是实现Timer的成员函数了..............
   首先是构造函数Timer::Timer(),完成一些初始化的工作:
[cpp] view plain copy
  1. Timer::Timer()  
  2. {  
  3.     is_pause = false//初始化计时器状态   
  4.     is_stop = true;  
  5. }  
计时器开始计时之前应该处于停止状态!(计时器只能处于一种状态,不要犯糊涂哦!)

   成员函数isPause()它的作用仅是让外部获取计时器是否处于暂停状态,so easy
[cpp] view plain copy
  1. bool Timer::isPause()  
  2. {     
  3.     if(is_pause)  
  4.     return true;  
  5.     else  
  6.     return false;  
  7. }  
  isStop函数和isPause一样只是一个接口,让外部获取计时器的状态:
[cpp] view plain copy
  1. bool Timer::isStop()  
  2. {  
  3.     if(is_stop)  
  4.         return true;  
  5.     return false;  
  6. }   

   下面是Timer::Start()函数的实现,它是计时器开始的时候要运行的函数:
[cpp] view plain copy
  1. void Timer::Start() //开始   
  2. {  
  3.     if(is_stop)  
  4.     {  
  5.         start_time = time(0);  
  6.         is_stop = false;  
  7.     }  
  8.     else if(is_pause)  
  9.     {  
  10.         is_pause = false;  
  11.         start_time += time(0)-pause_time; //更新开始时间:用此时的时间 - 暂停时所用的时间 + 上一次开始的时间 = 此时的开始时间   
  12.     }  
  13. }  
我们首先判断一下计时的状态,如果处于停止状态,获取开始的时间,然后更新计时器的状态;如果计时器正处在暂停状态,我们让计时器继续计时,我采用改变开始的计时的时间(start_time)去调整计时的时间 : (用此时的时间 - 暂停时所用的时间 + 上一次开始的时间 = 此时的开始时间)。如果计时器正处于运行状态,就什么也不做!(不知道大家能不能看的懂.....)

   这是暂停函数Timer::Pause()的实现:
[cpp] view plain copy
  1. void Timer::Pause() //暂停   
  2. {  
  3.     if(is_stop||is_pause) //如果处于停止/暂停状态,此动作不做任何处理,直接返回   
  4.         return;   
  5.     else    //否则调制为暂停状态  
  6.     {  
  7.         is_pause = true;  
  8.         pause_time = time(0); //获取暂停时间   
  9.     }  
  10. }  
如果没有在运行,也就是处于暂停或停止状态,什么也不做直接返回。否则就去处理暂停请求:既然我们进行了暂停的操作,就要改变计时器的状态,将状态设置为暂停,保存此刻的时间,(这个暂停的时间pause_time在上面的开始的函数中用的到!)。

接着我们去实现停止函数Timer::Stop():
[cpp] view plain copy
  1. void Timer::Stop()  //停止   
  2. {  
  3.     if(is_stop) //如果正处于停止状态(不是暂停状态),不做任何处理   
  4.         return ;   
  5.     else if(is_pause) //改变计时器状态   
  6.     {  
  7.         is_pause = false;  
  8.         is_stop = true;  
  9.     }  
  10.     else if(!is_stop)  
  11.     {  
  12.         is_stop = true;  
  13.     }   
  14. }  

如果处于停止状态,直接返回。否则如果处于暂停状态改变计时器的状态为is_stop = true;否则就是处于运行状态,直接改变计时器的状态为停止。

下面是显示时间的函数Timer::show():
[cpp] view plain copy
  1. void Timer::show()  
  2. {  
  3.     long t = time(0) - start_time;  
  4.     gotoxy(35,12);  
  5.     cout<<setw(2)<<setfill('0')<<t/60/60<<":"  
  6.         <<setw(2)<<setfill('0')<<t/60<<":"  
  7.         <<setw(2)<<setfill('0')<<t%60<<endl;  
  8. }  
这里我要说一下gotoxy(int x,int y)函数,它的作用是将控制台的光标定位到坐标(x,y)处,show函数是要放到死循环中的,所以这样始终将输出的时间打印到一个地方,实现了时间的更新(我是不是很聪明);setw(int x)是设置输出的字宽,setfill(char  ch)设置了字符的填充。time函数返回的是秒数,t/60/60得到小时,t/60得到分钟,t%60得到秒数。

下面就是主函数了main()
[cpp] view plain copy
  1. int main()  
  2. {  
  3.     Timer t;   
  4.     char ch;   
  5.     hidden();//隐藏光标  
  6.     system("color 02");   
  7.     gotoxy(35,12);  
  8.     cout<<"00:00:00";  
  9.     gotoxy(20,18);  
  10.     cout<<"按a开始,按空格暂停,按s停止";  
  11.     while(1)  
  12.     {  
  13.         if(kbhit())  
  14.         {  
  15.             ch = getch();  
  16.             switch (ch)  
  17.             {  
  18.                 case 'a':t.Start();break;  
  19.                 case 's':t.Stop();break;  
  20.                 case ' ':t.Pause();break;  
  21.                 default :break;  
  22.             }  
  23.         }  
  24.         if(!t.isStop()&&!t.isPause())   
  25.         {  
  26.             t.show();  
  27.         }  
  28.     }  
  29.       
  30. }  

Timer t;定义一个计时器。hidden();是用来隐藏控制台光标的,不是必须的。
然后是进入死循环,kbhit()函数是检测是否有按键,如有按键返回非0值,没有按键返回0;用getch()获取按键,然后用switch case分支结构处理不同的按键。

至此,我们的计时器设计完成!是不是感觉很简单啊!吐舌头

让我们看一下运行结果:



下面是本程序用到的头文件:
[cpp] view plain copy
  1. #include <iostream>  
  2. #include <cstdlib>  
  3. #include <ctime>  
  4. #include <conio.h>  
  5. #include <iomanip>  
  6. #include <windows.h>  


下面是代码中用到的函数:
void gotoxy(int x,int y)
[cpp] view plain copy
  1. void gotoxy(int x, int y)//定位光标,x为行坐标,y为列坐标  
  2. {  
  3.     COORD pos = {x,y};//(坐标  位置);   
  4.     HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);  //得到标准处理(标准输出处理);   
  5.     SetConsoleCursorPosition(hOut, pos);//设置控制台光标位置;   
  6. }   

void hidden( )
[cpp] view plain copy
  1. void hidden()//隐藏光标  
  2. {  
  3.         HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);  
  4.         CONSOLE_CURSOR_INFO cci;  
  5.     GetConsoleCursorInfo(hOut,&cci);  
  6.     cci.bVisible=0;//赋1为显示,赋0为隐藏  
  7.     SetConsoleCursorInfo(hOut,&cci);  
  8. }  


下面贴上完整代码
[cpp] view plain copy
  1. #include <iostream>  
  2. #include <cstdlib>  
  3. #include <ctime>  
  4. #include <conio.h>  
  5. #include <iomanip>  
  6. #include <windows.h>  
  7.   
  8. using namespace std;  
  9. void gotoxy(int x, int y)//定位光标,x为行坐标,y为列坐标  
  10. {  
  11.     COORD pos = {x,y};//(坐标  位置);   
  12.     HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);  //得到标准处理(标准输出处理);   
  13.     SetConsoleCursorPosition(hOut, pos);//设置控制台光标位置;   
  14. }   
  15.   
  16. void hidden()//隐藏光标  
  17. {  
  18.         HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);  
  19.         CONSOLE_CURSOR_INFO cci;  
  20.     GetConsoleCursorInfo(hOut,&cci);  
  21.     cci.bVisible=0;//赋1为显示,赋0为隐藏  
  22.     SetConsoleCursorInfo(hOut,&cci);  
  23. }  
  24.   
  25. class Timer  
  26. {  
  27.     private:  
  28.         long start_time;  
  29.         long pause_time;  
  30.         //两个bool值标记四种状态   
  31.         bool is_pause; //记录计时器的状态 (是否处于暂停状态)  
  32.         bool is_stop;//是否处于停止状态   
  33.     public:  
  34.         Timer();  
  35.         bool isPause(); //返回计时器状态   
  36.         bool isStop();  
  37.         //计时器的三种动作(功能)   
  38.         void Start();   
  39.         void Pause();  
  40.         void Stop();  
  41.         inline long getStartTime() {return start_time;}  
  42.         void show();  
  43. };  
  44.   
  45. Timer::Timer()  
  46. {  
  47.     is_pause = false//初始化计时器状态   
  48.     is_stop = true;  
  49. }  
  50.   
  51.   
  52. bool Timer::isPause()  
  53. {     
  54.     if(is_pause)  
  55.     return true;  
  56.     else  
  57.     return false;  
  58. }  
  59.   
  60. bool Timer::isStop()  
  61. {  
  62.     if(is_stop)  
  63.         return true;  
  64.     return false;  
  65. }   
  66.   
  67. void Timer::Start() //开始   
  68. {  
  69.     if(is_stop)  
  70.     {  
  71.         start_time = time(0);  
  72.         is_stop = false;  
  73.     }  
  74.     else if(is_pause)  
  75.     {  
  76.         is_pause = false;  
  77.         start_time += time(0)-pause_time; //更新开始时间:用此时的时间 - 暂停时所用的时间 + 上一次开始的时间 = 此时的开始时间   
  78.     }  
  79. }  
  80.   
  81. void Timer::Pause() //暂停   
  82. {  
  83.     if(is_stop||is_pause) //如果处于停止/暂停状态,此动作不做任何处理,直接返回   
  84.         return;   
  85.     else    //否则调制为暂停状态  
  86.     {  
  87.         is_pause = true;  
  88.         pause_time = time(0); //获取暂停时间   
  89.     }  
  90. }  
  91. void Timer::Stop()  //停止   
  92. {  
  93.     if(is_stop) //如果正处于停止状态(不是暂停状态),不做任何处理   
  94.         return ;   
  95.     else if(is_pause) //改变计时器状态   
  96.     {  
  97.         is_pause = false;  
  98.         is_stop = true;  
  99.     }  
  100.     else if(!is_stop)  
  101.     {  
  102.         is_stop = true;  
  103.     }   
  104. }  
  105.   
  106. void Timer::show()  
  107. {  
  108.     long t = time(0) - start_time;  
  109.     gotoxy(35,12);  
  110.     cout<<setw(2)<<setfill('0')<<t/60/60<<":"  
  111.         <<setw(2)<<setfill('0')<<t/60<<":"  
  112.         <<setw(2)<<setfill('0')<<t%60<<endl;  
  113. }  
  114.   
  115. int main()  
  116. {  
  117.     Timer t;   
  118.     char ch;   
  119.     hidden();//隐藏光标  
  120.     system("color 02");   
  121.     gotoxy(35,12);  
  122.     cout<<"00:00:00";  
  123.     gotoxy(20,18);  
  124.     cout<<"按a开始,按空格暂停,按s停止";  
  125.     while(1)  
  126.     {  
  127.         if(kbhit())  
  128.         {  
  129.             ch = getch();  
  130.             switch (ch)  
  131.             {  
  132.                 case 'a':t.Start();break;  
  133.                 case 's':t.Stop();break;  
  134.                 case ' ':t.Pause();break;  
  135.                 default :break;  
  136.             }  
  137.         }  
  138.         if(!t.isStop()&&!t.isPause())   
  139.         {  
  140.             t.show();  
  141.         }  
  142.     }  
  143.       
  144. }  
0 0
原创粉丝点击