C語言實現電子秒表
秒表是我們生活中常見的計時工具,特別是在運動會等比賽中,今天我就來寫一個簡單的電子秒表。
實現思路
這裡簡單介紹一下我的實現思路:
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; }
運行效果:
以上就是本文的全部內容,希望對大傢的學習有所幫助,也希望大傢多多支持WalkonNet。