C语言电子秒表
小辉_Super 人气:0秒表是我们生活中常见的计时工具,特别是在运动会等比赛中,今天我就来写一个简单的电子秒表。
实现思路
这里简单介绍一下我的实现思路:
1、简单版:简单版本只实现了单次计时功能,即每次开启程序后就开始计时,如果按下键盘任意键,就结束计时,计时通过Sleep(1000)延时实现,每过1秒,计数值(总秒数)cnt加1,打印时,将总秒数cnt转换成时分秒进行显示。【Sleep()函数并不准确,只能实现粗略延时】
2、高级版:实现毫秒级计时,可重复计时(暂停、清零),计时使用gettimeofday()函数,用来获取系统的秒数和毫秒数,将计时开始和计时暂停的秒数相减,即可获得计时期间的秒数。细节请看代码部分。
简易版本
#include <stdio.h> #include <conio.h> //kbhit()/_kbhit() #include <Windows.h> //Sleep(ms) int main() { int hour = 0, min = 0, sec = 0; int cnt = 0; printf("按任意键停止计时\n"); while(!_kbhit()) //任意键退出循环(结束计时) { hour = cnt / 3600; //获取计时小时数 min = cnt / 60; //获取计时分钟数 sec = cnt % 60; //获取计时秒数 printf(" %02d:%02d:%02d\r", hour, min, sec); Sleep(1000); //1s延时 cnt++; } printf("\n程序退出\n"); return 0; }
运行效果:
高级版本
代码可能一般,但至少功能已经实现,仅供参考
下面给出几个注释的解释:
- 计时初始时间指的是开始计时或继续计时时的系统时间(第一次暂停后,如果继续计时,此时的系统时间即为新的计时初始时间)
- 当前累计计时时长指的是从开始计时到当前时刻的时间差,即真正的有效计时时长
- 总累计计时时长指的是计时初始时间之前的计时时间,这个值只有在计时暂停时才进行更新(如第一次暂停时,总累计计时时长 = 第一次暂停的系统时间 - 开始计时时的系统时间;第二次暂停时,总累计计时长 = 总累计计时时长 + 第二次在暂停的系统时间 - 上次继续计时时的系统时间…)
#include <stdio.h> #include <conio.h> //kbhit()/_kbhit() getch() #include <Windows.h> //Sleep(ms) #include <sys/time.h> //struct timeval #include <unistd.h> //struct timeval /****************************************************************************** * @brief 获取系统当前秒数和毫秒(1970-1-1 0:0:0到现在) * @param tv timeval结构体变量 * @param tv_s 返回的秒数 * @param tv_ms 返回的毫秒数 ******************************************************************************/ void Get_Current_Timeval(struct timeval *tv, long *tv_s, long *tv_ms) { gettimeofday(tv,NULL); //获取1970-1-1到现在的时间保存到timeval变量 *tv_s = tv->tv_sec; //获取秒 *tv_ms = tv->tv_usec / 1000;//获取毫秒 } /****************************************************************************** * @brief 获取两个timeval成员的差值,通过tv_s_diff和tv_ms_diff返回 * @param tv_s_cur 当前系统时间秒数 * @param tv_ms_cur 当前系统时间毫秒数 * @param tv_s_old 计时初始时间(s) * @param tv_ms_old 计时初始时间(ms) * @param tv_s_diff 秒数的差值 * @param tv_ms_diff 毫秒的差值 ******************************************************************************/ void Get_Diff_Timeval(long tv_s_cur, long tv_ms_cur,\ long tv_s_old, long tv_ms_old,\ long *tv_s_diff, long *tv_ms_diff) { if(tv_ms_cur < tv_ms_old) { *tv_ms_diff = tv_ms_cur + 1000 - tv_ms_old; //获取这段时间的毫秒数 *tv_s_diff = tv_s_cur - tv_s_old - 1; //获取这段时间的秒数(自上次暂停或自初始时间) } else { *tv_ms_diff = tv_ms_cur - tv_ms_old; //获取这段时间的毫秒数(自上次暂停或自初始时间) *tv_s_diff = tv_s_cur - tv_s_old; //获取这段时间的秒数(自上次暂停或自初始时间) } } /****************************************************************************** * 主函数 * ****************************************************************************/ int main(void) { struct timeval tv; long tv_s_cur = 0, tv_ms_cur = 0; //当前系统时间 long tv_s_old = 0, tv_ms_old = 0; //计时初始时间 long tv_s_diff = 0, tv_ms_diff = 0; //存放时间的差值 int sec_cnt = 0, msec_cnt = 0; //当前累计计时时长 int hour = 0, min = 0, sec = 0, msec = 0; int timer_step = 0; //计时步骤 0:未开始, //1:开始,2:暂停 char key = 0; /**************** 菜单打印 ****************/ printf("================================\n"); //菜单 printf("| 空格:开始/暂停 R:清零 Q:退出 |\n"); printf("================================\n"); printf("\t%02d:%02d:%02d %02d\r", 0, 0, 0, 0); while(1) { /**************** 键盘按键扫描+操作 ****************/ key = 0; if(_kbhit()) //检测到按键按下 key = getch(); //读取按键 switch(key) { case ' ': //按空格键开始/暂停计时 if(timer_step == 0) //如果还未开启计时 { //获取当前秒和毫秒作为计时初始时间 Get_Current_Timeval(&tv, &tv_s_old, &tv_ms_old); timer_step = 1; //开始计时 } else if(timer_step == 1) //如果正在计时 { timer_step = 2; //暂停计时 //获取当前秒和毫秒 Get_Current_Timeval(&tv, &tv_s_cur, &tv_ms_cur); //获取当前系统时间与计时初始时间的差值 Get_Diff_Timeval(tv_s_cur, tv_ms_cur, tv_s_old,\ tv_ms_old, &tv_s_diff, &tv_ms_diff); msec_cnt += tv_ms_diff; //更新总累计计时时长(ms) if(msec_cnt >= 1000) { msec_cnt -= 1000; sec_cnt += tv_s_diff + 1; //更新总累计计时时长(s) } else sec_cnt += tv_s_diff; } else if(timer_step == 2) { timer_step = 1; //继续计时 //获取当前秒和毫秒 Get_Current_Timeval(&tv, &tv_s_cur, &tv_ms_cur); tv_s_old = tv_s_cur; //更新计时初始时间(s) tv_ms_old = tv_ms_cur; //更新计时初始时间(ms) } break; case 'r': //按r/R清零计时时间 case 'R': sec_cnt = msec_cnt = 0; //总累计计时值清零 tv_s_old = tv_s_cur; //更新计时初始时间(s) tv_ms_old = tv_ms_cur; //更新计时初始时间(ms) timer_step = 0; //回到步骤0(未开始计时) printf("\t%02d:%02d:%02d %02d\r", 0, 0, 0, 0); break; case 'q': case 'Q': printf("程序退出\n");return 0; } /**************** 计时操作 ****************/ if(timer_step == 1) { //获取当前秒和毫秒 Get_Current_Timeval(&tv, &tv_s_cur, &tv_ms_cur); //获取当前系统时间与计时初始时间的差值 Get_Diff_Timeval(tv_s_cur, tv_ms_cur, tv_s_old,\ tv_ms_old, &tv_s_diff, &tv_ms_diff); tv_ms_diff += msec_cnt; //当前累计计时时长(ms) if(tv_ms_diff >= 1000) { tv_ms_diff -= 1000; tv_s_diff += sec_cnt + 1; //当前累计计时时长(s) } else tv_s_diff += sec_cnt; hour = tv_s_diff / 3600; //获取计时小时数 min = tv_s_diff /60; //获取计时分钟数 sec = tv_s_diff % 60; //获取计时秒数 msec = tv_ms_diff / 10; //获取毫秒(单位10ms) //打印当前累计计时时长 printf("\t%02d:%02d:%02d %02d\r", hour, min, sec, msec); } Sleep(10); //10ms延时,防止打印太快导致显示效果不佳 } return 0; }
运行效果:
加载全部内容