Zade's Weblog

程序人生

Monthly Archives: 12月 2009

红霞映日,哭泄风雨

昨天晚上小妞妞发生了两件好玩的事情:

  1. 大约三点左右,小妞妞睡醒了吃奶,这是她的惯例.吃完了开始睡觉,老婆当时也没有睡意,在旁边静静的看着她.过了一会,觉得她有可能要撒尿了,就起来看看,但是已经迟了.小妞妞睡觉的时候,全身是用一个红色的小棉被裹起来的.这下可好,水漫金山,开裆裤的周围印上了一圈的红边.最为搞笑的是,小妞妞嫩嫩的小屁屁周围,也印上了一周的红边,乍一看真是红霞映日,光辉灿烂.
  2. 快到7点了吧,小妞妞突然毫无征兆的大哭了起来,老婆甚是惊慌,因为刚刚吃完奶,应该不是饿了,莫非是要撒尿?起来一把,果然如此!50天的小妞妞,已经知道通过哭声告诉爸妈:我要撒尿!她可真是聪明.这哭泄风雨之事,希望她以后坚持下去.

std::ios_base::iword和json的格式化输出

在std的标准库里面,有一个这样的接口:ios_base::iword,用于存储用户自定义的数据.我使用std iostream已经有些时间了,但是从未使用过这个函数.

最近在我进行json的格式化输出的时候,使用到了这个函数,特此说明一下.

下面是一个json格式化输出的例子:

name:{
  name1:value1,
  name3:{
    name1:value1,
    name2:value2
  },
  name2:value2,
  name4:[
    value1,
    value2
  ],
  name6:[{
      name2:value2,
      name3:value3
    },{
      name4:value4,
      name5:value5
    }
  ]
}

我们看到,这里的所谓的格式化并没有确切的定义,他的主要目的是为了增强可读性(你可以试着把上面的例子中的回车和空格去掉);考虑Eclipse中关于代码的风格问题.

上面的风格是典型的C语言代码的风格之一,我比较喜欢.那么现在的问题是

1)什么时候添加空格,添加多少?

2)什么时候添加回车?

我们观察一下前面的格式,可以得到以下的结论:

添加空格的时机:

1)name前面

2)]前面

3)}前面

4)数组的value前面

添加回车的时机:在添加空格前面

添加空格的个数:随着[{的数量递增,随着}]的数量递减;也就是说,我们需要一个数目记录括号的数量.问题是这个数据放在那里?

最经典的做法是抽象一个Fromarter对象,然后增加这样的一个接口函数;但是即便如此,因为这个细节是实现内部的,所以暴露在外面也不是很好.再说,这个复杂性是我们目前不想承担的.

在整个输出的过程中,输出对象stream总是存在的,如果能够把这个对象放在stream上是非常合适的,原因是:格式化的生命周期和stream的生命周期是一致的.

下面是我们的代码片段:

       void add_object_begin(){
            ++ ss.iword(0);
            ss << ‘{’;
        }
        void add_object_end(){
            — ss.iword(0);
            this->add_blanks();
            ss << ‘}’ ;
        }
        void add_array_begin(){
            ss << ‘[‘ ;
            ++ ss.iword(0);
        }
        void add_array_end(){
            — ss.iword(0);
            this->add_blanks();
            ss << ‘]’ ;
        }

Eclipse CDT 的无效路径

    使用Eclipse + CDT,我经常使用一些环境变量设置include path.同时当我把这个工程文件在机器之间移植的时候,我一般会修改这些环境变量的值,非常奇怪的是,Eclipse仍然会保留那些没有使用的,无效的include path.

   这虽然不会造成严重的错误,但是会生成警告,非常令人讨厌.我一直查找删除这些无效的include path的方法,终于查找到这样的一句话:

I’ve seen this problem too, old paths are never deleted. To manually fix the file you need to move/delete the ${projectname}.sc file found under ${workspace}/.metadata/.plugins/org.eclipse.cdt.make.core


这样就可以了.

技术开发和专利申请

今天我和同事想申请一篇关于图像瓦块复合文件的专利,我负责主体文件的书写,另一个同事搜索是否存在相同的或者类似的专利存在.

一开始的进行的很顺利,中国专利网上并没有类似的专利.但是不幸的是,昨天发现了一个类似的专利,还是我们同行业的人写的;这令我们很不开心.这倒不是因为这篇专利的存在,而是因为这个专利设计的技术早在2007年,我们就实现了,但是当时我们并没有申请,而这个已经通过的专利正是2007年申请的.

我的一个同事批评我说,你也太没有专利意识了!

这个批评是太对了!

自从我决定从事工程以来,我就没有打算书写一些所谓的论文了;但是没有这些,在年底总结的时候,内容似乎有一些干瘪.为什么不申请专利呢?

我们平时的技术文档,在很大的程度上可以书写成专利;这也是我今天看了和我们同内容的那个专利以后,油然而升起的自信心!

既然这样决定了,那么以后我会在这一方面特别的注意.

明年这个时候,看看我有多少专利吧!

Property Tree 和JSON格式

BOOST1.41发布了,新增加的一个库是Property Tree.在其文档中, 一段实例很能说明问题:

一段基于XML的配置文件:

<debug>
    <filename>debug.log</filename>
    <modules>
        <module>Finance</module>
        <module>Admin</module>
        <module>HR</module>
    </modules>
    <level>2</level>
</debug>

一个C++的内存结构:

struct debug_settings
{
    std::string m_file;          // log filename
    int m_level;                 // debug level
    std::set<string> m_modules;  // modules where logging is enabled
    void load(const std::string &filename);
    void save(const std::string &filename);
};

load的实现:

void debug_settings::load(const std::string &filename)
{
    using boost::property_tree::ptree;
    ptree pt;

    read_xml(filename, pt);

    m_file = pt.get<std::string>("debug.filename");
    m_level = pt.get("debug.level", 0);
    BOOST_FOREACH(ptree::value_type &v,
            pt.get_child("debug.modules"))
        m_modules.insert(v.second.data());
}

save的实现:

void debug_settings::save(const std::string &filename)
{
   using boost::property_tree::ptree;
   ptree pt;

   pt.put("debug.filename", m_file);
   pt.put("debug.level", m_level);
   BOOST_FOREACH(const std::string &name, m_modules)
      pt.put("debug.modules.module", name, true);

   write_xml(filename, pt);
}

这有几个特点:

  1. 基于XML配置文件的读写,在以往我的经验中,一般会使用一个XML的解析库,例如apache的xerces. 根据我的使用经验(2003年左右),这种方式是非常繁琐的,当时我就想到一种比较简便的使用方法,和这里实现load save的思路几乎是相同的,但是没有抽象提高到property tree这样的高度,不过现在看来真是亲切呀!不过我的另外一个教训是,为什么没有顺着这个思路开发一个类似于property tree的API呢?这个值得我深刻的反思一下.
  2. 和DOM模型一样,property tree也是一种完全读取到内存的做法,这比基于事件的XML解析或许不足,但是方便,简单,实用.对于配置文件而言,这足够了
  3. 读写的格式,除了XML,还有经典的INI格式和我最喜欢的JSON格式

从使用简单性来看,INI格式是最好的;从功能的强大性来看,XML格式是最好的;JSON格式居于二者之间.我更看好JSON格式.

给妞妞起名字

给未出生的小孩儿起名字,这一般是准爸爸和准妈妈的必备课.

在妞妞出生以前,我给她起名字的规划是这样的:

如果是男孩,就叫赵尔东(我老婆姓陈),小名叫牛牛(2009是牛年);

如果是女儿,就叫赵雨辰(辰陈同音,下雨的早晨,意境也很美),小名就叫妞妞.

老婆当时没有太多的意见,因为还没到必须的时候.等女儿终于诞生了,起名字的事情也终于搬上日程,老婆对小名没有意见,但是对于大名,觉得有两个不妥:

1 赵雨辰这个名字并不响亮,是平声而不是仄声,她举了一个台湾电视主持人的名字赵少康,很响亮,所以声调的规律是441,赵雨辰不符合

2 女儿诞生在一个鹅毛大雪的子时,而我记得怀她的时候也是今年春天的一个下雪的天气,这个小孩看起来和雪有很大的缘分,而不是雨.

总而言之,女儿的大名并没有在当时定下来,我们一直在商量其他的选择.老婆当时坐月子,这个任务我责无旁贷.像我这样天天接触电脑的人,网络成了我的第一选择.什么周易起名,天眼起名,瓷都起名等,我都查了又查.基本上遵循以下的几个原则:

1 按照老婆大人的意见,名字要响亮,最好的声调规律是441;

2 如果把老婆的姓加在最后,以赵*chen的方式,那么会更好;

3 女儿出生在子时(23点23分),而且当时在下大雪,名字中最好出现子(紫),雪之类的字,以示关联

4 老婆表弟的女儿出生比我们早几天,起名为向诗琪,不过老婆认为向思琪会更好一些,见贤思齐嘛.我嘲笑她那是毛主席儿媳妇的名字了.不过老婆总结的一个经验是最好是从某句诗文中化来一个名字,这样似乎显得比较”有文化”.

5 今年是牛年,名字中的字最好带草字头,预兆口粮很足,以后吃喝无忧.

按照这些原则,我得到的一些候选是:

赵紫涵(符合3)

赵紫萱(符合3,5)

赵雨辰(符合2)

赵雪辰(符合2,3)

赵怡辰(符合2)

赵雅萱(符合5)

赵芸卓(符合1,5)

赵紫菁(符合3)

赵雪钦(符合2)

赵汗青(符合1,4)

赵辰菲(符合2)

在这些名字当中,带"紫,涵,萱"都被老婆认为俗气,因为她的同学朋友当当中,有很多是带这些字眼的.

赵雪辰被我认为是很合适的一个,但是老婆反对的理由让我无可奈何:老婆是四川人,在当地的发音中,"雪辰","血橙"很相近,很不妥. 当她说给自己的表弟的时候,几乎立刻遭到嘲笑.

而赵汗青这个名字一下子就引起了老婆的注意."人生自古谁无死,留取丹心照汗青",不仅名字,而且连姓都包含其内,这只能说是太巧了.

这首诗的作者是南宋的文天祥,一个很有骨气的爱国文人.难道是700多年以前这个伟大的诗人就给我女儿把名字定了下来? 我还就这么认为了!

最后我们在字眼上斟酌了一下,定名为赵菡卿.菡是4声(这与我通常的直觉违背,我总是以为3声),有草字头,而且是荷花的意思(菡萏).卿,大臣,贤臣的意思,而且当今最著名的节目主持人之一是董卿,我也当一次追星族吧.这个名字符合了1,4,5.

2009.11.30,我在海淀妇幼给妞妞办了出生证明,起的名字就是"赵菡卿".