<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>鬼の领地 &#187; 兼容性</title>
	<atom:link href="http://blog.upsuper.org/tag/%e5%85%bc%e5%ae%b9%e6%80%a7/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.upsuper.org</link>
	<description>the place where there are some ghost appearing...</description>
	<lastBuildDate>Wed, 19 Oct 2011 13:21:47 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3</generator>
<xhtml:meta xmlns:xhtml="http://www.w3.org/1999/xhtml" name="robots" content="noindex" />
		<item>
		<title>今天写了个小小的 vc-fix</title>
		<link>http://blog.upsuper.org/write-a-little-vc-fix-today/</link>
		<comments>http://blog.upsuper.org/write-a-little-vc-fix-today/#comments</comments>
		<pubDate>Sun, 21 Mar 2010 02:39:51 +0000</pubDate>
		<dc:creator>upsuper</dc:creator>
				<category><![CDATA[探究学习]]></category>
		<category><![CDATA[C/C++/C#]]></category>
		<category><![CDATA[VC]]></category>
		<category><![CDATA[兼容性]]></category>
		<category><![CDATA[微软]]></category>
		<category><![CDATA[标准化]]></category>
		<category><![CDATA[编译器]]></category>

		<guid isPermaLink="false">http://blog.upsuper.org/?p=1119</guid>
		<description><![CDATA[我们的 C++ 老师给我布置了 C++ 的大作业来替代其他同学交的无聊题目。大作业的第一题就是完整的高精度库，并且要求使用运算符重载。因为原来用 C 写过，这次写，思路上没有太大问题，不过全部程序被我 C++ 化了，代码看过去很诡异……呃…… 我自己的机子上，自然使用 g++ 编译，不过我猜老师会要求 VC6 能够编译……我就用上次安装的 VC6 编译了一下，发现好几个错误和无数警告……其实也是我意料之中的。 其中我觉得最讨厌的莫过于 for 循环的循环变量不被视为 for 循环的局部变量这一点，导致大量变量被其认为是重复定义，这个是 VC6 和标准就语言上相去最远的问题了……不想每个都去改，麻烦死了。 在网上一找，还真找到一个简单的方法： 1 #define for if(0) ; else for 其实我也不知道这个是什么机理，不过真的很管用！ 另外一个就是 VC6 的标准库中没有 max 和 min 函数，这个也很囧，于是也自己写了一个。 以前做网页的时候经常写 ie-fix.css 文件，今天我弄 VC6 遇到这些问题，于是我也写了个 vc-fix.h 文件。M$ 真是一个需要 fix 的公司，什么时候出一个 m$-fix.com 好了…… 最后贴出我的 vc-fix.h，主要解决 VC6 下 [...]]]></description>
			<content:encoded><![CDATA[<p>我们的 C++ 老师给我布置了 C++ 的大作业来替代其他同学交的无聊题目。大作业的第一题就是完整的高精度库，并且要求使用运算符重载。因为原来用 C 写过，这次写，思路上没有太大问题，不过全部程序被我 C++ 化了，代码看过去很诡异……呃……</p>
<p>我自己的机子上，自然使用 g++ 编译，不过我猜老师会要求 VC6 能够编译……我就用<a href="http://blog.upsuper.org/a-simple-script-for-using-vc6-compiler-conveniently/">上次安装的 VC6</a> 编译了一下，发现好几个错误和无数警告……其实也是我意料之中的。<br />
<span id="more-1119"></span><br />
其中我觉得最讨厌的莫过于 for 循环的循环变量不被视为 for 循环的局部变量这一点，导致大量变量被其认为是重复定义，这个是 VC6 和标准就语言上相去最远的问题了……不想每个都去改，麻烦死了。</p>
<p>在网上一找，还真找到一个简单的方法：</p>

<div class="wp_codebox"><table><tr id="p11194"><td class="line_numbers"><pre>1
</pre></td><td class="code" id="p1119code4"><pre class="cpp" style="font-family:monospace;"><span style="color: #339900;">#define for if(0) ; else for</span></pre></td></tr></table></div>

<p>其实我也不知道这个是什么机理，不过真的很管用！</p>
<p>另外一个就是 VC6 的标准库中没有 max 和 min 函数，这个也很囧，于是也自己写了一个。</p>
<p>以前做网页的时候经常写 ie-fix.css 文件，今天我弄 VC6 遇到这些问题，于是我也写了个 vc-fix.h 文件。M$ 真是一个需要 fix 的公司，什么时候出一个 m$-fix.com 好了……</p>
<p>最后贴出我的 vc-fix.h，主要解决 VC6 下 for 循环变量的问题和 max、min 函数未定义的问题：</p>

<div class="wp_codebox"><table><tr id="p11195"><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
</pre></td><td class="code" id="p1119code5"><pre class="cpp" style="font-family:monospace;"><span style="color: #339900;">#ifndef _H_UPSUPER_VC_FIX_</span>
<span style="color: #339900;">#define _H_UPSUPER_VC_FIX_</span>
&nbsp;
<span style="color: #339900;">#ifdef _MSC_VER</span>
<span style="color: #339900;">#   if _MSC_VER &lt;= 1200</span>
<span style="color: #339900;">#       define for if (0); else for</span>
&nbsp;
<span style="color: #0000ff;">template</span> <span style="color: #000080;">&lt;</span><span style="color: #0000ff;">class</span> T<span style="color: #000080;">&gt;</span>
<span style="color: #0000ff;">inline</span> <span style="color: #0000ff;">const</span> T<span style="color: #000040;">&amp;</span> max<span style="color: #008000;">&#40;</span><span style="color: #0000ff;">const</span> T<span style="color: #000040;">&amp;</span> a, <span style="color: #0000ff;">const</span> T<span style="color: #000040;">&amp;</span> b<span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span>
    <span style="color: #0000ff;">return</span> a <span style="color: #000080;">&gt;</span> b <span style="color: #008080;">?</span> a <span style="color: #008080;">:</span> b<span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span>
&nbsp;
<span style="color: #0000ff;">template</span> <span style="color: #000080;">&lt;</span><span style="color: #0000ff;">class</span> T<span style="color: #000080;">&gt;</span>
<span style="color: #0000ff;">inline</span> <span style="color: #0000ff;">const</span> T<span style="color: #000040;">&amp;</span> min<span style="color: #008000;">&#40;</span><span style="color: #0000ff;">const</span> T<span style="color: #000040;">&amp;</span> a, <span style="color: #0000ff;">const</span> T<span style="color: #000040;">&amp;</span> b<span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span>
    <span style="color: #0000ff;">return</span> a <span style="color: #000080;">&lt;</span> b <span style="color: #008080;">?</span> a <span style="color: #008080;">:</span> b<span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span>
&nbsp;
<span style="color: #0000ff;">template</span> <span style="color: #000080;">&lt;</span><span style="color: #0000ff;">class</span> T, <span style="color: #0000ff;">class</span> Compare<span style="color: #000080;">&gt;</span>
<span style="color: #0000ff;">inline</span> <span style="color: #0000ff;">const</span> T<span style="color: #000040;">&amp;</span> max<span style="color: #008000;">&#40;</span><span style="color: #0000ff;">const</span> T<span style="color: #000040;">&amp;</span> a, <span style="color: #0000ff;">const</span> T<span style="color: #000040;">&amp;</span> b, Compare comp<span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span>
    <span style="color: #0000ff;">return</span> comp<span style="color: #008000;">&#40;</span>a, b<span style="color: #008000;">&#41;</span> <span style="color: #008080;">?</span> b <span style="color: #008080;">:</span> a<span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span>
&nbsp;
<span style="color: #0000ff;">template</span> <span style="color: #000080;">&lt;</span><span style="color: #0000ff;">class</span> T, <span style="color: #0000ff;">class</span> Compare<span style="color: #000080;">&gt;</span>
<span style="color: #0000ff;">inline</span> <span style="color: #0000ff;">const</span> T<span style="color: #000040;">&amp;</span> min<span style="color: #008000;">&#40;</span><span style="color: #0000ff;">const</span> T<span style="color: #000040;">&amp;</span> a, <span style="color: #0000ff;">const</span> T<span style="color: #000040;">&amp;</span> b, Compare comp<span style="color: #008000;">&#41;</span> <span style="color: #008000;">&#123;</span>
    <span style="color: #0000ff;">return</span> comp<span style="color: #008000;">&#40;</span>a, b<span style="color: #008000;">&#41;</span> <span style="color: #008080;">?</span> a <span style="color: #008080;">:</span> b<span style="color: #008080;">;</span>
<span style="color: #008000;">&#125;</span>
&nbsp;
<span style="color: #339900;">#   endif</span>
<span style="color: #339900;">#endif</span>
&nbsp;
<span style="color: #339900;">#endif // _H_UPSUPER_VC_FIX_</span></pre></td></tr></table></div>

<p>最后要解决的就是警告的问题。其实我很无语的是，所有的警告都是在 VC6 自己的头文件里面的……VC6 自己提示可以添加 /GX 来消除那些警告。于是我不得不再次修改我的编译脚本：</p>

<div class="wp_codebox"><table><tr id="p11196"><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
</pre></td><td class="code" id="p1119code6"><pre class="bash" style="font-family:monospace;"><span style="color: #666666; font-style: italic;">#!/bin/bash</span>
<span style="color: #666666; font-style: italic;"># - * - coding: UTF-8 - * -</span>
&nbsp;
<span style="color: #007800;">VC6_DIR</span>=<span style="color: #ff0000;">&quot;这里写上VC6的安装地址&quot;</span>
&nbsp;
<span style="color: #007800;">BIN</span>=<span style="color: #ff0000;">&quot;<span style="color: #007800;">$VC6_DIR</span>/VC98/Bin&quot;</span>
<span style="color: #7a0874; font-weight: bold;">export</span> <span style="color: #007800;">INCLUDE</span>=<span style="color: #ff0000;">&quot;<span style="color: #007800;">$VC6_DIR</span>/VC98/Include&quot;</span>
<span style="color: #7a0874; font-weight: bold;">export</span> <span style="color: #007800;">LIB</span>=<span style="color: #ff0000;">&quot;<span style="color: #007800;">$VC6_DIR</span>/VC98/Lib&quot;</span> 
&nbsp;
<span style="color: #007800;">ARGS</span>=
&nbsp;
<span style="color: #000000; font-weight: bold;">while</span> <span style="color: #7a0874; font-weight: bold;">getopts</span> <span style="color: #ff0000;">&quot;o:cG:&quot;</span> optname
<span style="color: #000000; font-weight: bold;">do</span>
    <span style="color: #000000; font-weight: bold;">case</span> <span style="color: #ff0000;">&quot;<span style="color: #007800;">$optname</span>&quot;</span> <span style="color: #000000; font-weight: bold;">in</span>
    <span style="color: #ff0000;">&quot;o&quot;</span><span style="color: #7a0874; font-weight: bold;">&#41;</span>
        <span style="color: #007800;">ARGS</span>=<span style="color: #ff0000;">&quot;<span style="color: #007800;">$ARGS</span> /o<span style="color: #007800;">$OPTARG</span>&quot;</span>
    <span style="color: #000000; font-weight: bold;">;;</span>
    <span style="color: #ff0000;">&quot;c&quot;</span><span style="color: #7a0874; font-weight: bold;">&#41;</span>
        <span style="color: #007800;">ARGS</span>=<span style="color: #ff0000;">&quot;<span style="color: #007800;">$ARGS</span> /c&quot;</span>
    <span style="color: #000000; font-weight: bold;">;;</span>
    <span style="color: #ff0000;">&quot;G&quot;</span><span style="color: #7a0874; font-weight: bold;">&#41;</span>
        <span style="color: #007800;">ARGS</span>=<span style="color: #ff0000;">&quot;<span style="color: #007800;">$ARGS</span> /G<span style="color: #007800;">$OPTARG</span>&quot;</span>
    <span style="color: #000000; font-weight: bold;">;;</span>
    <span style="color: #000000; font-weight: bold;">esac</span>
<span style="color: #000000; font-weight: bold;">done</span>
&nbsp;
wine <span style="color: #ff0000;">&quot;<span style="color: #007800;">$BIN</span>/CL.EXE&quot;</span> <span style="color: #007800;">$ARGS</span> <span style="color: #800000;">${@:$OPTIND}</span></pre></td></tr></table></div>

<p>到了最后，再补充一点点吧。VC6 发现了两个额外的错误，我觉得应该不是不兼容的问题。就是我重载的 operator++ 和 operator&#8211; 不小心忘记写 return *this; 了，g++ 没有给我任何提示的编译通过了，而 VC6 则将这个视为错误。</p>
<p>在这个问题上，我同意 VC6 的看法，虽然我怀疑可能 g++ 自己加上了那句话，不过我觉得这个应该至少给出一个警告而非什么都不说。当然，可能一个 fatal error 太过了点……</p>
<p>参考资料：</p>
<ul>
<li><a href="http://www.rugesy.cn/it/u20091012_22_34fe5127-ddfe-44fe-86f1-13afc360a794.html">VC6中FOR语句的变量声明问题</a> 回复的7楼</li>
<li><a href="http://topic.csdn.net/t/20041101/19/3511737.html">如何在程序调试阶段，判断当前的编译器是vc6的编译器还是intel8.0的编译器？ &#8211; CSDN社区</a></li>
<li><a href="http://www.cplusplus.com/reference/algorithm/max/">max &#8211; C++ Reference</a></li>
<li><a href="http://panpan.blog.51cto.com/489034/103074/">VC6.0不支持标准库函数max和min &#8211; C++技术 &#8211; 51CTO技术博客</a></li>
<li><a href="http://topic.csdn.net/t/20040909/19/3357414.html">warning C4530:C++ exception handler used, but unwind semantics are not enabled. Specify -GX &#8211; CSDN社区</a></li>
<li><a href="http://baike.baidu.com/view/1276757.html">_MSC_VER_百度百科</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://blog.upsuper.org/write-a-little-vc-fix-today/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>支持 Haiti 的小网站</title>
		<link>http://blog.upsuper.org/a-small-site-for-haiti/</link>
		<comments>http://blog.upsuper.org/a-small-site-for-haiti/#comments</comments>
		<pubDate>Sun, 31 Jan 2010 13:03:24 +0000</pubDate>
		<dc:creator>upsuper</dc:creator>
				<category><![CDATA[探究学习]]></category>
		<category><![CDATA[IE]]></category>
		<category><![CDATA[IP]]></category>
		<category><![CDATA[jQuery]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[公益]]></category>
		<category><![CDATA[兼容性]]></category>
		<category><![CDATA[地震]]></category>

		<guid isPermaLink="false">http://blog.upsuper.org/?p=987</guid>
		<description><![CDATA[17号的时候虫子向我求助，想要我帮忙做一个支持海地的小网站。大体的思路就是，在上面的放一个大地图，然后大家可以留言、上传照片什么的，然后就在地图上出现亮点，然后亮点点进去可以看到留言和照片~这个网站已经进入公测了，大家可以在这里查看：Haiti]]></description>
			<content:encoded><![CDATA[<p><a href="http://blog.upsuper.org/wp-content/uploads/2010/01/Haiti-3_1264924757767.png"><img src="http://blog.upsuper.org/wp-content/uploads/2010/01/Haiti-3_1264924757767-300x211.png" alt="" title="Haiti &lt;3_1264924757767" width="300" height="211" class="alignright size-medium wp-image-1000" /></a>17号的时候虫子向我求助，想要我帮忙做一个支持海地的小网站。大体的思路就是，在上面的放一个大地图，然后大家可以留言、上传照片什么的，然后就在地图上出现亮点，然后亮点点进去可以看到留言和照片~这个网站已经进入公测了，大家可以在这里查看：<a href="http://haiti.dnand.org/">Haiti <3</a>（话说我曾经问虫子“<3”是什么意思，她告诉我，是爱心的意思~）</p>
<p>我猜从来没做过网站的人一定会觉得这个很简单，但我觉得一点都不简单……不过似乎可以实现~这种无疑又是对我技术的一次挑战！<br />
<span id="more-987"></span><br />
一开始，我想用一种十分取巧的方式——直接用 Google Maps~探究了一段时间的 Google Maps。结果虫子要求：一是地图要暗，二是要出来的是亮点。想想，Google Maps 还是算了呃……（话说其实也不是不可以，不过实现了，很多数据从客户端走，也不大好）。不过像 Google Maps 这样极好的地图图片来源实在是太难得了！于是就直接用了~</p>
<p>首先要攻克的第一个问题是，如果我们知道来访者的经纬度，如何知道把他的点点在地图的什么位置？这是一个很神奇的问题，想想经纬度是为球面设计的，现在要把它转换到一个平面上。说来也巧，原来参与过天文软件 Stellarium 某个版本的翻译工作，正好翻译了其中被称作地图投影的部分。因为有好几个不同的投影方式，我渐渐就明白了，那个就是把球面图形映射到平面的方法！于是就找到了地图投影，经过查询，发现 Google Maps 使用的是 <a href="http://en.wikipedia.org/wiki/Mercator_projection">Mercator projection</a> (<a href="http://zh.wikipedia.org/zh-cn/%E9%BA%A5%E5%8D%A1%E6%89%98%E6%8A%95%E5%BD%B1%E6%B3%95">麦卡托投影法/墨卡托投影法/正轴等角圆柱投影</a>)。找到了投影法的名称，自然转换公式不是难事~不过这个公式看不懂……呃……算了，那些公式显然不在我现在的数学水平能够理解的范围之内，直接用好了……</p>
<p>用前面探究到的 Google Maps 的东西，写了个网页，对比了一下 Google Maps 转换的坐标和我的程序转换的坐标之间的情况，发现基本相等，有一部分会出现 1px 的差异，我就直接忽略之了~在调试这个程序的过程中，比较重要的大概就是 PHP 里面的三角函数相关的函数使用的都是弧度，而我们习惯上使用的经纬度都是角度，这样就需要一点点的转换了……好在 PHP 提供了 deg2rad 这样方便的函数~话说我的地图投影这个程序我把它单独分了一个文件出来，主要是里面定义了各种地图转换需要的常数，如果和别的功能合在一起大约看过去会比较乱……</p>
<p>下面遇到第二个重大的问题是：我们如何知道来访者所在的经纬度？！这个问题似乎比上面那个更复杂了……当然你可以直接请来访者告诉你，不过更好的方法显然是根据 IP 地址识别一下。不过说到 IP 地址的识别精度，那我也无奈了。我猜想在 IPv6 普及前，想要准确根据 IP 地址识别出位置大约是不可能的了。不过，可以接受的精度还是可以实现的~国内的 IP 数据库如纯真这样的，提供的都是一个字符串地址，那个是只能给人看的，电脑可不知道那些东西表示什么……于是就转向了国外的 IP 数据库。果然找到了些有趣的数据库，里面能包含 IP 可能对应的经度和纬度，而且还提供 CSV 下载，可好了~这里可以找到这个好东西：<a href="http://ipinfodb.com/ip_database.php">IP address geolocation SQL database :: IPInfoDB</a>。然后我需要一个可以提供 PHP 快速查找的文件。其实这个事情第一次做音乐投票系统的时候，为了限制投票 IP 在福建境内，就做过这个东西。思路也很简单：把每个 IP 段的数据变成定长的二进制数据，然后需要的时候二分查找~于是有了下面的转换用 Python 脚本：</p>

<div class="wp_codebox"><table><tr id="p9878"><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
</pre></td><td class="code" id="p987code8"><pre class="python" style="font-family:monospace;"><span style="color: #808080; font-style: italic;">#!/usr/bin/env python</span>
<span style="color: #808080; font-style: italic;"># - * - coding: UTF-8 - * -</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">csv</span>
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">struct</span>
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">sys</span>
&nbsp;
fin = <span style="color: #008000;">open</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'ip_group_city.csv'</span>, <span style="color: #483d8b;">'r'</span><span style="color: black;">&#41;</span>
c = <span style="color: #dc143c;">csv</span>.<span style="color: black;">reader</span><span style="color: black;">&#40;</span>fin, delimiter=<span style="color: #483d8b;">';'</span>, quotechar=<span style="color: #483d8b;">'&quot;'</span><span style="color: black;">&#41;</span>
fout = <span style="color: #008000;">open</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'ipdata.dat'</span>, <span style="color: #483d8b;">'wb'</span><span style="color: black;">&#41;</span>
c.<span style="color: black;">next</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
a = <span style="color: #ff4500;">0</span>
s = <span style="color: black;">&#91;</span><span style="color: black;">&#93;</span>
<span style="color: #ff7700;font-weight:bold;">for</span> r <span style="color: #ff7700;font-weight:bold;">in</span> c:
  a += <span style="color: #ff4500;">1</span>
  s.<span style="color: black;">append</span><span style="color: black;">&#40;</span><span style="color: #dc143c;">struct</span>.<span style="color: black;">pack</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'&gt;Iff2sh'</span>,
      <span style="color: #008000;">int</span><span style="color: black;">&#40;</span>r<span style="color: black;">&#91;</span><span style="color: #ff4500;">0</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span>,
      <span style="color: #008000;">float</span><span style="color: black;">&#40;</span>r<span style="color: black;">&#91;</span><span style="color: #ff4500;">7</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span>, <span style="color: #008000;">float</span><span style="color: black;">&#40;</span>r<span style="color: black;">&#91;</span><span style="color: #ff4500;">8</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span>,
      r<span style="color: black;">&#91;</span><span style="color: #ff4500;">1</span><span style="color: black;">&#93;</span>, <span style="color: #008000;">int</span><span style="color: black;">&#40;</span><span style="color: #008000;">float</span><span style="color: black;">&#40;</span>r<span style="color: black;">&#91;</span><span style="color: #ff4500;">10</span><span style="color: black;">&#93;</span> <span style="color: #ff7700;font-weight:bold;">or</span> <span style="color: #483d8b;">'0'</span><span style="color: black;">&#41;</span> <span style="color: #66cc66;">*</span> <span style="color: #ff4500;">2</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
  <span style="color: #ff7700;font-weight:bold;">if</span> a <span style="color: #66cc66;">%</span> <span style="color: #ff4500;">10000</span> == <span style="color: #ff4500;">0</span>:
    fout.<span style="color: black;">write</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">''</span>.<span style="color: black;">join</span><span style="color: black;">&#40;</span>s<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
    s = <span style="color: black;">&#91;</span><span style="color: black;">&#93;</span>
    <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #66cc66;">&gt;&gt;</span> <span style="color: #dc143c;">sys</span>.<span style="color: black;">stderr</span>, a,
fout.<span style="color: black;">write</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">''</span>.<span style="color: black;">join</span><span style="color: black;">&#40;</span>s<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
<span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #66cc66;">&gt;&gt;</span> <span style="color: #dc143c;">sys</span>.<span style="color: black;">stderr</span>, a
fin.<span style="color: black;">close</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
fout.<span style="color: black;">close</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></pre></td></tr></table></div>

<p>这样，就当获取经纬度差不多了吧~嗯~虽然那个精度实在不敢恭维……不过根据那个网站自己的数据，至少国家是不会弄错的（准确度 90%+），只是城市就不跟你保证了~（那个数据貌似显示，这个数据库中城市在中国只有 71% 左右是正确的……）。</p>
<p>最后是关于地图的最后一个问题……如何绘制？</p>
<p>经过考察，这个小网站未来要放的那个服务器是不支持 ImageMagick 的，于是只能用 GD 库了……</p>
<p>那个小点点，其实就是圆咯。于是我一开始用 imageFilledEllipse 函数在地图上画直径为 3px 的圆。不过那个的效果实在是不大行……另外一件事就是关于上传照片的问题，某些相机比较囧的都把照片方向弄在 Exif 里面……虽然 PHP 有很方便的库可以直接读取 Exif，但旋转和翻转就麻烦了……</p>
<p>关于 GD 库，有一件事我觉得很无语，那就是有好几个比较有趣的函数，如 imageAntiAlias、imageRotate 下面都写着：<br />
<blockquote>
    <strong>Note:</strong> This function is only available if PHP is compiled with the bundled version of the GD library.
</p></blockquote>
<p>于是就各种囧的不能在我自己机子上调试……目标服务器的 GD 库倒是符合条件，不过我发现其实想要通用还有一种很好的方法：在 Notes 里面找！通常不能通用的函数在 Notes 里面都有相应的通用解决方案~这次我在 Notes 里面找到了图片翻转、旋转、判断 Exif 方向、平滑绘制圆的函数~我觉得有些时候，下面的 Notes 比上面的文档要有意义的多……平滑绘制圆的函数，我为了半透明又改了一点。当然，改的不完美，也就不敢拿出来献丑了，勉强能用就是了~</p>
<p>此外，还抄来了 WordPress 里面一段创建不同大小图片和创建缩略图的代码，很好用嗯~话说，太久没写 PHP，很多东西都忘的差不多了，比如说输入的数据中有单引号会自动被 PHP escape 掉，这还让我苦恼了一下呃……</p>
<p>另外就是，设计中虫子给我提出了一个神奇的要求：跟 twitter。为了这件事，我进行了各种不和谐的活动，以了解 twitter 的 APIs……然后用了一个带缓冲的转接程序弄好了。</p>
<p>至于客户端部分，我再次使用了 jQuery，jQuery 果然是个好东西。而且为了上传，我又使用了 Uploadify。有赖于<a href="http://blog.upsuper.org/2009-recommend-platform-of-music-recruiter-for-fuzhou-no1-middle-school/">上一次做音乐征集系统</a>的经验，这次少走了不少弯路，而且大量的 IE6 的 bug 也被我巧妙地解决了~而且我发现 IE6 的某些莫名其妙的 bug （比如我在制作过程中遇到了一个 div 明明 right 是 0，却超出右边界很多）都可以通过设置 zoom: 1; 来解决……不知道 IE6 这种莫名其妙的浏览器到底是什么样 SB 的团队制作出来的。IE 曾经是带领万维网发展的，现在却成为了严重的阻碍者！用 IE 的孩子们赶快觉醒吧……我真得不想在为了 IE 花掉大把的时间调试了……</p>
<p>顺便说一下新发现的 IE6 的 bug（其实我也不知道是不是我新发现的……）：还是隐藏显示的问题。是用 AlphaImageLoader 这个 filter 的元素隐藏后显示，这个 filter 的效果会消失，也就是没用了……为了这个 bug，这次不得不在脚本中都加入了 ie-fix……而且，更严重的是，如果你在显示后再设置这个 filter，又会出现另外一个 bug：这个时候，被设置这个 filter 的元素内部的所有元素可见，但变成不可用，也就是好像点不到一样！我估计是这个 filter 变成了一个在元素内部最上层的一个东西，于是就挡住了其他所有的元素。我汗啊，IE6 的 QA 是干什么吃的啊……这个的解决办法说来也简单，另外弄一个 div，设置在同样的位置，同样的长宽，对他用那个 filter 就行了……</p>
<p>对了对了！说到 AlphaImageLoader 这个 filter，我又想起来一件事，证明了百度不适合用来搜索技术资料，至少比 Google 逊太多了：你分别在这两个搜索引擎里面输入“filter:progid:DXImageTransform.Microsoft.AlphaImageLoader”，我把结果贴出来：</p>
<div style="width: 100%; text-align: center;"><a href="http://blog.upsuper.org/wp-content/uploads/2010/01/_filterprogidDXImageTransform.Microsoft.AlphaImageLoader_1264941140183-e1264941753180.png"><img src="http://blog.upsuper.org/wp-content/uploads/2010/01/_filterprogidDXImageTransform.Microsoft.AlphaImageLoader_1264941140183-e1264941753180-190x300.png" alt="" title="百度搜索_filter:progid:DXImageTransform.Microsoft.AlphaImageLoader_1264941140183" width="190" height="300" class="alignnone size-medium wp-image-998" /></a><a href="http://blog.upsuper.org/wp-content/uploads/2010/01/filterprogidDXImageTransform.Microsoft.AlphaImageLoader-Google-搜索_1264941161008.png"><img src="http://blog.upsuper.org/wp-content/uploads/2010/01/filterprogidDXImageTransform.Microsoft.AlphaImageLoader-Google-搜索_1264941161008-163x300.png" alt="" title="filter:progid:DXImageTransform.Microsoft.AlphaImageLoader - Google 搜索_1264941161008" width="163" height="300" class="alignnone size-medium wp-image-995" /></a></div>
<p>请认真对比我的关键词和两个引擎的结果，你会发现：百度第一页没一个是我要找的，甚至连一个完整匹配的关键词都没有！难道是我的关键词是我瞎编的？不，你看 Google 的结果吧……嗯……事实胜于雄辩，百度众自重……</p>
<p>整个网站的代码，可能在经过完善以后会公布，也可能不公布。由于这次的东西不是做给自己的，所以不能完全我自己说的算了……</p>
<p>参考资料：</p>
<ul>
<li><a href="http://code.google.com/intl/zh-CN/apis/maps/">Google 地图 API &#8211; Google 代码</a></li>
<li><a href="https://groups.google.com/group/Google-Maps-API/msg/8222b18e7921f6e6">What type of map projection does Google use for Google Maps &#8211; Google Groups</a></li>
<li><a href="http://mathworld.wolfram.com/MercatorProjection.html">Mercator Projection &#8212; from Wolfram MathWorld</a></li>
<li><a href="http://www.maxmind.com/app/city_accuracy">MaxMind &#8211; GeoIP City Accuracy for Selected Countries</a></li>
<li><a href="http://apiwiki.twitter.com/">Twitter API Wiki</a> (请自备专用工具访问)</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://blog.upsuper.org/a-small-site-for-haiti/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>跨编译器的 C 语言 NaN 支持 (纠正)</title>
		<link>http://blog.upsuper.org/nan-support-for-cross-compiler-of-c/</link>
		<comments>http://blog.upsuper.org/nan-support-for-cross-compiler-of-c/#comments</comments>
		<pubDate>Mon, 18 Jan 2010 11:19:59 +0000</pubDate>
		<dc:creator>upsuper</dc:creator>
				<category><![CDATA[雕虫小技]]></category>
		<category><![CDATA[C/C++/C#]]></category>
		<category><![CDATA[VC]]></category>
		<category><![CDATA[兼容性]]></category>
		<category><![CDATA[宏]]></category>
		<category><![CDATA[微软]]></category>
		<category><![CDATA[标准化]]></category>
		<category><![CDATA[编译器]]></category>

		<guid isPermaLink="false">http://blog.upsuper.org/?p=933</guid>
		<description><![CDATA[之前的版本犯了一个重大的错误！我错了……没有经过认真的实验就贴出来…… 正文开始前，先看一个式子： 1 x != x 大家觉得，这个东西的返回可能为 true 么？事实上是可能的，只要这个 x 是 NaN，并且这个 C 编译器符合 IEEE 754 的标准。 所谓 NaN，即 Not A Number，不是一个数。这是 IEEE 754 国际浮点数运算标准当中规定的一个特殊值，这个值由于不是一个数，所以有很多奇怪的特性，比如上面这个不等于其本身。 虽然有这么个东西，而且是国际标准，不过我们也知道，这世界上总有那么些公司是不喜欢理会国际标准的，邪恶的 M$ 就是其中之一。而 Visual C++ 6.0 的 C 编译器也就“有幸”成为了少有的不能完全兼容 IEEE 754 的编译器之一。 至此，我们发现一个问题：邪恶的 M$ 的东西中，总是最垃圾的流传的最广，IE6 如此，VC6 也是如此。另外，在此声明一下，这里讲的全部是 C，不是 C++，在 C++ 中另外有一些比较符合标准的方式同时被各个编译器兼容。 OK，回归正题，既然 VC6 的编译器是个渣，可我们有的时候还是不得不让自己的代码与之兼容，于是就有了各种解决办法。 首先明确一下，我们现在需要两样东西，一是一个可以用于赋值的 NaN (在我的程序中作为一个标记值使用)，另一个是一个用于判断一个数是否为 NaN 的函数或宏。基于上面对 NaN [...]]]></description>
			<content:encoded><![CDATA[<p><strong style="color: red;">之前的版本犯了一个重大的错误！我错了……没有经过认真的实验就贴出来……</strong></p>
<p>正文开始前，先看一个式子：</p>

<div class="wp_codebox"><table><tr id="p93316"><td class="line_numbers"><pre>1
</pre></td><td class="code" id="p933code16"><pre class="c" style="font-family:monospace;">x <span style="color: #339933;">!=</span> x</pre></td></tr></table></div>

<p>大家觉得，这个东西的返回可能为 true 么？事实上是可能的，只要这个 x 是 NaN，并且这个 C 编译器符合 IEEE 754 的标准。</p>
<p>所谓 NaN，即 Not A Number，不是一个数。这是 IEEE 754 国际浮点数运算标准当中规定的一个特殊值，这个值由于不是一个数，所以有很多奇怪的特性，比如上面这个不等于其本身。</p>
<p>虽然有这么个东西，而且是国际标准，不过我们也知道，这世界上总有那么些公司是不喜欢理会国际标准的，邪恶的 M$ 就是其中之一。而 Visual C++ 6.0 的 C 编译器也就“有幸”成为了少有的不能完全兼容 IEEE 754 的编译器之一。</p>
<p>至此，我们发现一个问题：邪恶的 M$ 的东西中，总是最垃圾的流传的最广，IE6 如此，VC6 也是如此。另外，在此声明一下，这里讲的全部是 C，不是 C++，在 C++ 中另外有一些比较符合标准的方式同时被各个编译器兼容。</p>
<p>OK，回归正题，既然 VC6 的编译器是个渣，可我们有的时候还是不得不让自己的代码与之兼容，于是就有了各种解决办法。<br />
<span id="more-933"></span><br />
首先明确一下，我们现在需要两样东西，一是一个可以用于赋值的 NaN (在我的程序中作为一个标记值使用)，另一个是一个用于判断一个数是否为 NaN 的函数或宏。基于上面对 NaN 的介绍，在一个符合标准的编译器上，我们可以很容易地给出如下宏：</p>

<div class="wp_codebox"><table><tr id="p93317"><td class="line_numbers"><pre>1
2
</pre></td><td class="code" id="p933code17"><pre class="c" style="font-family:monospace;"><span style="color: #339933;">#define NaN (0.0 / 0.0)</span>
<span style="color: #339933;">#define IsNaN(x) ((x) != (x))</span></pre></td></tr></table></div>

<p>对于上面这样的 NaN 定义，VC6 不同寻常的会发生编译错误：</p>

<div class="wp_codebox"><table><tr id="p93318"><td class="line_numbers"><pre>1
</pre></td><td class="code" id="p933code18"><pre class="text" style="font-family:monospace;">error C2124: divide or mod by zero</pre></td></tr></table></div>

<p>可能也有人会问，难道除 0 不应该是错误么？事实上 IEEE 754 里面就是规定 0.0 / 0.0 = NaN。这里我给出一个我个人的理解：学过高等数学的人大约都会知道，一个无穷小除以一个无穷小，他们的极限可能是无穷大或任何实数，而由于浮点数的精度限制，这里的 0 可能不是真的 0，而是一个很小很小极其趋近于 0 的数，类似无穷小，于是有这样的规定吧。再来看看 IsNaN，这个宏就更无敌了，VC6 的编译器会自作聪明的直接把它优化为 false……</p>
<p>那么对于 VC6 我们该怎么办呢？</p>
<p>查阅了许多资料，最后我们在 MSDN 中翻出了一份年代久远的文档：<a href="http://msdn.microsoft.com/en-us/library/aa298428%28VS.60%29.aspx">_isnan</a>。这里的 _isnan 是 VC6 在 float.h 中定义的一个函数，用于校验一个数是否为 NaN。现在的问题就剩下，我们如何生成 NaN，以及如何判断编译器呢？</p>
<p>那么我们来思考一下，除了用零除零，还有什么方法可以生成 NaN 呢？翻看了 <a href="http://www.eecs.berkeley.edu/~wkahan/ieee754status/IEEE754.PDF">IEEE754 标准文档</a>，看到了开平方一个负数也应该是 NaN。这一点应该很好理解，开平方一个负数应该得到一个虚数，而虚数不是一个实数，所以也就 Not a Number 了~于是最后形成了下面一段预处理指令：</p>

<div class="wp_codebox"><table><tr id="p93319"><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
</pre></td><td class="code" id="p933code19"><pre class="c" style="font-family:monospace;"><span style="color: #339933;">#ifdef _FPCLASS_SNAN</span>
<span style="color: #339933;">#include &lt;math.h&gt;</span>
<span style="color: #339933;">#define NaN sqrt(-1)</span>
<span style="color: #339933;">#define IsNaN(x) _isnan(x)</span>
<span style="color: #339933;">#else</span>
<span style="color: #339933;">#define NaN (0.0 / 0.0)</span>
<span style="color: #339933;">#define IsNaN(x) ((x) != (x))</span>
<span style="color: #339933;">#endif</span></pre></td></tr></table></div>

<p>虽然调用 sqrt 可能有效率问题，而且额外的需要引用 math 头文件，不过还算几乎完美地解决了 NaN 跨编译器的兼容性问题~事实证明，这段代码可以通过 VC6 的编译器正确地编译并执行。</p>
<p>另外说一点东西，就是如何在 Linux 下用 VC6 的编译器呢？这个问题我想我解决的其实是不完美的，不过也留在这里吧。</p>
<p>首先我下载了一个免安装版的 VC6，然后解压。接着找到了 VC6/VC98/Bin 目录，里面有非常著名的 VC6 编译器的主程序 CL.EXE 以及连接器 LINK.EXE。对于编译器这种纯运算的程序，wine 的兼容性还是比较优美的。不过需要一个额外的 dll 文件支持：mspdb60.dll，这个文件<a href="http://www.dll-files.com/dllindex/dll-files.shtml?mspdb60">很容易载到</a>，解压到 wine 的系统目录 (~/.wine/drive_c/windows/system32) 就可以了。</p>
<p>接下去就是如何编译了……我的方法比较老土，是将待编译的文件复制到编译器目录，然后执行类似下面命令：</p>

<div class="wp_codebox"><table><tr id="p93320"><td class="line_numbers"><pre>1
</pre></td><td class="code" id="p933code20"><pre class="bash" style="font-family:monospace;">wine CL.EXE 源文件.c <span style="color: #000000; font-weight: bold;">/</span>I..<span style="color: #000000; font-weight: bold;">/</span>Include <span style="color: #000000; font-weight: bold;">/</span>o可执行文件.exe <span style="color: #000000; font-weight: bold;">/</span><span style="color: #c20cb9; font-weight: bold;">link</span> <span style="color: #000000; font-weight: bold;">/</span>LIBPATH:..<span style="color: #000000; font-weight: bold;">/</span>Lib</pre></td></tr></table></div>

<p>其中“源文件.c”和“可执行文件.exe”是很容易理解的，“/I../Include”是使编译器能知道 include 的文件应该去哪里找，而“/link”表示后面的部分是连接器参数，“/LIBPATH:../Lib”就是表示静态链接库的地址了~</p>
<p>最后再说说如何将 GCC 可以编译的程序移植到 VC6 中。GCC 实现了 C99 标准，但 VC6 因为出现在 1998 年 (怎么正好早一年……不过就算是 99 年出也未必会支持 C99 就是了……)，所以不支持 C99，于是所有的变量必须在函数最前面声明，不能混入代码内部。此外，在 VC6 当中，void 指针是不能进行运算的。还有就是不能用“//”开头的行注释，必须使用块注释。这是我移植过程中遇到的主要麻烦。</p>
<p>事实上，在 GCC 当中，可以验证大多数 C89 的限制，只要在编译的时候用如下语句：</p>

<div class="wp_codebox"><table><tr id="p93321"><td class="line_numbers"><pre>1
</pre></td><td class="code" id="p933code21"><pre class="bash" style="font-family:monospace;"><span style="color: #c20cb9; font-weight: bold;">gcc</span> <span style="color: #660033;">-ansi</span> <span style="color: #660033;">-pedantic</span> <span style="color: #660033;">-o</span> 可执行文件 源文件.c</pre></td></tr></table></div>

<p>只要把其中所有的 warning 全部消灭掉就可以啦~</p>
<p>当然，最好的方法莫过于在 VC6 的编译器中直接测试了……</p>
<p>最后最后，M$ 实在是……唉……这个世界上不明真相的孩子果然是占大多数的……</p>
<hr />
<p>关于修改的部分：之前的版本错误的使用 _FPCLASS_SNAN 这一校验函数 _fpclass 返回值当作 NaN 来使用。既然查到了这个，这里也顺便说一下这个东西吧。在 VC 的 float.h 库里面有 _fpclass 这个函数，用于检验一个浮点数的类型，可能的返回值都在 float.h 里面，如下：</p>

<div class="wp_codebox"><table><tr id="p93322"><td class="line_numbers"><pre>1
2
3
4
5
6
7
8
9
10
</pre></td><td class="code" id="p933code22"><pre class="c" style="font-family:monospace;"><span style="color: #339933;">#define _FPCLASS_SNAN   0x0001  /* signaling NaN */</span>
<span style="color: #339933;">#define _FPCLASS_QNAN   0x0002  /* quiet NaN */</span>
<span style="color: #339933;">#define _FPCLASS_NINF   0x0004  /* negative infinity */</span>
<span style="color: #339933;">#define _FPCLASS_NN     0x0008  /* negative normal */</span>
<span style="color: #339933;">#define _FPCLASS_ND     0x0010  /* negative denormal */</span>
<span style="color: #339933;">#define _FPCLASS_NZ     0x0020  /* -0 */</span>
<span style="color: #339933;">#define _FPCLASS_PZ     0x0040  /* +0 */</span>
<span style="color: #339933;">#define _FPCLASS_PD     0x0080  /* positive denormal */</span>
<span style="color: #339933;">#define _FPCLASS_PN     0x0100  /* positive normal */</span>
<span style="color: #339933;">#define _FPCLASS_PINF   0x0200  /* positive infinity */</span></pre></td></tr></table></div>

]]></content:encoded>
			<wfw:commentRss>http://blog.upsuper.org/nan-support-for-cross-compiler-of-c/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
	</channel>
</rss>

