首页>>科技 >>内容

时间规划c++编程题目及答案解析,C++日期和时间编程总结

发布时间:2023-12-19 09:30:10编辑:温柔的背包来源:

很多朋友对时间规划c++编程题目及答案解析,C++日期和时间编程总结不是很了解,每日小编刚好整理了这方面的知识,今天就来带大家一探究竟。

时间规划c++编程题目及答案解析,C++日期和时间编程总结

目录

一、概述

2.C风格的日期和时间库

2.1、数据类型

2.2、功能

2.3、梳理数据类型与函数的关系

2.4、时间类型

2.5、输出时间和日期

2.6、综合示例代码

3.计时库

3.1、时钟

3.2、C风格转换

3.3、时长比

3.4、时间间隔持续时间

3.5、时间点time_point

C++11的日期和时间编程内容在《C++ Primer(第五版)》一书中没有介绍。目前网上的文章大多质量堪忧或者不系统,所以写这篇文章是为了自己的技术积累和技术分享,大部分内容来自于网上资料,文末也给出了参考链接文章。

日期和时间库是每种编程语言都提供的内部库。可以用来打印模块时间以方便性能分析,也可以用来打印运行时间点。本文内容重点关注C++11-C++17。虽然C++20的日期和时钟库使用起来更加方便和强大,但由于版本兼容性和程序移植问题,不会深入讨论。

一、概述

C++ 中可用的日期和时间API 分为两类:

C 风格的日期时间库,位于头文件中。这是原始头文件的C++ 版本。

Chrono库:C++ 11中有一个新的API,增加了时间点、持续时间和时钟相关的接口(使用起来比较复杂)。

在C++11之前,C++编程只能使用C风格的日期时间库,其精度仅为秒级,对于精度要求较高的程序来说是不够的。但这个问题在C++11中已经得到解决。 C++11不仅扩展了精度要求,还提供了对不同系统的时间要求的支持。另一方面,对于只能使用C风格日期和时间库的程序,C++17中也添加了timespec,将精度提高到纳秒级别。

2.C风格的日期和时间库

#include 该头文件包含用于获取和操作日期和时间的函数和相关数据类型定义。

2.1、数据类型

名称说明time_t 可以表示基本算术类型time 的别名,可以表示函数time 返回的时间,单位为秒。 Clock_t 基本算术类型的别名,能够表示时钟滴答计数(可用作进程运行时)。 size_tsizeof 运算符返回的无符号整数类型。 struct tm 包含日历日期和时间结构体类型timespec* 时间以秒和纳秒表示2.2、函数

C风格日期时间库包含的时间操作函数如下:

函数说明std:clock_t clock() 返回自程序启动以来的处理器时钟时间。 double difftime(std:time_t time_end, std:time_t time_beg) 计算开始和结束之间的秒数std:time_t time (time_t*timer) 返回自纪元以来的当前系统时间。函数可以是空指针std:time_t mktime(struct tm * timeptr)将tm格式的时间转换为time_t表示的时间。时间转换函数如下:

函数说明char* asctime(const struct tm* timeptr) 将tm 结构体对象转换为字符串的文本char* ctime(const time_t* timer) 将time_t 对象转换为C 字符串,用于表示日历时间struct tm* gmtime (const time_t* time) 将time_t转换为UTC表示的时间struct tm* localtime (const time_t* timer) 将time_t转换为本地时间localtime函数使用参数timer指向的值填充tm结构体,其中值代表相应的时间,以本地时区表示。

strftime和wcsftime函数一般不常用,所以不再介绍。 tm结构体的一般定义如下:

structtm{inttm_sec;inttm_min;inttm_hour;inttm_mday;inttm_mon;inttm_year;inttm_wday;inttm_yday ;inttm_isdst;};

2.3、梳理数据类型与函数的关系

有许多与时间和日期相关的函数和数据类型。仅仅通过查看表格和代码并不容易记住。第一个参考链接的作者给出了如下所示的思维导图,方便记忆和理解上述所有函数和数据类型。他们之间各自的联系。

思维导图来自参考链接中的第一篇文章。后续思维导图出处也大同小异,不再一一注明。

这张图中,以数据类型为中心,带方向的实线箭头表示该函数可以返回对应类型的结果。

时钟函数是一个相对独立的函数,返回进程的运行时间。请参阅下面的详细描述。

time_t描述的是纪元时间,可以通过time函数获取,但只能精确到秒级。

timespec类型在time_t的基础上增加了纳秒精度,通过timespec_get获取。这是C++17 中的新功能。

tm 是一种日历类型,因为它包含年、月、日等信息。 time_t 和tm 类型可以通过gmtime、localtime 和mktime 函数相互转换。

考虑到时区的差异,有两个函数,gmtime和localtime。

无论是time_t还是tm结构体,都可以以字符串格式输出。 ctime 和asctime 输出的格式是固定的。如果需要自定义格式,则需要使用strftime或wcsftime函数。

2.4、时间类型

2.4.1、UTC时间

协调世界时(UTC) 是最重要的时间标准。它基于原子时间秒,并尽可能接近格林威治标准时间。

协调世界时是世界上调节时钟和时间的主要时间标准。它与0度经度的平均太阳时相差不超过1秒。因此,UTC时间+8即可得到北京标准时间(UTC+8)。

2.4.2、当地时间

当地时间与当地时区相关。例如,中国当地时间采用北京标准时间(UTC+8)。

2.4.3、纪元时间

Epoch 时间也称为Unix 时间或POSIX 时间。它表示自1970 年1 月1 日00:00 UTC 以来经过的秒数(不考虑闰秒)。它广泛应用于操作系统和文件格式。 ****** 头文件使用time_t 来表示纪元时间(以秒为单位)**。

纪元时间的思想很简单:从一个时间开始,加上偏移量就可以表示任何其他时间。

为什么选择这个时间作为起点呢?您可以点击这里:为什么1/1/1970 是“纪元时间”?

通过time函数获取当前时刻的纪元时间示例代码如下:

time_tepoch_time=time(nullptr);cout'Epochtime:'epoch_timeendl;//Epochtime:1660039180(日历时间:TueAug917402022)

time 函数接受一个指向要存储时间的对象的指针。通常可以传递一个空指针,然后通过返回一个值来接受结果。尽管标准中没有给出定义,但time_t 通常使用整数值来实现。

2.5、输出时间和日期

使用ctime 函数,可以将时间打印为固定格式字符串,格式为:Www Mmm dd hhss yyyy。代码示例如下:

//以字符串形式输出当前时间和日期time_tnow=time(nullptr);cout'Nowis:'ctime(now);//Nowis:TueAug918382022

2.6、综合示例代码

asctime()和difftime()函数的示例代码如下(直接复制运行):

#include#include#include#includeusingnamespacestd;//冒泡排序:数据从小到大排序voidbubbleSort(vectorarr){size_tnumber=arr.size();if(number=1)return;inttemp;for(inti=0;inumber;i++){for(intj=0;jarr[j+1]){temp=arr[j];arr [ j]=arr[j+1];arr[j+1]=temp;}}}}//difftime()函数:计算时间差,单位为svoiddifftime_test(){vectorinput_array;for(inti=90000; i0; i--){input_array.emplace_back(i);}time_ttime1=时间(nullptr);bubbleSort(input_array);time_ttime2=时间(nullptr);doubletime_diff=difftime(time2,time1);cout'inputarraysizeis'input_array.size () 'afterbubbleSorttime_diff:'time_diff's'endl;}//astime()函数:将本地时间tm结构体对象转换为字符串文本voidastime_test(){time_traw_time=time(nullptr);//获取当前日历时间structtm*local_timeinfo=localtime(raw_time);printf('Thecurrentdate/timeis:%s',asctime(local_timeinfo));}intmain(){difftime_test();astime_test();//3、输出当前纪元时间time_tepoch_time=time(nullptr ); cout'Epochtime:'epoch_timeendl;//4、以字符串形式输出当前时间和日期time_tnow=time(nullptr);cout'Nowis:'ctime(now);}

编译g++ time_demo.cpp -std=c++11后,运行程序./a.out后,输出结果为:

3.计时库

“Chrono”是英文chronology的缩写,意思是“年代学;年表”。

chrono 既是头文件的名称,也是子命名空间的名称。 chrono 头文件下的所有元素都在std:chrono 命名空间下定义。

std:chrono 是C++11 中引入的日期和时间处理库。计时库包括三种主要类型:时钟、时间点和持续时间。

3.1、时钟

C++11chrono 库包含三个时钟类:

名称说明chrono:system_clock 系统时钟(可调整) chrono:steady_clock 单调递增时钟(不可调整) chrono:high_resolution_clock 具有可用的最短滴答周期。 system_clock是当前系统的时钟。由于系统时钟可能随时调整,因此如果要计算两个时间点之间的时间差,不建议使用系统时钟。

stable_clock会保证时间单调增加,只会向前移动,不会减少,因此最适合测量时间间隔。

high_resolution_clock 表示具有由实现提供的最小计数周期的时钟。它可以是system_clock 或stable_clock 的别名,也可以是第三个独立时钟。在不同的标准库中,high_resolution_clock的实现不一致,所以官方不推荐使用该时钟。

这三个时钟类都有一些共同的成员函数和数据类型,如下所示:

名称说明now() 静态成员函数,返回当前时间,类型为clock:time_pointtime_point成员类型,当前时钟的时间点类型,用于表示具体的时间,具体参见“时间点”持续时间下面的member type,是clock Type的长度,用来表示一个时间间隔(一段时间)。有关详细信息,请参阅下面的“持续时间”代表成员类型。时钟的tick类型相当于clock:repperiod成员类型。时钟的单位相当于clock:periodis_steady静态成员类型:是否是稳定时钟,对于steady_clock这个值必须为true。每个时钟类都有一个now()静态函数来获取当前时间,返回类型用time_*point描述。 std:time_point是一个模板类,模板类示例为:std:steady\_*clock。这个写起来比较长。幸运的是,在C++11中,可以通过auto关键字自动推导变量类型。

std:time_pointnow1=std:now();autonow2=std:now();

3.2、C风格转换

system_*clock 与其他两个时钟的区别在于,它还提供了两个静态函数用于来回转换time_*point 和std:time_t。

名称说明to_time_t 将系统时钟时间点转换为time_tfrom_time_t 将time_t 转换为系统时钟时间点第一个参考链接中的文章给出了下图来描述c 风格和c++11 中几种时间类型的转换:

3.3、时长比

为了支持更高精度的系统时钟,C++11为自定义时间单位添加了新的头文件和类型。 std:ratio是一个模板类,提供编译时比率计算功能,并为std:duration提供基础服务。其声明如下:

模板类比;

第一个模板参数Num(分子) 代表分子,第二个参数Denom(分母) 代表分母。 typedef 比率毫;意思是千分之一。因为基本计算单位约定为秒,所以毫表示千分之一秒。因此,毫秒、微秒、纳秒等都可以通过比率来表示。

typedefrationano;//纳秒单位typedefratiomicro;//微秒单位typedefratiomilli;//毫秒单位typedefratios//秒单位

ratio可以表达的值不仅以10为基础,还可以表达任何小数秒,如:5/7秒、89/23409秒等。对于特定的比率,可以通过den值得到分母, num 获取分子的值。不仅如此,头文件中还包含:ratio_add、ratio_subtract、ratio_multiply、ratio_divide来完成分数的加减乘除四种算术运算。例如,如果要计算5/7+59/1023,可以使用以下代码:

ratio_addresult;doublevalue=((double)result.num)/result.den;coutresult.num'/'result.den'='valueendl;//代码输出结果为5528/7161=0.771959

在C++中,如果分子和分母都是整数,整数除法的结果仍然是整数,即小数点右边的部分会被丢弃。因此,如果想要获得double类型的结果,需要先将其转换为double。

3.3.1、持续运行

持续时间对象可以相互相加或相减。 chrono 为常用的持续时间操作提供了以下函数:

函数说明uration_cast 转换持续时间下限(C++17) 通过向下舍入将一个持续时间转换为另一持续时间ceil (C++17) 通过向上舍入将一个持续时间转换为另一持续时间一轮持续时间(C++17) 将持续时间到另一个持续时间,四舍五入到最接近的整数,偶数abs(C++17)获取持续时间的绝对值3.4,时间间隔持续时间

类模板std:duration 表示时间间隔,声明如下:

templateclassRep,classPeriod=std:ratioclassduration;

类成员类型说明:

成员类型定义注释rep第一个模板参数(Rep)表示类型,用作内部计数对象的类型。period第二个模板参数(Period)表示周期以秒为单位的Theratiotype。duration由Rep类型的计数次数和Period类型的计数周期组成,其中count number period 是一个编译时有理常量,表示从一个计数到下一个计数的秒数。 uration中存储的数据只是Rep类型的计数。如果Rep是浮点数,则duration可以表示小数计数的个数。周期作为持续时间类型的一部分包含在内,并且仅在不同持续时间之间进行转换时使用。

Rep表示用于表示Period数量的数值类型,例如int float double(刻度数)。

period 是std:ratio 类型,用于表示[以秒表示的时间单位],例如秒毫秒(一个滴答周期)。

成员函数count()返回Rep类型的Period的数量。

常用的持续时间已被定义。在std:chrono头文件中,常用的持续时间单位的代码如下:

///纳秒typedefduration纳秒;///微秒typedefduration微秒;///毫秒typedefduration毫秒;///秒typedefduration秒;///分钟typedefduration分钟;///小时typedefduration小时;

类型定义std:nanosecondsdurationstd:microsecondsdurationstd:millisecondsdurationstd:secondsdurationstd:minutesduration*至少29 位的有符号整数类型*/,std:ratio60»std:hoursduration*至少23 位的有符号整数类型*/,std:ratio3600»duration类的count()成员函数返回时间间隔的具体值。

3.4.1、时间间隔转换函数duration_cast

由于存在代表不同时间单位的各种持续时间,因此chrono 库提供了uration_cast 函数来更改持续时间类型。其声明如下:

templateconstexprToDurationduration_cast(constdurationd);

它的定义比较复杂,但是在我们的日常使用中,我们可以直接使用自动求导函数来返回对象类型。示例代码如下:

#include#include#include#includevoidf(){std:sleep_for(std:seconds(1));}intmain(){autot1=std:now();f();autot2=std:now( );//整数时长:需要uration_castautoint_ms=std:duration_cast(t2-t1);//小数时长:不需要uration_caststd:durationfp_ms=t2-t1;std:cout'f()took'fp_ms.count( )'ms,''or'int_ms.count()'wholemilliseconds';//程序输出结果:f()took1000.23ms,or1000wholemilliseconds}

3.5、时间点time_point

std:time_point 表示一个时间点(特定的时间),比如80 年代、你的生日、今天下午、火车出发时间等,只要能用计算机时钟表示即可。它包含两个信息:时钟和持续时间。它被实现为Duration 类型的值,存储自时钟纪元开始以来的时间间隔。其声明如下:

模板类时间点;

时钟的now() 函数返回的值是一个时间点。 time_point 中的time_since_epoch() 返回自时钟原点以来的持续时间。可以通过减去两个时间点来计算时间间隔。这是一个代码示例:

#include#include#include#includeusingnamespacestd;voidtime_point_test(){autostart=chrono:now();doublesum=0;for(inti=0;i100000000;i++){sum+=sqrt(i);} autoend=chrono:now();//通过两个时间点相减来计算时间间隔autotime_diff=end-start;//将时间间隔单位转换为毫秒autoduration=chrono:duration_cast(time_diff);cout'SqrtOperationcost :' period.count()'ms'endl;}intmain(){time_point_test();//程序输出结果:SqrtOperationcost:838ms}

3.5.1、时间点操作

对时间点有加减运算,计算结果符合常识:时间点+时长=时间点;时间点-时间点=持续时间。

审稿人:唐子宏

以上知识分享希望能够帮助到大家!