C++11:便利的工具

1 处理日期和时间的chrono库

1.1 记录时长的duration

duration表示一段时间间隔,用来记录时间长度,可以表示几秒、几分钟或者几个小时的时间间隔。duration的原型如下:

template<
	class Rep,
	class Period = std::ratio<1,1>
> class duration;

第一个模板参数Rep是一个数值类型,表示时钟数的类型;第二个模板参数是一个默认模板参数std::ratio,表示时钟周期,它的原型如下:

template<
	std::intmax_t Num,
	std::intmax_t Denom = 1
>class ratio;

它表示每个时钟周期的秒数,其中第一个模板参数Num代表分子,Denom代表分母,分母默认为1,因此,ratio代表的是一个分子除以分母的分数值,比如ratio<2>代表一个时钟周期是两秒, ratio<60>代表一分钟, ratio<60 * 60>代表一个小时, ratio<60 * 60 * 24>代表一天。而ratio<1,1000>代表的则是1/1000秒,即一毫秒,ratio<1, 1 000 000>代表一微秒,ratio<1,1 000 000 000>代表一纳秒。为了方便使用,标准库定义了一些常用的时间间隔,如时、分、秒、毫秒、微秒和纳秒,在 chrono命名空间下,它们的定义如下:

typedef duration <Rep, ratio<3600,1>> hours;
typedef duration <Rep, ratio<60,1>> minutes;
typedef duration <Rep, ratio<1,1>> seconds;
typedef duration <Rep, ratio<1,1000>> milliseconds;
typedef duration <Rep,ratio<1,1000000>> microseconds;
typedef duration <Rep,ratio<1,1000000000>> nanoseconds;

通过定义这些常用的时间间隔类型,我们能方便地使用它们,比如线程的休眠:

std::this_thread::sleep_for(std::chrono::seconds(3));	//休眠3秒
std::this_thread::sleep_for(std::chrono::milliseconds(100));	//休眠100毫秒

chrono还提供了获取时间间隔的时钟周期数的方法count(),它的基本用法如下:

#include <chrono>
#include <iostream>
int main ()
{
    
    
	std::chrono::milliseconds ms{
    
    3};	//3毫秒
	std::chrono::microseconds us = 2*ms;	//6000微秒
	std::chrono::duration<double, std::ratio<1, 30>> hz30 {
    
    3.5}; //30Hz clock using fractional ticks
	std: :cout <<"3 ms duration has " << ms.count () << " ticks \n"
	<<"6000 us duration has " << us.count ( ) << " ticks\n";
}

输出如下:
3 ms duration has 3 ticks
6000 us duration has 6000 ticks
时间间隔之间可以做运算,计算两端时间间隔的差值的示例如下:

std::chrono::minutes t1(10);
std::chrono::seconds t2(60) ;
std::chrono::seconds t3 = t1 - t2;
std::cout<< t3.count () <<" second" << std: :endl;

其中,t1代表10分钟、t2代表60秒,t3则是t1减去t2,也就是600-60=540秒。通过调用t3的count输出差值为540个时钟周期,因为t3的时钟周期为1秒,所以t3表示的时间间隔为540秒。

1.2 表示时间点的time point

time_point 表示一个时间点,用来获取从它的clock 的纪元开始所经过的duration(比如,可能是1970.1.1以来的时间间隔)和当前的时间,可以做一些时间的比较和算术运算,可以和ctime库结合起来显示时间。time_point必须用clock 来计时。time_point有一个函数time_from_eproch()用来获得1970年1月1日到 time_point时间经过的duration。下面是计算当前时间距离1970年1月1日有多少天的示例。

#include <iostream>
#include <ratio>
#include <chrono>

int main()
{
    
    
	using namespace std:: chrono;
	typedef duration<int, std:: ratio<60*60*24>> days_type;
	time_point<system_clock, days_type> today =
	time_point_cast<days_type>(system_clock::now());
	std::cout << today.time_since_epoch().count() << " days since epoch" <<std:: endl;
	return 0;
}

time_point还支持一些算术运算,比如两个time_point的差值时钟周期数,还可以和duration相加减。要注意不同clock 的time_point是不能进行算术运算的。下面的例子输出前一天和后一天的日期。

#include <iostream>
#include <iomanip>
#include <ctime>
#include <chrono>

int main()
{
    
    
	using namespace std::chrono;
	system_clock::time_point now = system_clock::now();
	std::time_t last = system_clock::to_time_t(now - hours(24));
	std::time_t next = system_clock::to_time_t(now + hours(24));
	std::cout << "One day ago, the time was "
	<< std::put time(std::localtime(&last),"%F %T") << '\n ';
	std::cout << "Next day, the time is "
	<< std::put_time(std::localtime(&next)"%F %T") << '\n ';
}

输出如下:
one day ago, the time was 2014-3-2622:38: 27
Next day, the time is 2014-3-2822:38:27
需要注意的是,上面的代码在vs2013下能编译通过,但在GCC下是不能编译通过的,因为GCC 还没有支持std::put_time。

1.3 获取系统时钟的clocks

clocks表示当前的系统时钟,内部有time_point、duration、Rep、Period等信息,主要用来获取当前时间,以及实现time_t和 time _point的相互转换。clocks包含如下3种时钟:
system_clock: 代表真实世界的挂钟时间,具体时间值依赖于系统。system_clock 保证提供的时间值是一个可读时间。
steady_clock: 不能被“调整”的时钟,并不一定代表真实世界的挂钟时间。保证先后调用now()得到的时间值是不会递减的。
high_resolution_clock: 高精度时钟,实际上是system_clock或者steady_clock 的别名。可以通过now()来获取当前时间点,代码如下:

#include <iostream>
#include <chrono>
int main ()
{
    
    
	std::chrono::system_clock::time_point t1 = std::chrono::system_clock::now();
	std::cout<<"Hello world\n" ;
	std::chrono::system_clock::time_point t2 = std::chrono::system_clock::now();
	std::cout<< (t2-t1).count()<<"tick count"<<std::endl;
}

输出如下:
Hello world
97tick count
system_clock和std::put_time配合起来使用可以格式化日期的输出。下面的例子是将当前时间格式化输出。

#include <chrono>
#include <ctime>
#include <iostream>
#include <iomanip>
#include <string>
using namespace std;
int main ()
{
    
    
	auto t = chrono::system_clock::to_time_t(std::chrono::system_clock::now());
	cout<< std::put_time(std::localtime(&t),"%Y-%m-%d %x")<<endl;
	cout<< std::put_time(std:: localtime(&t),"%Y-%m-%d %H.%M.%S")<<endl;
	return 0;
}

输出结果如下:
2014-3-27 22:11: 49
2014-3-27 22.11.49

2 数值类型和字符串的相互转换

C++11提供了to_string方法,可以方便地将各种数值类型转换为字符串类型:
std::string to_string( int value ) ;
std::string to_string( long value ) ;
std::string to_string( long long value ) ;
std::string to_string( unsigned value );
std::string to_string( unsigned long value );
std::string to_string( unsigned long long value );
std::string to_string( float value );
std::string to_string( double value );
std::string to_string( long double value );

std::wstring to_wstring( int value );
std::wstring to_wstring( long value );
std::wstring to_wstring( long long value );
std::wstring to_wstring( unsigned value );
std::wstring to_wstring( unsigned long value ) ;
std::wstring to_wstring( unsigned long long value );
std::wstring to_wstring( float value ) ;
std::wstring to_wstring( double value );
std::wstring to_wstring( long double value );

C++11还提供了字符串转换为整型和浮点型的方法:
atoi:将字符串转换为int类型。
atol:将字符串转换为long类型。
atoll:将字符串转换为long long类型。
atof:将字符串转换为浮点型。

#include <iostream>
#include <string>

int main(void)
{
    
    
	double f = 1.53;
	std::string f_str = std::to_string(f);
	std::cout << f_str << std::endl;

	double f1 = 4.125;
	std::wstring f_str1 = std::to_wstring(f1);
	std::wcout << f_str1 << std::endl;

	const char* str1 = "10";
	const char* str2 = "3.1415926";
	const char* str3 = "31337 with words";
	const char* str4 = "words and 2";

	int num1 = std::atoi(str1);
	int num2 = std::atoi(str2);
	int num3 = std::atoi(str3);
	int num4 = std::atoi(str4);
	double f2 = std::atof(str2);

	std::cout << "std::atoi(\"" << str1 << "\") is " << num1 << '\n'; 
	std::cout << "std::atoi(\"" << str2 << "\") is " << num2 << '\n'; 
	std::cout << "std::atoi(\"" << str3 << "\") is " << num3 << '\n'; 
	std::cout << "std::atoi(\"" << str4 << "\") is " << num4 << '\n'; 
	std::cout << "std::atoi(\"" << str2 << "\") is " << f2 << std::endl; 

	system("pause");
	return 0;
}

输出结果如下:
std::atoi(“10”) is 10
std::atoi(“3.14159”) is 3
std::atof (“31337 with words”) is 31337
std::atoi ( “words and 2”) is 0
如果需要转换的字符串前面部分不是数字,会返回0,上面的str4转换后返回0; 如果字符串的前面部分有空格和含数字,转换时会忽略空格并获得前面部分的数字。

3 宽窄字符转换

C++11增加了unicode字面量的支持,可以通过L来定义宽字符:

std::wstring str = L”中国人";	//定义unicode字符串

将宽字符串转换为窄字符串需要用到codecvt库中的std::wstring_convert。std::wstring_convert需要借助unicode转换器:

#include <iostream>
#include <string>
#include <codecvt>

int main(void)
{
    
    
	std::wstring str = L"我是中国人yzb";
	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);
	std::wstring wstr = converter.from_bytes(narrowStr);
	std::cout << narrowStr << std::endl;

	std::wcout.imbue(std::locale("chs"));  //初始化cout为中文输出
	std::wcout << wstr << std::endl;

	system("pause");
	return 0;
}

输出结果如下:
中国人
中国人

猜你喜欢

转载自blog.csdn.net/taifyang/article/details/129103541