共 6 页, « 1 [2] 3 4 5 » ... 最后一页 »
在处理多语言编码、使用UTF-8时,偶尔会遇到这个我称之为“c3c2问题”的问题。花了一天时间好不容易找到了原因所在,写在这里希望对遇到的人有所帮助。基于Perl语言写的,可能是Perl的专有问题,不过其他的语言若遇到类似的现象也可作为参考。
现象
进行编码转换时出现乱码。转换后的结果类似于下面的样子:
c3 a3 c2 81 c2 82 ...
看起来就像是正确的字符序列中加入了许多\xc3、\xc2的字符。
原因
对非utf-8字符序列进行 utf8::encode 或者 Encode::from_to($str, 'utf8', '...') 等,就会出现 c3 a3 c2 81... 一样的字符。 也就是说,把不是utf8编码的东西当作utf8编码来使用,就出现这个现象。
例如下面的例子。
#!/usr/bin/perl use Encode; $str1 = "あああ"; utf8::decode($str1); $str1 .= "あああ"; utf8::encode($str1); print $str1; print "----"; $str2 = "あああ"; Encode::from_to($str2, "UTF-8", "Shift_JIS"); utf8::encode($str2); print $str2;
执行结果如下:
$ perl mojibake.pl | xxd 0000000: e381 82e3 8182 e381 82c3 a3c2 81c2 82c3 ................ 0000010: a3c2 81c2 82c3 a3c2 81c2 822d 2d2d 2dc2 ...........----. 0000020: 82c2 a0c2 82c2 a0c2 82c2 a0 ...........
这里$str1是utf8字符流和字节流的混合体(实际上这是不对的),$str2是将shift-jis的字节流进行encode。其结果都会产生大量的\xc3和\xc2。
可能的原因:
- 将decode过的字符串和未decode的字符串连接在一起使用
- 对字符串连续进行两次 utf8 -> 其他编码的转换
这个题目似乎有些不太合适,因为这并不是我们常说的引用传递和值传递。但是我想提醒大家这一点,否则很容易犯错误。
问题:map语句的代码段中使用的 $_,是列表中的值本身,还是将列表中的值复制到 $_ 中?
例如,下面这段程序的运行结果是什么呢?
#!/usr/bin/perl
$,=',', $\="\n";
$a = [1,2,3];
print map { ++$_; } @$a; # (A)
print @$a; # (B)
C程序员们通常会认为map会将@$a中的每个值复制到 $_ 中,加一后返回(这里我特地用了 ++$_ 使得它返回加一之后的值), 因此(A)行输出 2,3,4 ,而(B)行输出 1,2,3 。实则不然。运行结果为
2,3,4 2,3,4
可见,并非@$a中的元素复制到$_中,而是$_本身就是@$a中的元素。而map的目的就是要改变操作数的值。 下面这个例子可以很清楚地看到这一点。
map { ++$_ } (1,2,3); # 运行时出错,++$_ 不能改变常量
类似地,grep的结果也是数组本身,返回值就是由操作数中的符合条件的元素本身组成的列表。如上例:
map { ++$_; } grep { $_ > 1 } @$a; # 运行后 $a 为 [1,3,4]
如果实在不想让map改变操作数的值,可以将操作数转成引用之后再强制转成数组:
map { ++$_; } @{[ @$a ]}; # 运行后 $a 为 [1,2,3]
当然,上面例子中 ++ 操作符很明显会改变操作数的值,因此意识到上面的问题并不困难。 不过如果是 s/// 运算符,可能就不那么明显了。
类似的情况还有函数调用时的 @_ ,它代表调用函数时的实际参数本身,而不是实际参数的拷贝。 对@_进行修改,会直接影响到实参(就像C语言里面的传指针一样)。
一般我们在定义函数时都这么写:
sub foo {
my $arg1 = shift;
}
参数多时可能会这么写:
sub foo {
my ($arg1, $arg2, $arg3) = @_;
}
这样写之后,@_的值就被赋给了$arg1、$arg2等变量,以后对$arg1、$arg2的修改不会影响到实际参数。 但如果想修改实际参数,就要这样做:
my $arg1 = \$_[0]; $$arg1 = 'Hello!'; # 调用函数时的第一个实参会变成 Hello!
Perl对YAML的支持很好,著名的Plagger就是用YAML作为配置文件的。
在Perl中读取YAML文件也很简单。常用的模块就是YAML,这是个纯Perl的实现,速度慢,但可以跨平台运行。 如果追求运行速度而不在乎平台问题,可以使用YAML::Syck和YAML::XS,两者都是C语言的实现。 YAML::Syck的C语言部分基于libsyck,而YAML::XS的C语言部分基于libyaml。 两者相比,YAML::XS稍稍快一点,而且它精确地实现了YAML标准1.1版的内容。
阅读全文 »这年头BlackBerry 7230的激活已经是老掉牙的话题了。其实原理相当简单, 无非是让BB做个到MDS服务器的连接,连上MDS之后BB就认为自己激活了, 然后就能使用cnwap正常上网了。maxpda上也有高人贴出了 自建MDS服务器进行激活的办法。
简单来说,BlackBerry 7230激活的过程如下:
- 导入ServiceBook,其中IPPP的IP地址需要指向MDS服务器。
- 在Options->Service Book中恢复删除所有内容。
- 设置Options->TCP的APN为空。
- 以上的设置是保证BlackBerry 7230能使用ServiceBook中设置的MDS服务器进行连接。
- 然后启动任意一款能不通过WAP建立网络连接的程序。QQ3可以,自带的浏览器似乎不行。
- 使用该程序建立直接的网络连接(不能走WAP)。
- 待BlackBerry 7230连接到MDS服务器之后,激活成功。
- 此时在Service Book中删除IPPP,并设置TCP的APN为cmwap,就可以用WAP上网了。

豆瓣上的介绍, 购买此书: 当当, 卓越, ChinaPub, 蔚蓝
这本书是今年二月份翻译的,两个人合作,用了一个半月的时间翻译+校对,虽然进度安排比较紧,但总算是按时交了稿,翻译的质量也还说得过去。
上周接到博文视点的消息,说这本书已经出版了,样书已经寄出来了。不过我还没收到,估计下周就能收到样书了吧。到网上查了查,发现各大书店已经开始卖了。
这本书的内容主要是面向PHP初学者的,但正如作者在前言中所述,这本书不会教你PHP和MySQL的基础知识,而是通过实际的项目进行讲解,在项目进展的过程中逐步地讲授需要的知识。个人认为这种方法要比教科书的好得多。我们在实际工作中学习也与之类似,不会有人去一步步手把手地教你怎样学习,都是直接将新人投入到项目中,在项目中磨砺。
书中介绍了八个实际可用的项目,除了基本的PHP和MySQL之外,还有较为新颖的Ajax、较高深的PEAR等内容。初学者通过这些项目可以切实地体会到PHP的方便性,而稍有基础的人则可以将书中的例子直接拿来,简单修改后即可直接放在网站上使用。当然,如果你已经是PHP高手,那么能从此书中学到的内容就有限了。
当然,本书自身也有一些不足之处,或许是因为作者精于技术但不善表达的缘故,书中一些概念的解释不太容易理解。加之我们英文水平有限,许多原文中的俗语都无法精确翻译出来,也影响了原文意思的表达。还望读者在阅读的过程中,借助Google、百度等搜索引擎,主动去查找那些难以理解的概念。另外,我们尽最大的努力保持翻译结果符合原意,但难免有疏漏之处,希望读者能够指出。
这个东西应该是很老很老很老了,不过很奇怪在国内为什么没几个人知道呢?虽然跟本blog的主题——技术——没有太大的关系,但因为实在是太常用了,就在这里贴一下吧。
原文来自Jorma Oksanen’s Origami,版权为非商用免费,但作者要求写出他的名字。另外本文的图和说明文字来自这里:A4用紙1枚で2枚収納できるCDケースをつくる。这篇文章要比原文说明得详细一些。
这两天一直在忙着做一个新的主题,暂且命名为Crystal吧。希望能带来一些新的体验。
做这个主题并没有花多大工夫,由于没有使用透明png图片,因此IE6的透明png问题就不用考虑,减少了很多工作量。而且也没有在Photoshop里打稿子而是直接写的CSS,因此页面设计上感觉有些粗糙,也是一个缺点吧。页面风格参考了awflasher的blog,在此向他表示感谢。
这两天一直在策划着做一个新的主题,一个看起来更干净些的主题。 风格么,自然还是选择Web 2.0的那些特性了。 首先要做的第一件事儿就是做个logo。
以前做logo都是用photoshop,不过做好的大图缩小之后总是达不到想要的效果,于是斗胆尝试了一下Illustrator。 在网上找了好半天Illustrator,除了一个视频教程之外就没有入门级教程了,而那个视频教程看起来会急死人。 没办法只好自己摸索了,好在Adobe的东西基本操作都差不多,弄了一个晚上也弄了个八九不离十。 在这里诚心请教各位Illustrator高人指点。
先秀一下新做的图标吧。这是大图:

将图标应用到页面上的效果。背景加了些黑色条纹。

Update:被fcicq说那个图标和网址放在一起不太协调。的确,自己也觉得图标上的衬线字体与网址的无衬线字体不般配。 但图标中若使用无衬线字体,那么一个简单的“i”字母又显得过于单薄。干脆重新设计图标吧。
阅读全文 »响应realazy的号召努力学习算法中。 这个莱文斯坦算法(Levenshtein Distance)还是比较好理解而且很实用的,放在这里做个备份吧。
原文请见 http://www.merriampark.com/ld.htm 。
什么是莱文斯坦距离?
莱文斯坦距离(LD)用于衡量两个字符串之间的相似度。 以下我们称这两个字符串分别为 s (原字符串) 和 t (目标字符串)。莱文斯坦距离被定义为''将字符串 s 变换为字符串 t 所需的删除、插入、替换操作的次数''。
例如:
- s="test", t="test", 那么 LD(s,t)=0,因为不需要做任何变换两者已相等;
- s="test", t="tent", 那么 LD(s,t)=1,因为s变换为t只需做一次替换(将"s"替换为"n")。
莱文斯坦距离越大,字符串的相似程度越低。
莱文斯坦距离以俄国科学家Vladimir Levenshtein命名,他于1965年发明了这个算法。 如果你对Levenshtein这个词的发音有问题,也可以称这个距离为编辑距离。
莱文斯坦距离被应用于以下领域:
- 拼写检查
- 语音识别
- DNA分析
- 剽窃检测
算法
- 设 s 的长度为 n,t 的长度为 m。如果 n = 0,则返回 m 并退出;如果 m=0,则返回 n 并退出。否则构建一个数组 d[0..m, 0..n]。
- 将第0行初始化为 0..n,第0列初始化为0..m。
- 依次检查 s 的每个字母(i=1..n)。
- 依次检查 t 的每个字母(j=1..m)。
- 如果 s[i]=t[j],则 cost=0;如果 s[i]!=t[j],则 cost=1。
- 将 d[i,j] 设置为以下三个值中的最小值:
- 紧邻当前格上方的格的值加一,即 d[i-1,j]+1
- 紧邻当前格左方的格的值加一,即 d[i,j-1]+1
- 当前格左上方的格的值加cost,即 d[i-1,j-1]+cost
- 重复3-6步直到循环结束。d[n,m]即为莱茵斯坦距离。
代码
代码请参考原文网站。 该网站给出了 Java、C++、Visual Basic三种语言的实现, 又在页面最下方的链接中给出了Perl、PL/SQL、TSQL、C#、Delphi、PHP 等数十种语言的实现方式。
所以我在这里就不献丑啦~。
下面是 tech.idv2.com 上推荐阅读的技术文章,按照主题分类。其中标有★的为强烈推荐阅读的文章, 通常都是原创教程,也有翻译的优秀文章。
阅读全文 »