Monday, May 24, 2010

最后的战役

John Basilone

献给John Basilone & Lena Mae Riggi

《The Pacific》第8集是属于John Basilone的, 前几集的大肆渲染让我感到很是困惑, 如此一个言过其实的角色凭什么占有这么多的戏份. 直到第8集, 我看到了他身上的正气, 看到了他心中不甘沉沦的理想. 当周围的人们因为他的英勇事迹欢呼雀跃, 因为他的荣耀与光环相敬如宾, Basilone想的不是怎样利用自己的影响力去多捞点好处, 不是每天在办公室喝喝咖啡, 玩玩打字机. 可能你也猜到了, Basilone是一个有抱负的人. 作为二战中唯一一个同时获得荣誉勋章与海军十字勋章的海军陆战队队员, 他选择了放弃舒适的生活, 回到那个能够让他的血液沸腾的地方. 他属于战场.

在新兵训练营遇见Lena是Basilone生命的转折, 前面几集大家可能都会把他当作是一个花花公子, 因为每次在他身边出现的女人都不一样. 在酒店就餐那段Lena演得真好, 那语气, 那神情, "Ooh. Ah. There goes John Basilone. The hero of Guadalcanal." Basilone真是尴尬得无地自容, 他需要向Lena证明自己的心是可以依靠的. 让我们跳过谈情说爱的剧情, 反正最后帅哥肯定是赢得了美女的芳心. 在Basilone即将出征奔赴战场之前, Lena嫁给了他. 在我看来, 这是全集最温情的时刻, Basilone躺在床上, 深情地望着Lena美丽的背影, Lena笑笑, 问到"What?", Basilone什么也没有说, 眼神中已经掺杂了些许泪光, 把目光转向了窗外, 那是一片平静的大海. 奔赴战场, 命运未卜, 怎能忍心留下Lena独自一人. Lena说她可以等, 而我只希望导演能够让Basilone平安回家.

1945年2月19日, 硫磺岛登陆战. 在长达10分钟的镜头里, 导演几乎把每一帧都给了Basilone, 这也许就意味着他最终的命运. 即使是在一年后重返战场, Basilone依旧骁勇善战. 在他倒下的那一刻, 世界静止了, 时间也静止了. Basilone微睁的双眼望着远方, 他心中所想, 只有Lena.

Tuesday, May 11, 2010

split()函数的C、C++标准库实现

2010.5.11 22:52更新: 在大猫同学的强烈要求下, 增加了测试代码中动态分配空间的销毁.

2010.5.14 22:46再更新: 上次更新代码之后, 大猫同学指出还是存在内存泄漏问题, 各位同学一定要注意malloc()free()必须成对使用哦~

最近有这么一个需求, split()函数大家都用过, 将字符串按特定的分隔符 (delimiter) 分割成几个部分, 这在脚本语言中早已司空见惯. 但C/C++中是没有的, 于是就给了我这样闲得蛋疼的人消磨时间的机会, 下面分别是用C和C++的标准库实现的split()函数.

首先是C语言的实现, 这个是我自己写的, 函数返回一个指向char*数组 (也就是字符串数组) 的指针.
#include <string.h>
#include <stdlib.h>

/*
 * split - Break a string @s into an array of strings.
 * @s: The string to be split.
 * @delim: The delimiter.
 * @n: The length of the array of strings, created by splitting @s.
 */
char** split(char* s, char delim, int* n)
{
    char* p;
    char* q;
    *n = 1;
    p = q = s;
    /*
     * Calculate the value of @n.
     */
    while ((p = strchr(q, delim)) != NULL)
    {
        ++*n;
        q = p + 1;  // skip the delimiter
    }
    p = q = s;

    char** sep = (char**) malloc(sizeof(char*) * (*n));  // the array of strings
    int i;
    for (i = 0; i != *n; ++i, q = p + 1)
    {
        /*
         * When there isn't delimiter, put `p' point to the end of @s.
         * Same like behavior of strchrnul() library function.
         */
        if ((p = strchr(q, delim)) == NULL)
            p = s + strlen(s);

        int len = p - q;
        sep[i] = (char*) malloc(sizeof(char) * (len + 1));
        strncpy(sep[i], q, len);
        sep[i][len] = '\0';
    }

    return sep;
}
可以使用下面的代码进行测试:
#include <stdio.h>
#include <stdlib.h>

char** split(char*, char, int*);

int main(int argc, char* argv[])
{
    char str[] = ":GFW::is:evil:";
    int i, n;
    char** sep = split(str, ':', &n);
    for (i = 0; i != n; ++i)
        printf("%s\n", sep[i]);

    for (i = 0; i != n; ++i)
    {
        free(sep[i]);
        sep[i] = NULL;
    }
    free(sep);
    sep = NULL;

    return 0;
}

C++实现来自Stack Overflow的一篇讨论, 我稍微进行了一些修改.
#include <sstream>
#include <vector>

using namespace std;

vector<string> split(const string s, char delim = ' ')
{
    vector<string> elems;
    istringstream ss(s);
    string item;
    while (getline(ss, item, delim))
    {
        elems.push_back(item);
    }
    if (item == "")
        elems.push_back(item);
    return elems;
}
代码很简洁, 测试代码就不写了, 大家应该都能看懂. 其实大名鼎鼎的Boost也实现了split(), 但毕竟不是任何时候都能使用Boost.

Sunday, May 9, 2010

转换多个JPG文件到PDF文件

原文发表于「桃源」: http://linux.cuit.edu.cn/?p=908

最近需要将大量JPG格式的图片全部转换到一个PDF文件里, Google之后发现Window$下清一色的收费软件, 即使有试用版, 也会带有很多限制. 而Linux下则从来都不缺乏这种实用的小工具, 在bitPrison.net的一篇文章中介绍了通过ImageMagick中的convert组件进行转换的方法, 经过尝试, 发现这种方法效率很低, 并且会占用很高的CPU. 该篇文章后面的评论提供了一种更优的方法, 使用PDFjam包中的pdfjoin命令完成, 具体步骤如下:
$ rename 's/\.jpg$/\.pdf/' *.jpg
$ pdfjoin --outfile alist.pdf *.pdf
这里先将所有JPG文件重命名为PDF文件, 接着便可使用pdfjoin命令进行合并.

其实GNOME或者KDE下的程序都可以直接将图片打印为PDF文件, 比如使用Eye of GNOME打开图片之后, 选择打印就会出现“Print to File”选项, 这种方法适用于少量的或者临时性的转换需求.