c++11 boost - 字符串(1) - 转换、格式化

2018-07-11 15:27:17

lexical_cast 类似于c中 atoi 函数,可以进程字符串与数字/浮点数之间的字面转换,出错会抛出 bad_lexical_cast 异常。

不过注意,待转换为数字的字符串中,只能允许数字,小数点,Ee。

boost::conversion 名称空间的 try_lexical_convert 可以避免抛出异常,返回 bool 。

// Copyright (c) 2015
// Author: Chrono Law
#include <iostream>
using namespace std;

#include <boost/lexical_cast.hpp>
using namespace boost;


void case1()
{
    int  x      = lexical_cast<int>("100");
    long y      = lexical_cast<long>("2000");
    float pai   = lexical_cast<float>("3.14159e5");
    double e    = lexical_cast<double>("2.71828");
    double r    = lexical_cast<double>("1.414,xyz", 5);  //指定转换前5位

    cout << x << y << pai << e << r << endl;

    string str = lexical_cast<string>(456);
    cout << str << endl;

    cout << lexical_cast<string>(0.618) << endl;
    cout << lexical_cast<string>(0x10) << endl;

    cout << lexical_cast<bool>("1") << endl;
	
	//字符串只能出现数字小数点和eE
    //lexical_cast<int>("0x100");
    //lexical_cast<int>("123L");
}

template<typename T>
bool num_valid(const char *str)
{
    T tmp;
    return conversion::try_lexical_convert(str, tmp);
}
//try
//{
//    lexical_cast<T>(str);
//    return true;
//}
//catch(bad_lexical_cast&)
//{
//    return false;
//};

void case2()
try
{
    assert( num_valid<double>("3.14"));
    assert(!num_valid<int>("3.14"));
    assert( num_valid<int>("65535"));

    int x;
    assert(!conversion::try_lexical_convert("0x100", x));

    cout << lexical_cast<int>("0x100");
    cout << lexical_cast<double>("HelloWorld");
    cout << lexical_cast<long>("1000L");
    cout << lexical_cast<bool>("false") << endl;
}
catch (bad_lexical_cast& e)
{
        cout << "error:" << e.what() << endl;
}

//自定义类
template<typename T>
struct outable
{
    friend std::ostream& operator<<(std::ostream& os, const T& x)
    {
        os << typeid(T).name();
        return os;
    }
};

class demo_class : public outable<demo_class>
{
//    friend std::ostream& operator<<(std::ostream& os, const demo_class& x)
//    {
//        os << "demo_class's Name";
//        return os;
//    }
};
void case3()
{
    cout << "demo_class:" << lexical_cast<string>(demo_class()) << endl;
}


//标准库
void case4()
try
{
    assert(stoi(" 42 ") == 42);
    assert(stol("100L") == 100L);
    assert(stol("1000 9") == 1000L);
    assert(stod("3.14ispai") == 3.14);

    assert(to_string(776ul) == "776");

    //cout << stoul("100L");
    //cout << stoul("x100");
    cout << stoi("9999999999");
}
catch(std::exception& e)
{
    cout << "error:" << e.what() << endl;
}

//模拟 lexical_cast
template<typename T>
T std_lexical_cast(const std::string& s);

template<>
int std_lexical_cast<int>(const std::string& s)
{
    return stoi(s);
}

template<>
long std_lexical_cast<long>(const std::string& s)
{
    return stol(s);
}

void case5()
{
    assert(std_lexical_cast<int>(" 10 ") == 10);
    assert(std_lexical_cast<long>("100L") == 100L);
}

int main()
{
    case1();
    case2();
    case3();
    case4();
    case5();
}
[root@192 c++]# g++ -std=c++11 main.cpp 
[root@192 c++]# ./a.out 
10020003141592.718281.414
456
0.61799999999999999
16
1
error:bad lexical cast: source type value could not be interpreted as target
demo_class:10demo_class
error:stoi


format 库可以代替 printf,实现字符串的格式化。

性能方面,由于printf不进行类型检查,直接输出,因此速度非常快,而 format 会做各种检查,性能会略慢。如果在乎性能又要使用 format ,可以先建立 const format 对象,然后拷贝会提升性能。

const format fmt("%10d %020.8f\n");  //常量对象
cout << format(fmt) %62 %2.236;    //拷贝使用
// Copyright (c) 2015
// Author: Chrono Law
#include <iostream>
using namespace std;

#include <boost/format.hpp>
using namespace boost;

void case1()
{
    cout << format("%s:%d+%d=%d\n") %"sum" % 1 % 2 % (1+2);

    format fmt("(%1% + %2%) * %2% = %3%\n");
    fmt % 2 % 5 ;
    fmt % ((2+5)*5);
    
    //返回内部格式化好的字符串对象
    cout << fmt.str();
}


void case2()
{
    format fmt("%05d\n%-8.3f\n% 10s\n%05X\n");
    cout << fmt %62 % 2.236 % "123456789" % 48;

    format fmt2("%|05d|\n%|-8.3f|\n%| 10s|\n%|05X|\n");
    cout << fmt2 %62 % 2.236 % "123456789" % 48;

    const format fmt3("%10d %020.8f %010X %10.5e\n");
    cout << format(fmt3) %62 % 2.236 % 255 % 0.618;
}

//高级功能
#include <iomanip>
using namespace boost;
using boost::io::group;

void case3()
{
	cout << endl;
    format fmt("%1% %2% %3% %2% %1% \n");
    cout << fmt %1 % 2 % 3;

	//第二个绑定为10
    fmt.bind_arg(2, 10);
    cout << fmt %1 %3;

    fmt.clear();  //重置缓冲区,可以再次使用 %
	
	//第一个111显示为8进制,第二个为10,第3个为333
    cout << fmt % group(showbase,oct,  111) % 333;

    fmt.clear_binds();  //清除所有绑定


    fmt.modify_item(1, group(hex, right, showbase,setw(8), setfill('*')));
    cout << fmt % 49 % 20 % 100;
    cout << endl;
}


int main()
{
    case1();
    case2();
    case3();
}
[root@192 c++]# g++ -std=c++11 main.cpp 
[root@192 c++]# 
[root@192 c++]# 
[root@192 c++]# ./a.out 
sum:1+2=3
(2 + 5) * 5 = 35
00062
2.236   
 123456789
00030
00062
2.236   
 123456789
00030
        62 00000000002.23600000 00000000FF 6.18000e-01

1 2 3 2 1 
1 10 3 10 1 
0157 10 333 10 0157 
****0x31 20 100 20 49


 备注

1.编译器版本gcc4.8.5,运行环境centos7 64位
2.本文只做简单记录用,详细用法请参考 Boost Library,或者是罗剑锋的 boost程序库完全开发指南 书本
3..原文地址http://www.freecls.com/a/2712/a1


©著作权归作者所有
收藏
推荐阅读
简介
天降大任于斯人也,必先苦其心志。