boost 学习笔记 10:设计模式

设计模式是一个面向对象的通用解决方案,是一套被反复使用,多数人知晓的代码设计经验总结。

一般分为:创建型模式、机构型模式和行为模式

创建型模型

抽象工厂 Abstract Factory

提供统一的创建接口。

生成器 Builder

将复杂对象的构建与表示分离,使得同样的构建过程可以创建不同的表示。

工厂方法

定义接口用于创建对象。

原型 Prototype

原型模式使用类的实例通过拷贝的方式创建对象,具体的拷贝行为可以定制。最常见的用法为类实现一个 clone() 成员函数,这个函数创建一个与原型相同或者相似的新对象。

单件 Singleton

运行时,类有且仅有一个实例。

结构性模型

如何组合类或者对象,更而形成更大更有用的新对象。

适配器 Adapter

把一个类的接口转换成另一个接口,在不改变原有代码的基础上复用原代码。

桥接 Bridge

将抽象部分与实现部分分离,使它们都可以独立的变化。

组合 Composite

将小对象组合成树形结构。

装饰 Decorator

运行时动态地给对象增加功能。

外观 Facade

为系统中大量对象提供一个一致的对外接口,简化系统使用。

享元 Flyweight

使用共享的方式节约内存的使用

代理 Proxy

它的意图不是改变接口插入新系统(适配),也不是为对象增加职责(装饰),而是要控制对象。

智能指针库,利用代理模式将原始指针包装,代理原始指针的职能。

行为模式

职责链 Chain of Responsibility

把对象连成一条链,使链上的每个对象都有机会处理请求。

命令 Command

将一个请求封装为一个对象,从而使你可用不同的请求对客户进行参数化。

解释器 Interpreter

给定一个语言, 定义它的文法的一种表示,并定义一个解释器, 该解释器使用该表示来解释语言中的句子。

迭代器 Iterator

提供一种方法顺序访问一个聚合对象中各个元素, 而又不需暴露该对象的内部表示。

中介者 Mediator

包装了一系列对象相互作用的方式,使得这些对象不必相互明显作用,从而使它们可以松散偶合。当某些对象之间的作用发生改变时,不会立即影响其他的一些对象之间的作用,保证这些作用可以彼此独立的变化。

备忘录 Memento

备忘录对象是一个用来存储另外一个对象内部状态的快照的对象。备忘录模式的用意是在不破坏封装的条件下,将一个对象的状态捉住,并外部化,存储起来,从而可以在将来合适的时候把这个对象还原到存储起来的状态。

观察者 Observer

定义对象间一对多的联系,当一个对象的状态发生变化时,所有与它有联系的观察者对象都会得到通知。

状态 State

允许对象在状态发生变化时行为也同时发生改变。

策略 Strategy

封装不同的“算法”,使它们可以在运行时相互替换。

模板 Template method

模板方法模式准备一个抽象类,将部分逻辑以具体方法及具体构造子类的形式实现,然后声明一些抽象方法来迫使子类实现剩余的逻辑。不同的子类可以以不同的方式实现这些抽象方法,从而对剩余的逻辑有不同的实现。先构建一个顶级逻辑框架,而将逻辑的细节留给具体的子类去实现。

访问者 Visitor

分离类的内部元素和访问它们的操作,可以在不改变内部元素的情况下增加作用于它们的新操作。

其他模式

空对象

用于返回无意义的对象时,它可以承担处理null的责任。

包装外观

通过外观的包装,使应用程序只能看到外观对象,而不会看到具体的细节对象,这样无疑会降低应用程序的复杂度,并且提高了程序的可维护性。

前摄器模式 Proactor

用于为异步事件多路分离和分派处理器的对象行为模式


2016-01-18 boost , C++

国家博物院一日游

说了很久想去国家博物院,只是迟迟没有动脚,终于熬到今天。本不是旅游旺季,早上9点出门到那边依然能够领到票进去,排队人数也不是很多,几乎就是去了拿票直接进。如果想要预约门票的话,提早电话或者网上预定,可参见官网文章

去的时候没有查攻略,也没有看任何文章,进到博物馆才发现那边这么大,一时间竟然不知道从那边逛起,幸而查了一眼马蜂窝,看到有人建议到地下一层从《古代中国》开始看。于是开始一段非常漫长的游览史,不是知道是因为走得太慢还是看的太认真,当走到“三国魏晋南北朝”开始已经开始寻找座位想要快速结束这段旅程了。而此后一遍又一遍的感慨中国历史太长,沉浸其中容易无法自拔。

参观的时候没有导游,所以大部分时间就是在读文物的介绍,然后自己维基百科查看,夏商周时候那些青铜器皿,几乎没有知道作用的,于是和小伙伴开始了异想天开,这是洗澡用的,这是喝酒用的,等等,不过倒也知道了一些知识:

  • ”匜“,拼音yí,是先秦的礼器,客人洗手之用。当时还在讨论,如果是,盛水,洗手器,为什么不写成半包围,中间加个手字,多形象
  • 瓦当,已经忘记了在哪个朝代看到的了,后来查看维基才知道,发明于战国时期的鲁班。是屋檐最前面的圆形瓦片,古人会在上面雕刻图案或者神兽。
  • 知道了三国中的魏国并不是曹操建立的,而是他儿子废了汉,看三国的时候没注意呢。
  • 知道了竹林七贤,除了嵇康,阮籍之外多记住了一个刘伶,其他的还是没记住
  • 知道了原来王守仁就是王阳明,他的书法还很不错

后来的后来真的没怎么看了,几乎都是快速浏览过,就这样快速的走过,光是看了一个到1912年的《古代中国》,走出展厅就已经到了下午,后来休息了一下,又粗粗的看了书法展,国博建筑概览就匆匆过去了,很多展厅也没去看,总之以后有机会再过去看看吧。以后有了小孩,应该做好充分的准备工作再去看看,回来之后看到维基上列举的一些国家级文物,印象是有的,只是当时也没有仔细的看,四羊方尊,金缕玉衣,等等当时历史教科书中存在的图片展现到眼前是还是会激动一下的。只是后来倦于拍照片,回来整理也就只几张。

给后人的参考,其之前可以大概的浏览这个维基页面,在其中的古代中国中,列举了一些文物,有一些还是很值得一看的。比如远古时期的”人面鱼纹彩陶盆“,”玉琮“等等;夏商周的青铜器;秦汉的兵马俑,石刻;到后期的瓷器等等。

人面鱼纹彩陶盆 人面鱼纹彩陶盆

大禹治水 大禹治水图

四羊方尊 著名的四羊方尊

金边玉杯 金边玉杯,得此一杯,此生足矣

金制头饰 金制头饰,匆匆路过,突然看到这个饰品,太美了。

可爱的神兽 可爱的神兽,没想到古人也是挺萌的嘛

又一只萌萌的神兽 又一只萌萌的神兽

说不上名字的青铜器 说不上名字的青铜器,已经忘了他叫什么了,应该也是尊吧。

请工作人员不要这么摆设啊,会吓死人的 最后!!!请工作人员不要这么摆设啊,会吓死人的


2016-01-17 博物院 , travel , beijing , 游记 , 经验总结

boost 学习笔记 9:并发编程

Boost中有两个用于并发编程的组件。首先是thead库:它为C++增加了可移植的线程处理能力。然后是一个用于同步和异步IO操作的功能强大的库——asio,它使用了前摄器模式,可以处理串口,网络通信,而且有望成为C++标准底层通信库。

互斥量是一种用于线程同步的手段,它可以在线程编程中防止多个线程同时操作共享资源(或称临界区)。一旦一个线程锁定了互斥量,那么其他线程必须等待他解锁互斥量才能在访问共享资源。thead提供了7中互斥量类型(实际只有五种):

  • mutex 独占式互斥量
  • try-mutex mutex 同义词
  • timed_mutex 独占式互斥量,提供超时锁定功能
  • recursive_mutex 递归式互斥量,可以多次锁定,相应也要多次解锁
  • recursive_try_mutex recursive_mutex 同义词
  • recursive_time_mutex 递归式互斥量,基本功能同 recursive_mutex ,提供超时锁定功能
  • shared_mutex multi-reader/single-writer 型共享互斥量 读写锁

mac下使用 boost thread 需要将 libboost_thread.dylib libboost_thread-mt.dylib lib boost-system.dylib 加入到工程,链接进工程。

具体用法:

#include <iostream>
#include <string>
#include <boost/assign.hpp>
#include <boost/typeof/typeof.hpp>
#include <boost/assign.hpp>
#include <boost/thread.hpp>
#include <boost/thread/mutex.hpp>
#include <boost/ref.hpp>
#include <boost/bind.hpp>
using namespace boost;
using namespace std;

#define BOOST_DATE_TIME_SOURCE
#define BOOST_THREAD_NO_LIB

// 模板类配合模板参数提供不同范围的计数,提供隐式类型转换操作
// 在多线程环境下安全计数
template <typename T>
class basic_atom: noncopyable {
private:
    T n;
    typedef boost::mutex mutex_t;
    mutex_t mu;

public:
    basic_atom(T x = T()):n(x) {}
    T operator++(){
        mutex_t::scoped_lock lock(mu);
        return ++n;
    }
//    T operator=(const T _n){
//        mutex_t::scoped_lock lock(mu);
//        n = _n;
//        return _n;
//    }
    operator T()    {return n;}
};

boost::mutex io_mu;

typedef basic_atom<int> atom_int;

void printing(atom_int& x, const string& str){
    for (int i = 0;  i < 5; ++i) {
        boost::mutex::scoped_lock lock(io_mu);
        cout << str << ++x <<endl;
    }
}

void to_interrupt(atom_int& x, const string& str){
    try {
        for (int i = 0;  i < 5; ++i) {
            this_thread::sleep(posix_time::seconds(1));
            boost::mutex::scoped_lock lock(io_mu);
            cout << str << ++x <<endl;
        }
    } catch (thread_interrupted& ) {
        cout << "thread_interrupted" <<endl;
    }
}

int main(int argc, const char * argv[]) {

    cout << "start" <<endl;
    this_thread::sleep(posix_time::seconds(2));
    cout << "sleep 2 seconds" <<endl;

    boost::mutex mu;
    try {
        mu.lock();
        cout << "do some operations" << endl;
        mu.unlock();
    } catch (...) {
        mu.unlock();
    }

    boost::mutex mu1;
    boost::mutex::scoped_lock lock(mu1);
    cout << "some operations" <<endl;

    atom_int x;

    thread t1(printing, boost::ref(x), "hello");

//    this_thread::sleep(posix_time::seconds(2));

    // join & timed_join
    if (t1.joinable()) {
        t1.join();          // 等待t1 线程结束再返回,不管执行多长时间
    }

    thread t2(printing, boost::ref(x), "boost");
    t2.timed_join(posix_time::seconds(1));      // 最多等待1秒返回

    thread t(to_interrupt, boost::ref(x), "interrupt");
    this_thread::sleep(posix_time::seconds(4));
    t.interrupt();
    t.join();

    return 0;
}

asio

Boost.Asio是一个跨平台的、主要用于网络和其他一些底层输入/输出编程的C++库。以下代码实现一个简单的tcp服务,访问http://localhost:6688可得到字符.

#include <iostream>
#include <string>
#include <boost/assign.hpp>
#include <boost/typeof/typeof.hpp>
#include <boost/assign.hpp>
#include <boost/thread.hpp>
#include <boost/thread/mutex.hpp>
#include <boost/asio.hpp>
using namespace boost;
using namespace std;

int main(int argc, const char * argv[]) {
    using namespace boost::asio;

    try {
        io_service ios;

        ip::tcp::acceptor acceptor(ios, ip::tcp::endpoint(ip::tcp::v4(), 6688));
        cout << acceptor.local_endpoint().address() << endl;

        while (true) {
            ip::tcp::socket sock(ios);
            acceptor.accept(sock);

            cout << "client:" ;
            cout << sock.remote_endpoint().address() << endl;
            sock.write_some(buffer("hello asio"));
        }
    } catch (std::exception& e) {
        cout << e.what() << endl;
    }

    return 0;
}

更多 boost.asio 相关内容查看C++ 网络编程


2016-01-16 boost , C++

boost 学习笔记 10:Python

项目中需要将C++的程序暴露给网络使用,我也不想使用C++来用网络编程,就想到可以使用Python来解决Web端,然后将 C++ 的接口暴露给 Python 。于是在寻求解决方案的时候找到了 boost.python 库。

boost 中的 Python 库支持在 Python 和 C++ 之间的自由转换,包括 C++ 到 Python 的类型转换,默认参数,关键字参数,引用,指针等等。boost.python 库可以让 Python 轻易地调用 C++ 编写的模块,也可以很容易地在 C++ 中调用 Python 。

使用

C++ 文件中需要包含头文件

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

还需要在链接的时候,加入 -lboost_python

以下操作借助Linux下g++完成,Windows可能需要借助其他工具,导出C++函数具体实现:

hello.cpp

char const* greet()
{
    return "hello, world";
}

#include <boost/python.hpp>

BOOST_PYTHON_MODULE(hello)			// Python 模块开始
{
    using namespace boost::python;		// 打开命名空间
    def("greet", greet);
}

Makefile

PYTHON_VERSION = 2.7
PYTHON_INCLUDE = /usr/include/python$(PYTHON_VERSION)

# location of the Boost Python include files and library
#  
BOOST_INC = /usr/local/include
BOOST_LIB = /usr/local/lib

# compile mesh classes
TARGET = hello

$(TARGET).so: $(TARGET).o
    g++ -shared $(TARGET).o -L$(BOOST_LIB) -lboost_python -L/usr/lib/python$(PYTHON_VERSION)/config -lpython$(PYTHON_VERSION) -o $(TARGET).so

$(TARGET).o: $(TARGET).cpp
    g++ -I$(PYTHON_INCLUDE) -I$(BOOST_INC) -fPIC -c $(TARGET).cpp

clean:
    rm *.so *.o

hello.py

#!/usr/bin/env python
# -*- coding: UTF-8 -*-

import hello
print hello.greet()

输出: hello, world

注意将 python, boost 所在目录 include 进去,在链接时加上 -lboost_python -lpython2.7 并 include python 和 boost目录。

Demo 地址GitLab : https://gitlab.com/einverne/boost_test/


2016-01-16 boost , C++

删除社交账号状态

这两天陆陆续续通过一些插件脚本删除了一些社交网站数据。年轻的时候发过一些无聊的状态,然后很久以后都没有登陆过的一些账号,倒不如关了的好,自此以后墙外只用 Google+ , 还有 Blog 记录一下所思所想,墙内公开内容除了豆瓣可能也没得发了,不愿生活在一个审查的制度下。虽然我可能也不会发什么敏感的内容,可谁知道什么敏感,什么不敏感呢?

facebook

Delete all facebook posts , 可以利用以下插件删除 Facebook 所有状态,包括账号内的头像等等。

Chrome Extension link

https://chrome.google.com/webstore/detail/facebook-timeline-cleaner/lfejocdlmhhkmnabbaeckmaehmgaffje

Update: 可惜了这个插件被删除了

renren

关闭账号

weibo

delete tool 删除工具 http://app.weibo.com/detail/62A7lB

批量删除 weibo http://3.amfen.sinaapp.com/

删除微博评论 http://weibo333.com/

腾讯微博

设置中关闭账号

关闭 QQ 空间

通过以下链接申请删除 QQ 空间。

http://imgcache.qq.com/qzone/web/qzone_submit_close.html


2016-01-15 经验总结 , social , posts

间谍之桥 感悟

间谍之桥 Bridge of Spies 2015 影评

一名伟大的律师,成就一件伟大的人质交换。剧情7分,表演8分,娱乐7分。汤姆汉克斯的演技自然没得说,不过俄国人质的更加深入人心,虽然并不知道他的名字,但之后就再不会忘记他的名字 —- Mark Rylance 。而电影在娱乐性方面给人更多的是思考,沉浸在那段历史中,思考的是那段历史中人们做过的每一个决策。

原本以为这部影片是讲述“间谍”之间的故事,看到开场辩护时就知道被标题所骗。联系到最近的快播案,两国在司法上可谓天上地下。从1957年的《十二怒汉》开始,到这部《间谍之桥》50多年间好莱坞从未放弃探讨司法的公平性。而前半部分的辩护差点让我以为电影会从间谍故事转变成法庭辩护。幸而在后面美国侦察机被炸到苏联土地等情节,才让故事走上交换人质的主线。也让电影变得更加主旋律。

电影中最棒的两段台词:

第一段出现在CIA希望Donovan背弃律师的誓言泄露被告的信息时,Donovan告诉CIA探员的话:

I’m Irish, you’re German, but what makes us both Americans? Just one thing, one one one. The rule book. We call it the Constitution. We agree to the rules, and that’s what makes us Americans, it’s all that makes us Americans.

第二段是 Donovan和 Abel 之间的对话。

DONOVAN: You don’t seem alarmed. ABEL: Would it help?

电影剧本下载地址


2016-01-13 movie , 思考感悟 , american , action

每天学习一个命令:su 切换身份或者使用 superuser

su 用来切换身份或者升级成使用 superuser。如果没有加任何参数,则 su 默认变为 superuser。

参数格式

    su [options] [username]

su 命令用来改变当前登录 session 的用户身份。直接使用 su 默认成为 superuser,使用参数 su - 短横线,则完全切换成该用户登录的状态,连同环境变量一同切换,工作目录也会切换。

-c 指令  或 --command= 指令 :执行完指定的指令后,即恢复原来的身份; 
-f 或——fast:适用于 csh 与 tsch,使 shell 不用去读取启动文件; 
- 或 -l 或——login:改变身份时,也同时变更工作目录,以及 HOME,SHELL,USER,logname。此外,也会变更 PATH 变量; 
-m,-p 或 --preserve-environment:变更身份时,不要变更环境变量; 
-s 或 --shell=:指定要执行的 shell; 

使用

切换用户而不切换工作目录

whoami   # 显示当前用户
einverne
pwd  # 当前目录
/home/einverne
su root # 切换到 root 用户
Password:
ev einverne # whoami
root
ev einverne # pwd
/home/einverne
ev einverne # exit
exit

切换用户并切换工作目录

whoami
einverne
pwd
/home/einverne
su -
Password:
ev ~ # pwd  # 注意此目录
/root
ev ~ #

2016-01-12 linux , command , su , superuser

boost 学习笔记 8:算法

对应书中第8章 算法,这一章作者介绍的很简单,只是举例使用 foreach , minmax ,其他算法都略去了。

foreach

将C++的语法扩充,使用 foreach 循环变量。

需包含头文件

#include <boost/foreach_hpp>

具体用法:

#include <iostream>
#include <string>
#include <boost/assign.hpp>
#include <boost/typeof/typeof.hpp>
#include <boost/assign.hpp>
#include <boost/foreach.hpp>
using namespace boost;
using namespace std;

int main(int argc, const char * argv[]) {

    using namespace boost::assign;
    vector<int> v = (list_of<int>(1),2,3,4,5);

    /**
     * 第一个参数 VAR 是循环变量声明 想要高效地使用序列内元素或者修改序列,需要声明使用引用
     * 第二个参数 COL 是要遍历的序列
     *
     */
    BOOST_FOREACH(int x, v){
        cout << x << "-";
    }
    cout << endl;

    string str("hello world");
    BOOST_FOREACH(char& c, str){
        cout << c << "-";
    }
    cout << endl;

    // use typeof
    BOOST_TYPEOF(*v.begin()) y;             // BOOST_AUTO(y, *v.begin())
    BOOST_FOREACH(y, v){
        cout << y << ",";
    }
    cout << endl;

    return 0;
}

minmax

在同一次操作中同时获取最大最小值。需包含头文件:

#include <boost/algorithm/minmax.hpp>
using namespace boost;

具体用法:

#include <iostream>
#include <string>
#include <boost/assign.hpp>
#include <boost/typeof/typeof.hpp>
#include <boost/assign.hpp>
#include <boost/algorithm/minmax_element.hpp>
using namespace boost;
using namespace std;

int main(int argc, const char * argv[]) {

    using namespace boost::assign;

    vector<int> v = (list_of(543), 90, 23, 42, 3, 10);

    BOOST_AUTO(x ,boost::minmax_element(v.begin(), v.end()));
    cout << "min: " << *x.first << endl;
    cout << "max: " << *x.second << endl;

    // first_min_element  找到第一个最小值
    // last_min_element 最后一个最小值

    return 0;
}

2016-01-12 boost , C++

boost 学习笔记 7:property_tree

上一篇文章boost容器中留下一个property_tree 没有学,觉得既然 boost 提供了 property_tree 这样好的工具来给C++ 解析xml和Json,必须要留有一定的篇幅来讲它。

原先项目中使用到JSON,需要使用C++解析一段返回值, JSON 格式如下:

{
  "ret": "101",
  "error": [
    {
      "errortype": "A0001",
      "errorstroke": {
        "0": "0.2",
        "1": "0.3"
      }
    },
    {
      "errortype": "A0021",
      "errorstroke": {
        "0": "0.2",
        "1": "0.3"
      }
    }
  ]
}

error 字段是一个数组,数组中的每个元素都是一个对象Object,每个Object中是一个键值对,其中 errorstroke 同样包含一个对象。我们都知道JSON只包含三种数据结构,矢量,数组和映射(参考),这样无疑给我们的解析工作带来很多遍历,这三种数据结构几乎可以将时间所有的信息包含进去。

下面就是解析这段 JSON 字符串的具体代码:(注意将JSON字符串 escape)

#include <iostream>
#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/json_parser.hpp>
#include <boost/foreach.hpp>
#include <string>

using namespace boost::property_tree;

int main(int argc, const char * argv[]) {

    std::string str_json = "{\"ret\":\"101\",\"error\":[{\"errortype\":\"A0001\",\"errorstroke\":{\"0\":\"0.2\",\"1\":\"0.3\"}},{\"errortype\":\"A0021\",\"errorstroke\":{\"0\":\"0.2\",\"1\":\"0.3\"}}]}";

    ptree pt;                       //define property_tree object
    std::stringstream ss(str_json);
    try {
        read_json(ss, pt);          //parse json
    } catch (ptree_error & e) {
        return 1;
    }

    std::cout << pt.get<std::string>("ret") << std::endl;
    ptree errortype = pt.get_child("error");            // get_child to get errors

    // first way
    for (boost::property_tree::ptree::iterator it = errortype.begin(); it != errortype.end(); ++it) {
        std::cout << it->first;
        std::cout << it->second.get<std::string>("errortype") << std::endl;
        ptree errorstroke = it->second.get_child("errorstroke");
        for (ptree::iterator iter = errorstroke.begin(); iter != errorstroke.end(); ++iter) {
            std::string key = iter->first;
            std::cout << iter->first << std::endl;
            std::cout << iter->second.data() << std::endl;
        }
    }

    // second way: using boost foreach feature
//    BOOST_FOREACH(ptree::value_type &v, errortype){
//        ptree& childparse = v.second;
//        std::cout << childparse.get<std::string>("errortype") << std::endl;
//        ptree errorstroke = childparse.get_child("errorstroke");
//        BOOST_FOREACH(ptree::value_type& w, errorstroke){
//            std::cout << w.first << std::endl;
//            std::cout << w.second.data() << std::endl;
//        }
//    }
    return 0;
}

代码的输出:

 101
 A0001
 0
 0.2
 1
 0.3
 A0021
 0
 0.2
 1
 0.3

再换用另外一段 JSON 尝试解析,从下面这段 JSON 中能够轻易的看出 JSON 内部的结构,支持的数据结构和类型:

{
  "array": [
    1,
    2,
    3
  ],
  "boolean": true,
  "null": null,
  "number": 123,
  "object": {
    "a": "b",
    "c": "d",
    "e": "f"
  },
  "string": "Hello World"
}

具体解析代码:

#include <iostream>
#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/json_parser.hpp>
#include <boost/foreach.hpp>
#include <string>
using namespace std;
using namespace boost::property_tree;

int main(int argc, const char * argv[]) {

    std::string str_json = "{\"array\":[1,2,3],\"boolean\":true,\"null\":null,\"number\":123,\"object\":{\"a\":\"b\",\"c\":\"d\",\"e\":\"f\"},\"string\":\"Hello World\"}";

    ptree pt;                       //define property_tree object
    std::stringstream ss(str_json);
    try {
        read_json(ss, pt);          //parse json
    } catch (ptree_error & e) {
        return 1;
    }

    ptree arraypt =pt.get_child("array");
    for (boost::property_tree::ptree::iterator it = arraypt.begin(); it != arraypt.end(); ++it) {
        cout << it->second.data() << " ";
    }
    cout << endl;

    std::cout << pt.get<bool>("boolean") << std::endl;
    std::cout << pt.get<std::string>("null") << std::endl;
    std::cout << pt.get<int>("number") << std::endl;
    std::cout << pt.get<std::string>("string") << std::endl;
    ptree opt = pt.get_child("object");

    BOOST_FOREACH(ptree::value_type &v, opt){
        cout << v.first << " : ";
        cout << v.second.data() << endl;
    }

    return 0;
}

利用 Boost property_tree 构造 JSON 字串,以下代码能够构造上面的JSON:

#include <iostream>
#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/json_parser.hpp>
#include <boost/foreach.hpp>
#include <string>
using namespace std;
using namespace boost::property_tree;

int main(int argc, const char * argv[]) {

    std::string str_json = "{\"array\":[1,2,3],\"boolean\":true,\"null\":null,\"number\":123,\"object\":{\"a\":\"b\",\"c\":\"d\",\"e\":\"f\"},\"string\":\"Hello World\"}";

    ptree root, arr,object;
    arr.push_back(std::make_pair("","1"));
    arr.push_back(std::make_pair("","2"));
    arr.push_back(std::make_pair("","3"));

    object.put("a","b");
    object.put("c","d");
    object.put("e","f");

    root.add_child("array", arr);
    bool boolvalue = true;
    root.put("boolean",boolvalue);
    root.put("null","null");
    int num = 123;
    root.put("number",num);
    root.add_child("object",object);
    root.put("string","Hello World");

    //write_json("out.json", root);
    stringstream s;
    write_json(s, root, false);
    string out = s.str();
    cout << out ;
    return 0;
}

两个有用的JSON工具:

Boost property_tree 解析 XML 可参考这篇文章 ,解释得非常清楚。


2016-01-11 boost , C++

每天学习一个命令:apt 安装卸载软件

APT 是 Advanced Packaging Tools 的缩写,是 Debian 及其派生的发行版(使用最广泛的 Ubuntu/Linux Mint 等等)的软件包管理器。 APT 可以自动下载、配置和安装二进制或源代码格式软件包,简化了 Unix 系统上管理软件的过程。 APT 最早被设计成 dpkg 的前端,用来处理 deb 格式的软件包。

APT 主要由以下几个命令组成:

  • apt-get
  • apt-cache
  • apt-file

APT 能够自动处理软件的依赖问题,大大简化了工作流程

这里主要讲 apt-get 的常见用法

常用命令

搜索软件包

apt search package_name

安装软件包

apt install package

更新源

自动根据 /etc/apt/sources.list 中的设定,以及 /etc/apt/sources.list.d 目录下的设定,更新软件资料源。

sudo apt update

使用如下命令安装更新

sudo apt upgrade

移除软件源

apt remove package  # 移除软件包,但是保留配置文件
apt purge package #移除软件包并移除配置
apt autoremove # 移除孤立的并不被依赖的软件包

列出软件清单

apt list

升级系统

sudo apt-get dist-upgrade

最后如果还有什么不明了的,可以 man apk

前端界面

我目前使用

  • Synaptic

reference


2016-01-11 apt , linux , command , ubuntu

电子书

最近文章

  • 每天学习一个命令:使用 rz sz 向服务器发送文件 搜索 rz sz 命令使用方式进来的,可以不用往下看了,直接学习 scp 或者 rsync 吧, rz sz 看了一下还是有很多限制的。
  • 分析家里局域网 WiFI 瓶颈 目前我的情况是,家中有一个千兆主路由放在客厅接外面的宽带,而我自己的房间有一台比较老的 Netgear 3800 路由来无线桥接连接外面的主路由,因为我不想我的 3800 路由中的设备暴露到主路由的设置中,所以用了 OpenWrt 的桥接模式。但是随着我在 3800 这台路下接的设备增多,导致目前 3800 这台路由不堪重负,已经影响到了我日常 streaming 局域网 NAS 中的电影。所以最近想更换一下这台已经 8 年历史的 WNDR 3800 路由器。
  • GitLab CI 使用笔记 CI/CD 不必多说。
  • 使用命令行远程网络唤起主机 在 Linux 下可以通过 etherwake 命令来网络唤醒设备。
  • Cloud-init 初始化虚拟机配置 在安装 Proxmox 后在它的文档中了解到了 cloud-init。所以就来梳理一下。