C語(yǔ)言實(shí)現(xiàn)電子秒表
秒表是我們生活中常見(jiàn)的計(jì)時(shí)工具,特別是在運(yùn)動(dòng)會(huì)等比賽中,今天我就來(lái)寫(xiě)一個(gè)簡(jiǎn)單的電子秒表。
實(shí)現(xiàn)思路
這里簡(jiǎn)單介紹一下我的實(shí)現(xiàn)思路:
1、簡(jiǎn)單版:簡(jiǎn)單版本只實(shí)現(xiàn)了單次計(jì)時(shí)功能,即每次開(kāi)啟程序后就開(kāi)始計(jì)時(shí),如果按下鍵盤(pán)任意鍵,就結(jié)束計(jì)時(shí),計(jì)時(shí)通過(guò)Sleep(1000)延時(shí)實(shí)現(xiàn),每過(guò)1秒,計(jì)數(shù)值(總秒數(shù))cnt加1,打印時(shí),將總秒數(shù)cnt轉(zhuǎn)換成時(shí)分秒進(jìn)行顯示?!維leep()函數(shù)并不準(zhǔn)確,只能實(shí)現(xiàn)粗略延時(shí)】
2、高級(jí)版:實(shí)現(xiàn)毫秒級(jí)計(jì)時(shí),可重復(fù)計(jì)時(shí)(暫停、清零),計(jì)時(shí)使用gettimeofday()函數(shù),用來(lái)獲取系統(tǒng)的秒數(shù)和毫秒數(shù),將計(jì)時(shí)開(kāi)始和計(jì)時(shí)暫停的秒數(shù)相減,即可獲得計(jì)時(shí)期間的秒數(shù)。細(xì)節(jié)請(qǐng)看代碼部分。
簡(jiǎn)易版本
#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("按任意鍵停止計(jì)時(shí)\n"); ? ? while(!_kbhit()) ? ? ? ? ? ?//任意鍵退出循環(huán)(結(jié)束計(jì)時(shí)) ? ? { ? ? ? ? hour = cnt / 3600; ? ? ?//獲取計(jì)時(shí)小時(shí)數(shù) ? ? ? ? min = cnt / 60; ? ? ? ? ?//獲取計(jì)時(shí)分鐘數(shù) ? ? ? ? sec = cnt % 60; ? ? ? ? //獲取計(jì)時(shí)秒數(shù) ? ? ? ? printf(" ?%02d:%02d:%02d\r", hour, min, sec); ? ? ? ? Sleep(1000); ? ? ? ? ? ?//1s延時(shí) ? ? ? ? cnt++; ? ? } ? ? printf("\n程序退出\n"); ? ? return 0; }
運(yùn)行效果:
高級(jí)版本
代碼可能一般,但至少功能已經(jīng)實(shí)現(xiàn),僅供參考
下面給出幾個(gè)注釋的解釋?zhuān)?/strong>
- 計(jì)時(shí)初始時(shí)間指的是開(kāi)始計(jì)時(shí)或繼續(xù)計(jì)時(shí)時(shí)的系統(tǒng)時(shí)間(第一次暫停后,如果繼續(xù)計(jì)時(shí),此時(shí)的系統(tǒng)時(shí)間即為新的計(jì)時(shí)初始時(shí)間)
- 當(dāng)前累計(jì)計(jì)時(shí)時(shí)長(zhǎng)指的是從開(kāi)始計(jì)時(shí)到當(dāng)前時(shí)刻的時(shí)間差,即真正的有效計(jì)時(shí)時(shí)長(zhǎng)
- 總累計(jì)計(jì)時(shí)時(shí)長(zhǎng)指的是計(jì)時(shí)初始時(shí)間之前的計(jì)時(shí)時(shí)間,這個(gè)值只有在計(jì)時(shí)暫停時(shí)才進(jìn)行更新(如第一次暫停時(shí),總累計(jì)計(jì)時(shí)時(shí)長(zhǎng) = 第一次暫停的系統(tǒng)時(shí)間 - 開(kāi)始計(jì)時(shí)時(shí)的系統(tǒng)時(shí)間;第二次暫停時(shí),總累計(jì)計(jì)時(shí)長(zhǎng) = 總累計(jì)計(jì)時(shí)時(shí)長(zhǎng) + 第二次在暫停的系統(tǒng)時(shí)間 - 上次繼續(xù)計(jì)時(shí)時(shí)的系統(tǒng)時(shí)間…)
#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 ? ? ? 獲取系統(tǒng)當(dāng)前秒數(shù)和毫秒(1970-1-1 0:0:0到現(xiàn)在) ?* @param tv ? ?timeval結(jié)構(gòu)體變量 ?* @param tv_s ?返回的秒數(shù) ?* @param tv_ms 返回的毫秒數(shù) ?******************************************************************************/ void Get_Current_Timeval(struct timeval *tv, long *tv_s, long *tv_ms) { ? ? gettimeofday(tv,NULL); ? ? ?//獲取1970-1-1到現(xiàn)在的時(shí)間保存到timeval變量 ? ? *tv_s = tv->tv_sec; ? ? ? ? //獲取秒 ? ? *tv_ms = tv->tv_usec / 1000;//獲取毫秒 } /****************************************************************************** ?* @brief ? ? ? ? ? ?獲取兩個(gè)timeval成員的差值,通過(guò)tv_s_diff和tv_ms_diff返回 ?* @param tv_s_cur ? 當(dāng)前系統(tǒng)時(shí)間秒數(shù) ?* @param tv_ms_cur ?當(dāng)前系統(tǒng)時(shí)間毫秒數(shù) ?* @param tv_s_old ? 計(jì)時(shí)初始時(shí)間(s) ?* @param tv_ms_old ?計(jì)時(shí)初始時(shí)間(ms) ?* @param tv_s_diff ?秒數(shù)的差值 ?* @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; ?//獲取這段時(shí)間的毫秒數(shù) ? ? ? ? *tv_s_diff = tv_s_cur - tv_s_old - 1; //獲取這段時(shí)間的秒數(shù)(自上次暫?;蜃猿跏紩r(shí)間) ? ? } ? ? else ? ? { ? ? ? ? *tv_ms_diff = tv_ms_cur - tv_ms_old; ?//獲取這段時(shí)間的毫秒數(shù)(自上次暫?;蜃猿跏紩r(shí)間) ? ? ? ? *tv_s_diff = tv_s_cur - tv_s_old; ? ? //獲取這段時(shí)間的秒數(shù)(自上次暫?;蜃猿跏紩r(shí)間) ? ? } } /****************************************************************************** ?* 主函數(shù) ?* ****************************************************************************/ int main(void) { ? ? struct timeval tv; ? ? long tv_s_cur = 0, tv_ms_cur = 0; ? //當(dāng)前系統(tǒng)時(shí)間 ? ? long tv_s_old = 0, tv_ms_old = 0; ? //計(jì)時(shí)初始時(shí)間 ? ? long tv_s_diff = 0, tv_ms_diff = 0; //存放時(shí)間的差值 ? ? int sec_cnt = 0, msec_cnt = 0; ? ? ?//當(dāng)前累計(jì)計(jì)時(shí)時(shí)長(zhǎng) ? ? int hour = 0, min = 0, sec = 0, msec = 0; ? ? int timer_step = 0; ? ? ? ? ? ? ? ? //計(jì)時(shí)步驟 0:未開(kāi)始, ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? //1:開(kāi)始,2:暫停 ? ? char key = 0; ? ? /**************** 菜單打印 ****************/ ? ? printf("================================\n"); //菜單 ? ? printf("| 空格:開(kāi)始/暫停 R:清零 Q:退出 |\n"); ? ? printf("================================\n"); ? ? printf("\t%02d:%02d:%02d %02d\r", 0, 0, 0, 0); ? ? while(1) ? ? { ? ? ? ? /**************** 鍵盤(pán)按鍵掃描+操作 ****************/ ? ? ? ? key = 0; ? ? ? ? if(_kbhit()) ? ? ? ? ? ? ? ? ? ? ?//檢測(cè)到按鍵按下 ? ? ? ? ? ? key = getch(); ? ? ? ? ? ? ? ?//讀取按鍵 ? ? ? ? switch(key) ? ? ? ? { ? ? ? ? ? ? case ' ': ? ? ? ? ? ? ? ? ? ? //按空格鍵開(kāi)始/暫停計(jì)時(shí) ? ? ? ? ? ? ? ? if(timer_step == 0) ? ? ? //如果還未開(kāi)啟計(jì)時(shí) ? ? ? ? ? ? ? ? { ? ? ? ? ? ? ? ? ? ? //獲取當(dāng)前秒和毫秒作為計(jì)時(shí)初始時(shí)間 ? ? ? ? ? ? ? ? ? ? Get_Current_Timeval(&tv, &tv_s_old, &tv_ms_old); ? ? ? ? ? ? ? ? ? ? timer_step = 1; ? ? ? //開(kāi)始計(jì)時(shí) ? ? ? ? ? ? ? ? } ? ? ? ? ? ? ? ? else if(timer_step == 1) ?//如果正在計(jì)時(shí) ? ? ? ? ? ? ? ? { ? ? ? ? ? ? ? ? ? ? timer_step = 2; ? ? ? //暫停計(jì)時(shí) ? ? ? ? ? ? ? ? ? ? //獲取當(dāng)前秒和毫秒 ? ? ? ? ? ? ? ? ? ? Get_Current_Timeval(&tv, &tv_s_cur, &tv_ms_cur); ? ? ? ? ? ? ? ? ? ? //獲取當(dāng)前系統(tǒng)時(shí)間與計(jì)時(shí)初始時(shí)間的差值 ? ? ? ? ? ? ? ? ? ? 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; ? ? ? //更新總累計(jì)計(jì)時(shí)時(shí)長(zhǎng)(ms) ? ? ? ? ? ? ? ? ? ? if(msec_cnt >= 1000) ? ? ? ? ? ? ? ? ? ? { ? ? ? ? ? ? ? ? ? ? ? ? msec_cnt -= 1000; ? ? ? ? ? ? ? ? ? ? ? ? sec_cnt += tv_s_diff + 1; //更新總累計(jì)計(jì)時(shí)時(shí)長(zhǎng)(s) ? ? ? ? ? ? ? ? ? ? } ? ? ? ? ? ? ? ? ? ? else ? ? ? ? ? ? ? ? ? ? ? ? sec_cnt += tv_s_diff; ? ? ? ? ? ? ? ? } ? ? ? ? ? ? ? ? else if(timer_step == 2) ? ? ? ? ? ? ? ? { ? ? ? ? ? ? ? ? ? ? timer_step = 1; ? ? ? ? ? ? ? ?//繼續(xù)計(jì)時(shí) ? ? ? ? ? ? ? ? ? ? //獲取當(dāng)前秒和毫秒 ? ? ? ? ? ? ? ? ? ? Get_Current_Timeval(&tv, &tv_s_cur, &tv_ms_cur); ? ? ? ? ? ? ? ? ? ? tv_s_old = tv_s_cur; ? ? ? ? ? //更新計(jì)時(shí)初始時(shí)間(s) ? ? ? ? ? ? ? ? ? ? tv_ms_old = tv_ms_cur; ? ? ? ? //更新計(jì)時(shí)初始時(shí)間(ms) ? ? ? ? ? ? ? ? } ? ? ? ? ? ? ? ? break; ? ? ? ? ? ? case 'r': ? ? ? ? ? ? ? ? ? ? //按r/R清零計(jì)時(shí)時(shí)間 ? ? ? ? ? ? case 'R': ? ? ? ? ? ? ? ? sec_cnt = msec_cnt = 0; ? //總累計(jì)計(jì)時(shí)值清零 ? ? ? ? ? ? ? ? tv_s_old = tv_s_cur; ? ? ?//更新計(jì)時(shí)初始時(shí)間(s) ? ? ? ? ? ? ? ? tv_ms_old = tv_ms_cur; ? ?//更新計(jì)時(shí)初始時(shí)間(ms) ? ? ? ? ? ? ? ? timer_step = 0; ? ? ? ? ? //回到步驟0(未開(kāi)始計(jì)時(shí)) ? ? ? ? ? ? ? ? printf("\t%02d:%02d:%02d %02d\r", 0, 0, 0, 0); ? ? ? ? ? ? ? ? break; ? ? ? ? ? ? case 'q': ? ? ? ? ? ? case 'Q': printf("程序退出\n");return 0; ? ? ? ? } ? ? ? ? /**************** 計(jì)時(shí)操作 ****************/ ? ? ? ? if(timer_step == 1) ? ? ? ? { ? ? ? ? ? ? //獲取當(dāng)前秒和毫秒 ? ? ? ? ? ? Get_Current_Timeval(&tv, &tv_s_cur, &tv_ms_cur); ? ? ? ? ? ? //獲取當(dāng)前系統(tǒng)時(shí)間與計(jì)時(shí)初始時(shí)間的差值 ? ? ? ? ? ? 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; ? ? ? ? ?//當(dāng)前累計(jì)計(jì)時(shí)時(shí)長(zhǎng)(ms) ? ? ? ? ? ? if(tv_ms_diff >= 1000) ? ? ? ? ? ? { ? ? ? ? ? ? ? ? tv_ms_diff -= 1000; ? ? ? ? ? ? ? ? tv_s_diff += sec_cnt + 1; ? ?//當(dāng)前累計(jì)計(jì)時(shí)時(shí)長(zhǎng)(s) ? ? ? ? ? ? } ? ? ? ? ? ? else ? ? ? ? ? ? ? ? tv_s_diff += sec_cnt; ? ? ? ? ? ? hour = tv_s_diff / 3600; ? ? ? ? //獲取計(jì)時(shí)小時(shí)數(shù) ? ? ? ? ? ? min = tv_s_diff /60; ? ? ? ? ? ? //獲取計(jì)時(shí)分鐘數(shù) ? ? ? ? ? ? sec = tv_s_diff % 60; ? ? ? ? ? ?//獲取計(jì)時(shí)秒數(shù) ? ? ? ? ? ? msec = tv_ms_diff / 10; ? ? ? ? ?//獲取毫秒(單位10ms) ? ? ? ? ? ? //打印當(dāng)前累計(jì)計(jì)時(shí)時(shí)長(zhǎng) ? ? ? ? ? ? printf("\t%02d:%02d:%02d %02d\r", hour, min, sec, msec); ? ? ? ? } ? ? ? ? Sleep(10); ? ? ? //10ms延時(shí),防止打印太快導(dǎo)致顯示效果不佳 ? ? } ? ? return 0; }
運(yùn)行效果:
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
C語(yǔ)言數(shù)據(jù)結(jié)構(gòu)與算法之圖的遍歷(二)
這篇文章主要是介紹了利用廣度優(yōu)先算法實(shí)現(xiàn)圖的遍歷,文中利用圖文詳細(xì)的介紹了實(shí)現(xiàn)步驟,對(duì)我們學(xué)習(xí)數(shù)據(jù)結(jié)構(gòu)與算法有一定的幫助,需要的朋友可以參考一下2021-12-12淺析C/C++中的可變參數(shù)與默認(rèn)參數(shù)
C支持可變參數(shù)的函數(shù),這里的意思是C支持函數(shù)帶有可變數(shù)量的參數(shù),最常見(jiàn)的例子就是我們十分熟悉的printf()系列函數(shù)。我們還知道在函數(shù)調(diào)用時(shí)參數(shù)是自右向左壓棧的2013-09-09C++實(shí)現(xiàn)單例模式的自動(dòng)釋放
這篇文章主要為大家詳細(xì)介紹了C++實(shí)現(xiàn)單例模式的自動(dòng)釋放,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-06-06解析內(nèi)存對(duì)齊 Data alignment: Straighten up and fly right的詳解
對(duì)于所有直接操作內(nèi)存的程序員來(lái)說(shuō),數(shù)據(jù)對(duì)齊都是很重要的問(wèn)題.數(shù)據(jù)對(duì)齊對(duì)你的程序的表現(xiàn)甚至能否正常運(yùn)行都會(huì)產(chǎn)生影響2013-05-05C++數(shù)據(jù)結(jié)構(gòu)之搜索二叉樹(shù)的實(shí)現(xiàn)
了解搜索二叉樹(shù)是為了STL中的map和set做鋪墊,我們所熟知的AVL樹(shù)和平衡搜索二叉樹(shù)也需要搜索二叉樹(shù)的基礎(chǔ)。本文將詳解如何利用C++實(shí)現(xiàn)搜索二叉樹(shù),需要的可以參考一下2022-05-05