C语言小项目——电子秒表(毫秒级)
秒表是我们生活中常见的计时工具,特别是在运动会等比赛中,今天我就来写一个简单的电子秒表。
文章目录
- 实现思路
- 简易版本
- 高级版本
实现思路
这里简单介绍一下我的实现思路:
- 简单版:简单版本只实现了单次计时功能,即每次开启程序后就开始计时,如果按下键盘任意键,就结束计时,计时通过
Sleep(1000)
延时实现,每过1秒,计数值(总秒数)cnt
加1,打印时,将总秒数cnt
转换成时分秒进行显示。【Sleep()函数并不准确,只能实现粗略延时】 - 高级版:实现毫秒级计时,可重复计时(暂停、清零),计时使用
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)}elsesec_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)}elsetv_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;
}
运行效果:
C语言小项目——电子秒表(毫秒级)相关推荐
- c语言为什么要建项目,一个C语言小项目为什么都说牛逼
原标题:一个C语言小项目为什么都说牛逼 意在鼓励C语言学者.更有兴趣,学习更富有创业和乐趣! 推荐加学习交流群:658807522 可以在一起学习交流,既是参赛选手,又是学者,也可以先学习再参赛,反正 ...
- C语言小项目——走迷宫
C语言小项目--走迷宫 设计方向: 1.定义二维字符数组作为迷宫 2.定义变量记录老鼠的位置 3.判定移动后位置的变化 4.记录游戏时长 5.判定到达终点的条件 总体设计: 1.用不同字符代表墙.老鼠 ...
- C语言小项目之“究极无敌螺旋丸极爆炸狂拽炫酷五彩棒的”通讯录之*派小猩*作品
C语言小项目之"究极无敌螺旋丸极爆炸狂拽炫酷五彩棒的"通讯录之派小猩作品 项目概述 基于C语言开发一个多功能的通讯录 功能目录 1.增加 2.删除 3.查找 4.修改 5.显示 6 ...
- C语言小项目——通讯录的存储系统(静态版,动态版,文件版)
目录 前言 一.总体设计框架 二.三种通讯录的功能阐述 三.静态通讯录 1.结构体设计 2.初始化通讯录 3.增加联系人的信息 4.删除联系人的信息 5.查找指定联系人并打印 6.修改联系人的信息 7 ...
- 嵌入式培训经验分享——C语言小项目(五子棋)
在学习了C语言的基本语法之后,我们可以尝试着来做一个小小的项目,下面是我尝试着做的一个小项目-----五子棋,分享给大家,功能不太完善,多多指教,里面没有用到指针的知识点. #include < ...
- C语言小项目Conway‘s_Game_of_Life
这是我C语言的一个小项目,如有Bug请指出. 用C语言来实现Conway's_Game_of_Life 规则: 细胞有存活或死亡两种状态,与自身周围的八个细胞互动 细胞周围的存活细胞 == 2个时,该 ...
- C语言小项目之猜数字
学习完c语言循环.选择内容,我们对c语言有个初步的认识了,让我们来实现一个小项目吧!!! 1.猜数字小项目分析: 我们利用c语言制造出随机数来猜,在只知道范围的前提下我们无非有以下三种可能,猜大了.猜 ...
- C语言小项目-《通讯录》(超详细讲解)
加油加油!!! 文章目录 前言 一:静态库通讯录 1:通讯录介绍 1.1代码主体框架的介绍 1.2 要实现的功能 2:通讯录实现 2.1 通讯录的外部封装 2.1 创建通讯录 2.2 初始化通讯录 2 ...
- 学习笔记10-C语言-小项目-五子棋
小项目: 需要的数据 1.定义棋盘的二维数组 2.定义变量用于记录下棋的坐标 3.定义角色 @ 黑棋 O 白棋 * 空位业务逻辑: 是否需要对数据初始化 for(;;) {1.清屏.显示棋盘2.落子坐 ...
- C语言小项目实践——日历程序
完整代码包已经上传至我的down,修改请保留原作者注释 http://download.csdn.net/detail/xuptacm/9835030 炫迈日历计划研究报告 1.引言 日常生活中我们往 ...
最新文章
- CART树 python小样例
- 看完这篇!Linux网络基础知识通关!
- Android 单击+双击+短按+长按 逻辑
- VUE : 双重 for 循环写法、table 解析任意 list 、万能表格组件、解析一维数组、动态生成 table 所有数据
- 方法论:如何从0到1搭建一套完整的邀请体系
- Eureka获取注册信息
- nvm use切换node版本,但是切换后没有*号
- neo4j 节点与关系
- linux shell解析1
- 多表查询, 聚集查询和分组查询
- c#教程与视频教程类专题资料免费下载整理合集
- 关于metasploit的一些架构目录
- 时间片轮转调度算法(Java)
- 根据后缀名/扩展名获取content-type/Mime类型
- SecureCRT/FX的破解软件注册机被系统自动删除解决办法
- HDU3404POJ3533(Nim积摸版)
- phhphphphphphphp转自 细雪之舞 专注DEV
- Bibexcel 与 Pajek 基本分析
- 【矩阵论】2. 矩阵分解——SVD
- python爬虫代理ip_Python爬虫如何获取代理ip及ip验证?