暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

【C++11】 C++11中的便捷工具类

CPP开发前沿 2021-10-07
1307

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;
}
复制
2 数值和字符串的相互转换
C++11中提供了to_string方法,可以方便的将数值类型转换为字符串类型。相关的方法定义如下:
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
复制
除此之外,C++11还提供了将字符串转换为数值类型的方法,主要有:
  • 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 -


扫码关注


图文:龙小

排版:龙小

文章转载自CPP开发前沿,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论