Boost 第十章 操作系统相关

本文章所有内容源于《BOOST程序库完全开发指南:深入C++“准”标准库(第3版)》第十章


为了使代码可以在不同平台之间相互移植,介绍system库,它封装了操作系统底层的错误代码,为上层提供了一个可移植的统一的处理接口;随后是chrono和cpu_timer库,它延续到第二章的讨论,基于操作系统的API提供高精度的时间功能;第四个是filesystem库,提供跨平台的文件系统处理能力,能够以一直的方式处理不同操作系统中的文件和目录;最后是program_options库,为程序员提供强大的命令行参数解析和程序运行选项配置能力。

1. system

1.1 功能:

封装了操作系统底层的错误代码和错误信息,使调用操作系统功能的程序可以被很容易的移植。它作为基础部件被chrono、filesystem、asio等库调用。

1.2 头文件:

#define BOOST_ERROR_CODE_HEADER_ONLY
#include <boost/system/error_code.hpp>
using namespace boost::system;

1.3 用法:

核心类:

  • error_category
  • error_code
  • error_condition
#include <boost/system/error_code.hpp>
#include <boost/system/system_error.hpp>
using namespace boost::system;
#include <iostream>
using std::string;
using std::cout;
using std::endl;
class my_category : public error_category           //公有继承错误类别
{
public:
    virtual const char *name() const BOOST_SYSTEM_NOEXCEPT
    { return "MYAPP_CATEGORY"; }

    virtual string message( int ev ) const
    {
        string msg;
        switch(ev)                                                                       //使用switch产生错误消息
        {
            case 0:
                msg="ok";break;
            default:
                msg="some error";break;
        }
        return msg;
    }
};
//可以把error_code(偏重操作系统和底层API)转换成error_condition(偏重移植)
/*----------------------错误类型--------------------------*/
void case1()
{
    my_category my_cat;                                                             //自定义错误类别的实例
    error_code ec(10,my_cat);                                                    //错误码10,自定义类别
    cout << ec.value() << "  " << ec.message() << endl;
    ec = error_code( 10, system_category() );                       //系统错误类别
    cout << ec.value() << "  " << ec.message() << endl;
}

/*----------------------错误代码--------------------------*/
void case2()
{
    std::cout << system_category().name() << std::endl;

    error_code ec;
    assert(ec.value() == errc::success);
    assert(!ec);
    assert(ec.category() == system_category());

    ec.assign(3L, system_category());
    auto econd = ec.default_error_condition();
    assert(econd == ec);


    assert(econd == system_category().default_error_condition(3L));

    std::cout << ec.message() << std::endl;
    std::cout << econd.message() << std::endl;
    std::cout << econd.value() << std::endl;

}

/*----------------------错误异常--------------------------*/
void case3()
{
    try
    {
        throw system_error(error_code(5, system_category()));
    }
    catch (system_error& e)
    {
        std::cout << e.what();
    }
}
int main()
{
    case1();
    case2();
    case3();
}

2. chrono

2.1 功能:

chrono库里很多时间概念和date_time类似,但是它更侧重于表达“计算机时间”里的时间,所以是一个很重要的基础不见,被cpu_timer和thread等库所使用

2.2 头文件:

#define BOOST_ERROR_CODE_HEADER_ONLY //无需编译使用system库
#define BOOST_CHRONO_HEADER_ONLY //无需编译即可使用chrono库
#define BOOST_CHRONO_EXTENSIONS //使用扩展功能
#include <boost/chrono.hpp> //chrono库头文件
using namespace boost::chrono;

2.3 用法:

#include "/home/桌面/算法书/C++Boost/boost_guide/common/std.hpp"
//using namespace std;
using std::cout;
using std::endl;

//#define BOOST_ERROR_CODE_HEADER_ONLY
#define BOOST_CHRONO_HEADER_ONLY
#define BOOST_CHRONO_EXTENSIONS
#include <boost/chrono.hpp>
using namespace boost;
using namespace boost::chrono;

//
typedef duration<long,   ratio<30>> half_min;               //半分钟
typedef duration<int,    ratio<60*15>> quater;                  //一刻钟
typedef duration<double, ratio<3600*24>> day;                   //一天

//typedef duration<int,60*60> my_hour;                          //不能直接用整数
//typedef duration<int,ratio<-10, 1000>> my_ms;         //不能用负数
void case1()
{
    seconds s(10);                                              //十秒相当于  10*ratio<1>
    minutes m(5);                                               //五分钟相当于 5*ratio<60>
    hours   h(1);                                                       //1*ratio<3600>
    milliseconds ms(100);                               //100*ratio<1,1000>

    assert(s.count() == 10);                                    //成员函数count用于计数
    assert(ms.count() == 100);

    s *= 3;                                                                         //可以乘除数字标量
    s += seconds(30);                                                   //加建运算必须都是时间长度
    s = s - seconds(20);
    assert(s < seconds(50));                                        //比较也必须是时间长度
    cout << s << endl;                                              //输出40秒

}
//
void case2()
{
    seconds s(10);
    minutes m(5);

    s += m;                                                                                         //输出310秒,混合使用
    cout << s << endl;

    //m+= s;                                                                                  //失败,整数类型不能表示小数概念

    {
        seconds s(10);
        typedef duration<double, ratio<60>> my_min;
        my_min m(5);
        m += s;
        cout << m << endl;
    }

    {
        seconds s(40);
        auto m = duration_cast<minutes>(s);
        cout << m << endl;

        seconds s2(301);
        cout << duration_cast<minutes>(s2) << endl;
    }

    {
        seconds s(3600 + 50);                               //1小时+50秒
        cout << floor<minutes>(s) << endl;      //60分  //floor向下舍入
        cout << ceil<minutes>(s) << endl;       //61分  四舍五入
        cout << round<minutes>(s) << endl;  //61分四舍五入到最近,小的向上舍入
        cout << round<hours>(s) << endl;        //1小时
    }
}

//
//时钟
template<typename T>
using clock_desc = clock_string<T, char>;

void case3()
{
    cout << clock_desc<system_clock>::name() << endl;       //系统启动开始计时
    cout << clock_desc<system_clock>::since() << endl;

    cout << clock_desc<steady_clock>::name() << endl;           //进程启动开始计时
    cout << clock_desc<steady_clock>::since() << endl;

    cout << clock_desc<process_real_cpu_clock>::name() << endl;
    cout << clock_desc<process_real_cpu_clock>::since() << endl;
}

//
void case4()
{
    auto tp1 = system_clock::now();                                                    //获取系统时钟的当前时间点
    cout << tp1 << endl;

    auto d = tp1.time_since_epoch();                                                    //获取自起点以来的时间长度
    cout << duration_cast<hours>(d) << endl;                                //转换为小时
    cout << duration_cast<day>(d) << endl;                                      //转换为自定义的天  

    auto tp2 = tp1 +minutes(1);                                                         //1分钟之后的时间点
    cout << tp2 << endl;

    {
        auto tp = steady_clock::now();
        cout << tp << endl;

        auto d = tp.time_since_epoch();
        cout << round<minutes>(d) << endl;                              //转换分钟
        cout << round<hours>(d) << endl;
    }
}

//
hours operator"" _h(unsigned long long n)       //小时字面意思
{
    return hours(n);
}

seconds operator"" _s(unsigned long long n)     //秒字面意思
{
    return seconds(n);
}

milliseconds operator"" _ms(unsigned long long n)   //毫秒字面值
{
    return milliseconds(n);
}
void case5()
{
    auto h = 5_h;
    auto s = 45_s;
    auto ms = 200_ms;

    cout << h << s << ms << endl;
}
//
void case6()
{
    auto tp = system_clock::now();                  //当前时间
    auto t = system_clock::to_time_t(tp);       //转换为time_t结构

    cout << std::ctime(&t) << endl;             //输出字符串形式的日期
}

//
class steady_timer final
{
private:
    typedef boost::chrono::steady_clock clock_type;                 //定义时钟类型

    //typedef clock_type::duration duration_type;
    typedef clock_type::time_point time_point_type;             //定义时间点类型
    typedef boost::chrono::microseconds duration_type;          //使用微秒精度

    time_point_type m_start = clock_type::now();                        //构造时记录时间点
public:
    steady_timer() = default;                                                            
    ~steady_timer() = default;
public:
    void restart()
    {
        m_start = clock_type::now();
    }

    duration_type elapsed() const
    {
        return round<duration_type>(
                clock_type::now() - m_start);
    }
};

//

int main()
{
    steady_timer t;

    case1();
    case2();
    case3();
    case4();
    case5();
    case6();

    cout << t.elapsed() << endl;
}

3. cpu_timer

3.1 功能:

计算cpu的相关时间

3.2 头文件:

#define BOOST_ERROR_CODE_HEADER_ONLY
#include <boost/system/error_code.hpp>
using namespace boost::system;

3.3 用法:

#include "/home/桌面/算法书/C++Boost/boost_guide/common/std.hpp"
using namespace std;

#include <boost/algorithm/string.hpp>
#include <boost/timer/timer.hpp>
using namespace boost::timer;

//
void case1()
{
    vector<string> v(10, "monado");         //一个存储字符串的容器

    cpu_timer t;                                                    //声明同时启动计时器
    assert(!t.is_stopped());

    for (int i = 0;i < 10000; ++i)
    {
        boost::join(v, "-");                                    //Boost的字符串连接算法
    }//end for

    t.stop();                                                               //暂时计时器
    assert(t.is_stopped());                                  //计时器已经暂停

    cout << "pause for a while..." << endl;                 //标准流输出
    cout << "we can do something..." << endl;       //不计入时间

    t.resume();                                                                             //恢复计时器运行
    assert(!t.is_stopped());

    for(string& x : v)
    {   x +=x; }

    cout << t.format();
}

//
void case2()
{
    const nanosecond_type ms = 1000 * 1000;                     //毫秒常量

    cpu_times ct = {2000 *ms, 1000*ms, 100*ms};                 //初始化cpu_times
    cout << format(ct, 7);                                                                      //默认格式输出
}
//2.000 wall, 1.00s user + 0.100s system = 1.100s cpu(55.0%)
//
void case3()
{
    cpu_times ct = {2000, 1000, 100 };               //初始化cpu_times
    cout << format(ct, 3);                                                                   //默认格式输出

}
//
int main()
{
    case1();
    case2();
    case3();
}

4. system

4.1 功能:

一个可移植的文件系统操作库做了大量的工作,使用POSIX标准表示文件系统的路径,接口很多类似标准库的容器和迭代器具

4.2 头文件:

#include <boost/filesystem.hpp>
using namespace boost::filesystem;

4.3 用法:

“/”来分隔文件名和目录名,“.”表示当前目录,“…”表示上级目录

#include "/home/桌面/算法书/C++Boost/boost_guide/common/std.hpp"
//using namespace std;
using std::string;
using std::cout;
using std::endl;

#include <boost/foreach.hpp>
#include <boost/filesystem.hpp>
using namespace boost::filesystem;
namespace fs = boost::filesystem;

//
void case1()
{
    path p1("./a_dir");
    path p2("/usr/local/lib");
    // path p3("c:\\tmp\\test.text");
    // path p4("d:/boost/boost/filesystem/");

    path p5;
    assert(p5.empty());

}

//
void case2()
{
    char str[] = "the path is (/root).";

    {
        path p(str + 13, str + 14);
        assert(!p.empty());

        p /= "etc";
        string filename = "xinetd.conf";
        p.append(filename.begin(), filename.end());
        cout << p << endl;
        cout << system_complete(p) << endl;			//返回路径在当前文件系统中的完整路径(绝对路径)
    }

    {
        path p(str + 13, str + 15);

        p += "etc";
        string filename = "xinetd.conf";
        p.concat(filename.begin(), filename.end());
        cout << p << endl;
    }

    path p("/::/*/?/<>");
}

//
void case3()
{
    string fname("w+abc.xxx");
    assert(!portable_posix_name(fname));
    assert(windows_name(fname));

    assert(!portable_name("w+()abc.txt")    && !portable_name("./abc"));
    assert(!portable_directory_name("a.txt") && portable_directory_name("abc"));
    assert( portable_file_name("a.bc") && !portable_file_name("y.conf"));

}

//
void case4()																	//路径处理
{
    path p("/usr/local/include/xxx.hpp");

    cout << p.string() << endl;

    cout << p.parent_path() << endl;
    cout << p.stem() << endl;
    cout << p.filename() << endl;
    cout << p.extension() << endl;

    assert(p.is_absolute());				//用于检测path是否是一个绝对(完整)路径,需要依据具体的文件系统的表示
    assert(system_complete(p).is_absolute());

    cout << p.root_name() << endl;
    cout << p.root_directory() << endl;
    cout << p.root_path() << endl;

    assert(!p.has_root_name());
    assert( p.has_root_path());
    assert( p.has_parent_path());
	//下面这两个可以改变原地址path
    cout << p.replace_extension() << endl;
    cout << p.replace_extension("hxx") << endl;
    cout << p.remove_filename() << endl;

    path p1("/test/1.cpp");
    path p2("/TEST/1.cpp");
    path p3("/abc/1.cpp");

    assert(p1 != p2);
    assert(p2 < p3);

    p = "/boost/tools/libs";

    BOOST_FOREACH(auto& x , p)
    {
            cout << "["<< x << "]";			//输出路径字符串
    }

}

//
void case5()
{
    path p("/test.txt");			//一个不存在的文件

    try
    {
        file_size(p);				//检查文件大小
    }
    catch(filesystem_error& e)			//捕获异常
    {
        cout << e.path1() << endl;
        cout << e.what() << endl;
    }

}

//
void case6()
{
    assert(status("/dev/null").type()   == character_file);
    assert(status("/bin").type()    == directory_file);
    assert(status("/bin/sh").type()     == regular_file);

    assert((status("/bin/sh").permissions() & owner_exe) == owner_exe);

    path root = "/usr/local/include/boost";

    assert( is_directory(root));
    assert(!exists(root/"nofile"));
    assert(!is_symlink(root/"version.hpp"));
    assert(!is_other(root/"version.hpp"));
    assert( is_regular_file(root/"version.hpp"));
    assert(!fs::is_empty(root/"version.hpp"));

}

//
void case7()
{
    cout << initial_path() << endl;
    cout << current_path() << endl;

    // generate a temp file for test
    std::ofstream("./test.txt") << "abcd" << std::endl;

    //path p("/usr/local/include/boost/version.hpp");
    path p("./test.txt");
    cout << file_size(p) << endl;

    time_t t = last_write_time(p);
    last_write_time(p, time(0));

    (void)t;
}

//
#include <boost/ratio.hpp>
void case8()
{
    using namespace boost;
    //const int GBYTES = 1000*1000*1000;          //GB,不是GiB
    space_info si = space("/home/chrono");
    cout << si.capacity / giga::num<< endl;
    cout << si.available / giga::num<< endl;
    cout << si.free / giga::num<< endl;
}

//
void case9()
{
    //namespace fs = boost::filesystem;

    path ptest = "./test";
    if (exists(ptest))
    {
        if (fs::is_empty(ptest))
        {
            remove(ptest) ;
        }
        else
        {
            remove_all(ptest);
        }
    }

    assert(!exists(ptest));
    create_directory(ptest) ;

    copy_file("/usr/local/include/boost/version.hpp", ptest / "a.txt");
    assert(exists(ptest / "a.txt"));

    rename(ptest / "a.txt", ptest / "b.txt");
    assert(exists(ptest / "b.txt"));

    create_directories(ptest / "sub_dir1" / "sub_dir1");
}

//
void case10()
{
    //directory_iterator end;
    //for (directory_iterator pos("/usr/local/lib/");pos != end; ++pos)
    //{       cout << *pos << endl;   }
    string path = "/dev/shm";//"/tmp";

    typedef std::pair<directory_iterator, directory_iterator> dir_range;
    //dir_range dr(directory_iterator("/usr/local/lib/"),
    dir_range dr(directory_iterator(path.c_str()),
    directory_iterator());

    BOOST_FOREACH(auto& x , dr)
    {      cout << x << endl;       }

    typedef recursive_directory_iterator rd_iterator;

    rd_iterator  end;
    for (rd_iterator pos(path.c_str());pos != end; ++pos)
    {
        cout << "depth" << pos.depth() << ":" <<*pos << endl;
    }


}
//
int main()
{
    case1();
    case2();
    case3();
    case4();
    //case5();
    case6();
    case7();
    case8();
    //case9();
    case10();
}

实例1:实现查找文件功能
实例2:实现模糊查找文件功能
实例3:实现拷贝目录功能

#include "/home/桌面/算法书/C++Boost/boost_guide/common/std.hpp"
//using namespace std;
using std::string;
using std::vector;
using std::cout;
using std::endl;

#include <boost/optional.hpp>
#include <boost/utility/string_ref.hpp>

#include <boost/foreach.hpp>
#include <boost/filesystem.hpp>
using namespace boost;
using namespace boost::filesystem;
namespace fs = boost::filesystem;

typedef recursive_directory_iterator rd_iterator;
//
optional<path>
find_file(const path& dir, const string& filename)
{
    typedef optional<path> result_type;
    if (!exists(dir) ||!is_directory(dir))
    {   return result_type();   }

    rd_iterator end;
    for (rd_iterator pos(dir);pos != end; ++pos)
    {
        if(!is_directory(*pos) &&
                pos->path().filename() == filename)
        {   return result_type(pos->path());    }
    }

    return result_type();
}

void case1()
{
    auto r = find_file("/usr/local/include/boost", "version.hpp");

    if (r)
    {   cout << *r << endl; }
    else
    {   cout << "file not found." << endl;  }
}

//
#include <boost/xpressive/xpressive_dynamic.hpp>
#include <boost/algorithm/string.hpp>
using namespace boost::xpressive;

vector<path> find_files(const path& dir, const string& filename)
{
    static xpressive::sregex_compiler rc;
    if (!rc[filename].regex_id())
    {
        string str = replace_all_copy(
                replace_all_copy(filename, ".", "\\."),
                "*", ".*");
        rc[filename] = rc.compile(str);
    }

    typedef vector<path> result_type;
    result_type v;

    if (!exists(dir) || !is_directory(dir))
    {   return v;    }

    rd_iterator end;
    for (rd_iterator pos(dir);pos != end; ++pos)
    {
        if(!is_directory(*pos) &&
                regex_match(pos->path().filename().string(), rc[filename]))
        {
            v.push_back(pos->path());
        }
    }

    return v;
}

void case2()
{
    auto v = find_files("/usr/local/include/boost/timer", "*.hpp");
    cout << v.size() << endl;

    for(path &p : v)
    {   cout << p << endl;  }

}

//

// disable pragma warning
#define BOOST_ALLOW_DEPRECATED_HEADERS

#include <boost/progress.hpp>

size_t copy_files(const path& from_dir, const path& to_dir ,
                    const string& filename = "*")
{
    if (!is_directory(from_dir))
    {
        cout << "args is not a dir." << endl;
        return 0;
    }

    cout << "prepare for copy, please wait..." << endl;

    auto v = find_files(from_dir, filename);
    if (v.empty())
    {
        cout << "0 file copied." << endl;
        return 0;
    }

    cout << "now begin copy files ..." << endl;
    path tmp;
    progress_display pd(v.size());

    for(auto& p : v)
    {
        tmp = to_dir / p.string().substr(from_dir.string().length());
        if (!exists(tmp.parent_path()))
        {
            create_directories(tmp.parent_path());
        }
        copy_file(p, tmp);
        ++pd;
    }

    cout << v.size() << " file copied." << endl;
    return v.size();
}

void case3()
{
    copy_files("/usr/local/include/boost/timer", "./t");
}

//
#include <boost/filesystem/fstream.hpp>
namespace newfs = boost::filesystem;

void case4()
{
    // generate a temp file for test
    std::ofstream("./test.txt") << "abcd" << std::endl;

    path p("./test.txt");
    newfs::ifstream ifs(p);
    assert(ifs.is_open());
    cout << ifs.rdbuf();

    // remove file
    ifs.close();
    remove(p);
}


//

int main()
{
    case1();
    case2();
    case3();
    case4();
}

5. program_options

4.1 功能:

参数选择器

4.2 头文件:

#include <boost/program_options.hpp>
using namespace boost::program_options;

4.3 用法:

#include <fstream>
#include <sstream>
#include "/home/桌面/算法书/C++Boost/boost_guide/common/std.hpp"
using namespace std;

#include <boost/program_options.hpp>
using namespace boost::program_options;

//
int case1(int argc, char* argv[])                               
{
    options_description opts("demo options");           

    opts.add_options()                                                                                  //增加两个程序选项
        ("help", "just a help info")                                                                    //帮助选项
        ("filename", value<string>(), "to find a file")                                  //文件名选项
        ;
    variables_map vm;                                                                           //选项存储map容器
    store(parse_command_line(argc, argv, opts), vm);            //解析存储

    if (vm.count("help"))                                                                               //处理帮助选项
    {
        cout << opts << endl;                                                       //输出帮助选项
        return 0;
    }

    if (vm.count("filename"))                                       //要查找的文件名
    {   cout << "find " << vm["filename"].as<string>() << endl;}

    if (vm.empty())                                                 //没有任何选项参数
    {   cout << "no options" << endl;   }

    return 0;
}

int main(int argc, char* argv[])      //需要命令行参数
{
    case1(argc, argv);
}
#include <fstream>
#include <sstream>
#include "/home/桌面/算法书/C++Boost/boost_guide/common/std.hpp"
using namespace std;

#include <boost/program_options.hpp>
using namespace boost::program_options;

//
void print_vm(options_description &opts, variables_map &vm)
{
    if (vm.empty())         //无参数处理
    {
        cout << opts << endl;       //输出帮助信息
        return;
    }

    if (vm.count("help"))  //处理帮助选项
    {
        cout << opts << endl;
    }

    //输出查找文件名,因为它有缺省值,故总存在
    cout << "find opt:" << vm["filename"].as<string>() << endl;

    if (vm.count("dir"))                            //处理搜索路径
    {
        cout << "dir opt:";
        for(auto& str:
                vm["dir"].as<vector<string> >())            //遍历选项值
        {   cout << str << ","; }
        cout << endl;
    }

    if (vm.count("depth"))
    {   cout << "depth opt:" << vm["depth"].as<int>() << endl;}     //处理搜索深度
}

void case1(int argc, char* argv[])
{
    options_description opts("demo options");

    string filename;
    opts.add_options()

        ("help,h", "help message\n   a bit of long text")

        ("filename,f",
         value<string>(&filename)->default_value("test"), "to find a file")

        ("dir,D", value<vector<string> >()->multitoken(), "search dir")

        ("depth,d", value<int>()->implicit_value(5), "search depth")
        ;

    variables_map vm;
    store(parse_command_line(argc, argv, opts), vm);
    notify(vm);

    print_vm(opts, vm);

    stringstream ss;
    ss << "filename=a.cpp\ndir=/usr/bin\ndepth=10";
    store(parse_config_file(ss, opts), vm);

    ifstream ifs("config.ini");
    store(parse_config_file(ifs, opts, true), vm);

    const char *str = "config.ini";
    store(parse_config_file<char>(str, opts, true), vm);

}

int main(int argc, char* argv[])      //需要命令行参数
{
    case1(argc, argv);
}
#include <fstream>
#include <sstream>
#include "/home/桌面/算法书/C++Boost/boost_guide/common/std.hpp"
using namespace std;

#include <boost/program_options.hpp>
using namespace boost::program_options;

//
int case1(int argc, char* argv[])
{
    options_description opts("demo options");

    opts.add_options()
        ("help", "just a help info")
        ("filename", value<string>(), "to find a file")
        ;
    variables_map vm;
    store(parse_command_line(argc, argv, opts), vm);

    if (vm.count("help"))
    {
        cout << opts << endl;
        return 0;
    }

    if (vm.count("filename"))
    {   cout << "find " << vm["filename"].as<string>() << endl;}

    if (vm.empty())
    {   cout << "no options" << endl;   }

    return 0;
}

//

void case2()
{
    value<string>();

    value<int>()->default_value(10)
        ->implicit_value(1);

    double x;
    value<double>(&x)->zero_tokens()
        ->multitoken()->required();

}

//
void print_vm(options_description &opts, variables_map &vm)
{
    if (vm.empty())
    {
        cout << opts << endl;
        return;
    }

    if (vm.count("help"))
    {
        cout << opts << endl;
    }

    //输出查找文件名,因为它有缺省值,故总存在
    cout << "find opt:" << vm["filename"].as<string>() << endl;

    if (vm.count("dir"))
    {
        cout << "dir opt:";
        for(auto& str:
                vm["dir"].as<vector<string> >())
        {   cout << str << ","; }
        cout << endl;
    }

    if (vm.count("depth"))
    {   cout << "depth opt:" << vm["depth"].as<int>() << endl;}
}

void case3(int argc, char* argv[])
{
    options_description opts("demo options");

    string filename;
    opts.add_options()

        ("help,h", "help message\n   a bit of long text")

        ("filename,f",
         value<string>(&filename)->default_value("test"), "to find a file")

        ("dir,D", value<vector<string> >()->multitoken(), "search dir")

        ("depth,d", value<int>()->implicit_value(5), "search depth")
        ;

    variables_map vm;
    store(parse_command_line(argc, argv, opts), vm);
    notify(vm);

    print_vm(opts, vm);

    stringstream ss;
    ss << "filename=a.cpp\ndir=/usr/bin\ndepth=10";
    store(parse_config_file(ss, opts), vm);

    ifstream ifs("config.ini");
    store(parse_config_file(ifs, opts, true), vm);

    const char *str = "config.ini";
    store(parse_config_file<char>(str, opts, true), vm);

}

//
void case4(int argc, char* argv[])
{
    options_description opts("demo options");

    string filename;
    opts.add_options()

        ("help,h", "help message\n   a bit of long text")

        ("filename,f",
         value<string>(&filename)->default_value("test"), "to find a file")

        ("dir,D", value<vector<string> >()->multitoken(), "search dir")

        ("depth,d", value<int>()->implicit_value(5), "search depth")
        ;

    variables_map vm;

    positional_options_description pod;
    pod.add("filename", 1).add("dir", 2).add("depth", -1);
    auto pr =
        command_line_parser(argc, argv).
            options(opts).
                positional(pod).
                    run();
                    store(pr, vm );

    notify(vm);
    print_vm(opts, vm);
}

//
string name_mapper(const string& env_name)
{
    static map<string, string> nm =
        {{"HOME", "home"},{"USER", "uname"}};

    return nm[env_name];
}

void case5(int argc, char* argv[])
{
    options_description opts("demo options");

    string filename;
    opts.add_options()

        ("help,h", "help message\n   a bit of long text")

        ("filename,f",
         value<string>(&filename)->default_value("test"), "to find a file")

        ("dir,D", value<vector<string> >()->multitoken(), "search dir")

        ("depth,d", value<int>()->implicit_value(5), "search depth")
        ("home", value<string>(), "home dir")
        ("uname", value<string>(), "user's name")

        ;

    variables_map vm;

    store(parse_environment(opts, name_mapper),vm);
    cout << vm["home"].as<string> ()<< endl;
    cout << vm["uname"].as<string> ()<< endl;

    notify(vm);
    print_vm(opts, vm);
}

//
void case6(int argc, char* argv[])
{
    options_description opts1("group 1");
    opts1.add_options()
        ("help,h", "help message");

    options_description opts2("group 2(hide)");
    opts2.add_options()
        ("filename,f", value<string>(), "to find a file");

    options_description opts3("group 3");
    opts3.add_options()
        ("dir,D", value<vector<string> >()->composing(), "search dir")
        ("depth,d", value<int>(), "search depth");

    options_description opts_all;
    opts_all.add(opts1).add(opts2).add(opts3);

    options_description opts_cfgfile;
    opts_cfgfile.add(opts2).add(opts3);

    options_description opts_showhelp("demo options");
    opts_showhelp.add(opts1).add(opts3);

    variables_map vm;

    store(parse_command_line(argc, argv, opts_all), vm);
    store(parse_config_file<char>("config.ini", opts_cfgfile, true), vm);

    if (vm.count("help") || vm.empty())
    {
        cout << opts_showhelp << endl;
        return;
    }

    notify(vm);
    print_vm(opts_all, vm);
}


//

int main(int argc, char* argv[])
{
    //case1(argc, argv);
    case2();
    //case3(argc, argv);
    //case4(argc, argv);
    //case5(argc, argv);
    case6(argc, argv);
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值