用C++做一个计时器(Timer)
用C++写了一个计时器,总体上说拥有倒计时和正计时两个功能。
既然是计时器,那么肯定和时间有关,所以还是提前声明一下计时器的核心函数是什么。那就是包含于头文件windows.h中的Sleep函数,注意,如果是windows系统的话,在这里S要大写的。
1.Sleep函数可以使计算机程序(进程,任务或线程)进入休眠,使其在一段时间内处于非活动状态。当函数设定的计时器到期,或者接收到信号、程序发生中断都会导致程序继续执行。
2.Sleep()函数的调用需要一个时间作为参数,代表程序执行挂起的时间间隔。通常参数的单位是秒,但在一些更加精确的操作系统中能以毫秒甚至是微秒为单位。
3.Sleep函数的一般形式:Sleep(unsigned long);
其中,Sleep()里面的单位,是以毫秒为单位,所以如果想让函数滞留1秒的话,应该是Sleep(1000);
在Linux下,sleep中的“s”不大写
sleep()单位为秒,usleep()里面的单位是微秒。在内核中,sleep的实现是由pause函数和alarm函数两个实现的。
特别注意在Codeblocks环境下是无法使用sleep函数的,因为在windows上Codeblocks采用mingw(Gnu在Window环境下的编译器,可以充分使用WindowsApi)作为编译器,而在stdlib.h中sleep的说明如下:_CRTIMP void __cdecl __MINGW_NOTHROW _sleep (unsigned long) __MINGW_ATTRIB_DEPRECATED;可以认为mingw舍弃了sleep函数,建议用Sleep实现sleep。
好了,话不多说,直接上代码啦︿( ̄︶ ̄)︿
#include<iostream>
#include<Windows.h>
#include<time.h>
#include<conio.h>
#include<cstdlib>
using namespace std;
void menu(void)
{
cout << "=========================================" << endl;
cout << "=================计时器==================" << endl;
cout << "=========================================" << endl;
cout << "===============1.开始计时================" << endl;
cout << "=========================================" << endl;
cout << "===============2.倒计时==================" << endl;
cout << "=========================================" << endl;
cout << "===============3.退出计时================" << endl;
cout << "=========================================" << endl;
}
上面是各种头文件包含以及命名空间的声明还有菜单函数,注意windows.h必须要包含,其他的没什么需要特别指出的。
接着就是Timer1函数,这里是用于正常计时而非倒计时:
Timer1():
void Timer1(void)
{
cout << "空格键暂停,在确定继续计时时需要连续两次键入除空格以外的按键即可继续进行计时..." << endl; //开局说明
system("pause&&cls");
int hour = 0, minute = 0, second = 0, i, j;
char pause, c;
for (i = 0, j = 0; i < 100000; i++)
{
cout << "当前时间:" << endl;
second = i - j;
cout << hour << " : " << minute << " : " << second << endl;
if (second == 60) //满60秒加一分钟
{
minute++;
i = 0;
}
if (minute == 60) //满60分钟加一个小时,小时上不封顶
{
hour++;
minute = 0;
}
while (kbhit())
{
pause = getch();
}
if (pause == 32) //摁下空格就会暂停当前计时
{
cout << "是否退出当前计时?(Y/N)" << endl;
cin >> c;
if (c == 'y' || c == 'Y')
{
break;
}
}
Sleep(940);
system("cls");
}
}
在这里不难看出是通过for循环计算秒来实现对秒的更新,再通过清屏函数来把更新之后的每一分每一秒再通过cout函数来输出到屏幕上。秒更新了,分就更新,时也会更新。
之后再通过conio.h中的kbhit函数和getch函数来读取我们在计时中的摁键操作,在注释中标明的摁下空格就可以暂停当前计时(空格的ascii码是32),然后再通过连续的两次键入其他摁键就可以解除当前的暂停计时。大家应该对键入空格可以暂停计时的原理是明白的,但是也许会有人不太理解为什么连续键入两次其他摁键才能暂停计时,我来解释一下原理:在键入N/n来确定继续计时之后,此时回车确定输入n,也就是键入一次。在等待一段时间后会再次进入for循环,之后由于while(kbhit())下的getch会读取余健也就是上次输入的空格,所以此时会继续暂停并提示是否继续计时,这就导致程序”卡住了“。只有连续摁两次键,在回车确认输入n之后再跟一个回车那么此时while(kbhit())下的getch会读取余健也就是上次输入的其他摁键(在这里是回车),所以可以正常继续运行程序,继续计时,直到不想计时了键入Y/y来退出计时返回主菜单。
那么这时候大家可能会问:不是一秒来刷新一次吗?为什么是Sleep(940)呢,不是Sleep(1000)呢,不是刚刚说完一秒的计时需要Sleep(1000)吗?
确实,从理论上来讲,确实应该是Sleep(1000),但是由于进程调度的问题,当再次接收到信号执行程序时就会发生延迟的问题,也就是精度没有那么高,会出现实际上的延时时间长于所设定的时间的问题。 比如设置Sleep(1000),准确的时间可能是1.04秒、1.05秒左右(Sleep(1000)在我的电脑上实验一分钟内的误差足足有4秒,比标准时间慢了四秒,当然,这和操作系统硬件都有关系,换一台电脑或许就不一样了)所以为了提高精度,让延时时间更接近一秒钟,我们就选择调低参数,即Sleep(940),这是我实践多次得到的结果,和标准时间几乎没有差异。
Sleep()这个函数可以让线程睡眠一段时间,而后继续执行,参数是毫秒。
但是我们会发现,当毫秒数过小时,Sleep往往不能按照给定的时间睡眠,而是睡了长了一点的时间,这是由于Sleep函数的精度导致的,一般的系统默认的精度是10毫秒,也就是说,如果参数小于10,那么Sleep的时间可能是10,或者更多,系统尽量以10毫秒为精度保证时间准确,这对于高精度的程序来说明显不足,系统时钟clock()函数也存在类似问题。
在这里切记,Sleep(unsigned int)是有精度缺失的,要调低它的参数(比如1000到940)才能让计时器更加精准。
接下来,就是Timer2函数,用于倒计时可以设置任意时间:
Timer2():
void Timer2(void)
{
system("cls");
int time, i;
while (1)
{
cout << "请输入你要求的倒计时时间(秒):" << endl;
cin >> time;
while (time > 0)
{
system("cls");
cout << "当前剩余:" << time << "秒" << endl;
time--;
Sleep(940);
}
char select;
cout << "计时结束,是否继续进行倒计时(Y/N):" << endl;
cin >> select;
if (select == 'n' || select == 'N')
{
break;
}
}
}
依然不要忘了Sleep的有关问题,在这里没什么特别强调的,退出即返回主菜单界面。
main函数:
int main(void)
{
int choice;
while (1)
{
system("color 6");
system("cls");
menu();
cout << "请输入你的选择:" << endl;
cin >> choice;
switch (choice)
{
case 1:
{
Timer1();
break;
}
case 2:
{
Timer2();
break;
}
case 3:
{
cout << "正在退出......" << endl;
Sleep(800);
exit(0);
}
default:
{
cout << "输入无效,请尝试重新输入..." << endl;
system("pause");
continue;
break;
}
}
}
return 0;
}
到这里就算是结束啦ヾ( ̄ー ̄)X*
完成了一个简易的计时器(精准度个人觉得还是可以的了),写了一些总结,有错误的话还请大家指出★,°:.☆( ̄▽ ̄)/$:.°★