C++11 中提供了一些非常方便的工具库,这些工具库有时间相关的类,也有字符转换类,在实际编码中,这些类可以帮助大家快速处理时间、日期以及字符串相关的操作。
1 处理日期和时间的chrono库
chrono库中包含了三个时间类型,分别是表示时间间隔的duration、时钟clocks和时间点time point。
1.1 时间间隔duration
duration的原型如下:
template <class Rep, class Period = ratio<1> >
class duration;
复制
上面的定义中,Rep表示数据类型,ration表示周期,是一个比例值,ration的定义如下:
template <intmax_t N, intmax_t D = 1> class ratio;
复制
使用时表示的事N/D,D默认等于1。如果用ration表示一秒就可以按照如下来写:
std::ratio<1,1>
复制
同理,如果是一个小时,一分钟就可以按照如下来写:
std::ratio<3600,1>;//一小时
std::ratio(60,1);//一分钟
复制
使用duration,可以很方便的定义一些时间间隔,如下面的代码:
int main ()
{
//5毫秒
std::chrono::milliseconds ms(5);
//15000微妙
std::chrono::microseconds us=3*ms;
//获取CPU时钟间隔
std::chrono::duration<double,std::ratio<1,30>> cpu_30(3.5);
std::cout<<"5毫秒周期间隔"<<ms.count()<<std::endl;
std::cout<<"15000微妙CPU周期间隔"<<us.count()<<std::endl;
return 0;
}
复制
代码输出结果为:
5毫秒CPU时钟周期5
15000微妙CPU时钟周期15000
复制
时间间隔函数还可以参与计算,如下面代码所示:
int main ()
{
std::chrono::milliseconds foo (1000); // 1 second
foo*=60;
std::cout << "duration (in periods): ";
std::cout << foo.count() << " milliseconds.\n";
std::cout << "duration (in seconds): ";
std::cout << foo.count() * std::chrono::milliseconds::period::num / std::chrono::milliseconds::period::den;
std::cout << " seconds.\n";
return 0;
}
复制
代码输出结果为:
duration (in periods): 60000 milliseconds.
duration (in seconds): 60 seconds.
复制
需要特别说明的是,在duration的计算过程中,如果两个duration的时钟周期不同,计算时会先转换成一致的时钟周期然后在进行运算,转换规则如下:
如果存在两个duration,第一个duration表示为:ratio(x1,y1),第二个表示为:ratio(x2,y2),如果x1,x2的最大公约数为A,y1,y2的最小公倍数为B,则转换成统一的时钟周期后可以标识为:ration(A,B).
示例如下:
int main ()
{
std::chrono::duration<double,std::ratio<4,7>> d1(3);
std::chrono::duration<double,std::ratio<2,9>> d2(1);
auto d3 = d1-d2;
std::cout << typeid(d3).name()<<std::endl;
std::cout << d3.count() << std::endl;;
return 0;
}
复制
d3.count()的输出结果为:47.
1.2 时间节点 time point
time_point表示的是一个时间节点,可以标识从纪元或者1970.1.1以来经历的时间,可以和ctime结合使用。在实际编码时,time_point使用clock计时。在time_point中可以使用time_from_eproch()来获取1970年以后经历的秒数。如下面的代码:
int main ()
{
typedef std::chrono::duration<double,std::ratio<60*60*24>> day;
std::chrono::time_point<std::chrono::system_clock,day> today =
std::chrono::time_point_cast<day>(std::chrono::system_clock::now());
std::cout << today.time_since_epoch().count()<<" day's since epoch"<<std::endl;
return 0;
}
复制
代码运行结果如下:18906.1 day's since epoch
除此之外,time_point还支持算术运算,比如计算前一天或者后一天日期和时间。代码如下:
int main ()
{
std::chrono::system_clock::time_point now = std::chrono::system_clock::now();
std::time_t lastDay = std::chrono::system_clock::to_time_t(now - std::chrono::hours(24));
std::time_t nextDay = std::chrono::system_clock::to_time_t(now + std::chrono::hours(24));
std::cout <<"前一天日期时间是:"<< std::put_time(std::localtime(&lastDay),"%F %T")<<std::endl;
std::cout <<"后一天日期时间是:"<< std::put_time(std::localtime(&nextDay),"%F %T")<<std::endl;
return 0;
}
复制
PS:有些版本的编译器可能不支持put_time.需要进行更新。
1.3 获取系统时钟 clocks
clocks有三种时钟,分别是:
system_clock: xianshi现实的时钟,依赖操作系统时间
steady_clock: 不能被调整的
high_resolution_clock:高精度时钟,使用now或者时间点
获取的时钟中期可以参数算术运算,实例如下:
int main ()
{
std::chrono::system_clock::time_point begin = std::chrono::system_clock::now();
std::cout<<"hello world"<<std::endl;
std::chrono::system_clock::time_point end = std::chrono::system_clock::now();
std::cout <<"tick count:"<<(end - begin).count()<<std::endl;
return 0;
}
复制
string to_string (int val);
string to_string (long val);
string to_string (long long val);
string to_string (unsigned val);
string to_string (unsigned long val);
string to_string (unsigned long long val);
string to_string (float val);
string to_string (double val);
string to_string (long double val);
复制
int main ()
{
std::string pi = "pi is " + std::to_string(3.1415926);
std::string perfect = std::to_string(1+2+4+7+14) + " is a perfect number";
std::cout << pi << '\n';
std::cout << perfect << '\n';
return 0;
}
复制
pi is 3.141593
28 is a perfect number
复制
atoi:数值型字符串转换为整型
atol:数值型字符串转换为long型
atoll:数值型字符串转换为long long型
atof:数值型字符串转换为浮点型
演示代码如下:
int main ()
{
char buffer[256];
printf ("Enter a long number: ");
fgets (buffer, 256, stdin);
long lNum = atol(buffer);
int iNum = atoi(buffer);
long long llNum = atoll(buffer);
double fNum = atof(buffer);
return 0;
}
复制
3 宽窄字符转换
C++11中增加了unicode字符的支持,使用时通过“L”定义宽字符,如:
std::wstring str = L"中国共产党万岁";
复制
将宽字符转换为窄字符时需要使用codecvt库,该库提供了如下字符编码转转接口:
std::codecvt_utf8:封装了utf-8到ucs2和ucs4的转换
std::codecvt_utf16:封装了utf-16到ucs2和ucs4的转换
std::codecvt_utf8_utf16:封装了utf-8到utf-16的转换
代码示例如下:
std::wstring str = L"中国共产党万岁";
std::wstring_convert<std::codecvt<wchar_t, char, std::mbstate_t>> converter(new std::codecvt<wchar_t, char, std::mbstate_t>("CHS"));
std::string narrowStr = converter.to_bytes(str);
//字符串转换为wstring
std::wstring wstr = converter.from_bytes(narrowStr);
std::cout << narrowStr << std::endl;
std::wcout.imbue(std::locale("chs"));
复制
运行结果如下:
PS:代码在VS2019编译通过,如果编译不过的话需要升级编译器版本。
- EOF -
扫码关注
图文:龙小
排版:龙小