通常HTTP状态代码是三位数字,并以1至5开头,比如200代表状态正常、404代表页面不存在、500代表服务器内部错误。当某一天我看到一个HTTP请求的状态是12007的时候,立马就傻了-_-

比如以下代码:

1
2
3
4
5
6
7
var xmlhttp = new ActiveXObject("Msxml2.Xmlhttp.6.0");
xmlhttp.open("GET", "http://testserver", true);
xmlhttp.send();
while(xmlhttp.readyState != 4) {
    WScript.Sleep(100);
}
WScript.Echo(xmlhttp.status); //12007

于是Google之,发现这是由WinINet定义的状况代码,表示服务器名称无法被解析(ERROR_INTERNET_NAME_NOT_RESOLVED)。也就是说,这个HTTP请求根本没发到服务器上,在WinINet那一层,就出错了。

类似的状态还有:

  • 12002:请求超时 (ERROR_INTERNET_TIMEOUT)
  • 12014 / 12015:无法登录FTP服务器(可能是密码错误) (ERROR_INTERNET_INCORRECT_PASSWORD / ERROR_INTERNET_LOGIN_FAILURE)
  • 12031:连接被重置 (ERROR_INTERNET_CONNECTION_RESET)

更多WinINet的错误信息可以参见KB193625.

 

简单来说,使用??@@C++()指令的组合:

@@C++()支持各种C++指令,如数学运算、字符串、指针和宏;而??用来显示运算结果。

如下图:

 

此文谨献于那段徘徊在AC、WA和TLE之间的时光……

排序,就是把一堆杂乱无章的元素,按照一定的顺序排列起来。比如以前在学校里,考完试老师发考卷的时候,会按照分数从高到低来发,于是他就需要事先把考卷按顺序排好,然后在上课的时候发掉。把考卷按分数从高到低排好的过程,就可以称为排序。

排序的方法有很多种,有一些在日常生活中可以用得到,另一些则是仅用于计算机领域,因为计算机的思考过程和人类多少有点不一样。

从一个简单的例子开始:扑克的“争上游”玩法,假设没有顺子和葫芦(即三拖一或三拖二)的规则,所以手中的牌按照牌面的大小来排序是比较合理的。发牌完成之后,我一般会一张一张地摸起面前的牌,每摸起一张牌,就把它插入手中牌的相应位置,并保证手中的牌有序。比方说,摸起第二张的时候,如果它比第一张大,就放在第一张的后面,否则就放在第一张的前面;摸起第三张的时候,就按大小放在第一张之前、第一第二张之前或者第二张之后;以此类推。这样把面前的牌都拿到手中时,手中的牌就是有序的。这种方法被称为插入排序(Insertion Sort)。(插入排序有一个进化版叫做希尔排序(Shell Sort),有兴趣的同学可以自已研究。)当然也有些人不喜欢这种方法,他们一下子把所有的牌都拿起来,这时候手里的牌是无序的,然后他们会做一个操作:(假设一共有12张牌),先在所有的牌中挑出牌面最大的一张,比如黑桃2,放在所有牌的最后面,然后在剩于的11张牌中,挑出最大的一张,比如红桃A,放在黑桃2之前,以此类推,也可以把牌都理好顺序。这种方法叫做选择排序(Selection Sort)。

而在“八十分”的玩法中,上述两种排序方法就不怎么适用了。按照八十分的规则,手中的牌通常是按照花色来摆放的,先把同花色的牌放在一起,然后再对四种花色,分别调整同花色牌的顺序(假设是需要有顺序的)。这种方法叫做桶排序(Bucket Sort),或者基数排序(Radix Sort)。每种花色可以视为一个桶,先把牌按照它的花色分别扔进这四个桶里,然后再对每个桶中的牌分别进行排序。桶排序在一定条件下可以进化成计数排序(Counting Sort),这里不多说了。

桶排序和前面的插入排序、选择排序有一点不一样。在桶排序中,所有的元素都被放到相应的桶里之后,每个桶里的排序方式,可以是不一样的。比如第一个桶中使用插入排序,第二个桶继续使用桶排序。从另一个角度来说,各个桶之间是相互独立的,排序操作可以同时进行。也就是说,如果扑克牌的数量很多,可以先把牌放进桶里,然后找多个人,每个人对一个桶进行排序,这样的并行操作可能提高效率。而在插入排序或者选择排序中,想要并行操作就相关来说复杂一点。

另一种可以进行并行操作的方法是合并排序(Merge Sort),与桶排序不同的是,合并排序先把要排序的扑克牌分成几份,每份都是没排过序的,然后分别对每一份进行排序,于是每一份内部都是有序的了(假设顺序是从小到大),最后要做的操作是,比较每一份扑克牌的第一张,选出最小的一张牌,由于每一份牌都是从小到大有序的,所以选出来的那一张一定是所有牌中最小的,把这张放到一边,再重复同样的操作选出一张最小的牌,放在刚才那张牌的上面,以此类推,就可以达到排序的效果了。不难想象,对每一份扑克牌的排序操作,是可以同时进行的。

以上几种排序方法是日常中能见到的,下面来说说仅用于计算机中的排序方法。

首先,也就是最基本的就是冒泡排序(Bubble Sort)了。对于一个长度为n的数组A,从i=0到n-2,比较A[i]和A[i+1],如果A[i]>A[i+1],则把它们交换,这样一次循环下来,A[n-1]就是数组中最大的数(证明略:P),然后重复n次,就可以把整个数组排序了。顺便复习一下算法复杂度,冒泡排序的时间复杂度是O(n²),空间复杂度为O(1)。

剩下最著名的快速排序(Quicksort)了,顾名思义,它是目前公认最快的内排序算法。(插一句,内排序是指所有需要排序的元素都存放在内存中,如果内存不足以存放所有的元素,由于外部存储器速度的制约,排序算法需要进行一定的调整。)快排的基本思想是,先在数组中取一个元素x,然后整理这个数组,使x左边的元素都不大于x,而x右边的元素都不小于x,然后再对x左右两边分别应用快排算法,最终将整个数组排序。不难发现,快排算法的好坏取决于元素x的选取,如果每次都很不巧得选了最小的元素,快排对退化成选择排序。一般来说,快排的时间复杂度为O(nlg(n)),空间复杂度是O(lg(n))。和合并排序一样,快排是分治思想一个典型定用,也就是说,它可以使用并行算法优化。

以上几种就是基础的排序方法了,还有一些由它们演化、改进出来的算法,就不多提了。

顺便复习一下复杂度,在单线程情况下,理论上最快的是桶排序(或者计数排序),可以达到O(n),但是需要使用大量的空间。一般情况下最快的是快速排序,O(nlg(n))时间,O(lg(n))空间。其它被快排BS掉的方法,多数是O(n²)时间,O(1)空间。

 

在PowerShell中,我们可以使用Function关键字来定义一个函数,比如:

1
2
3
4
5
6
Function Get-Data {
    Param (
        [int] $data = -1
    )
    return $data;
}

这个名为Get-Data的函数接收一个int类型的参数$data,直接将其返回。那么,我同时还需要一个接收string类型的Get-Data函数怎么办?方法比较奇怪,至少和传统的C++之类的语言不同。

在PowerShell中定义重载函数,需要指定参数所属的Parameter Set,如下:

1
2
3
4
5
6
7
8
9
Function global:Get-Data {
    Param (
        [Parameter(ParameterSetName="ByInt", Position=0)] [int] $intData,
        [Parameter(ParameterSetName="BySwitch", Position=0)] [switch] $boolData,
        [Parameter(ParameterSetName="ByArray", Position=0)] [string[]] $arrayData
)

Write-Host $PsCmdlet.ParameterSetName
}

不难发现,ParameterSetName指定了每个参数所属的ParameterSet,Position表示这是一个匿名参数。而$PsCmdlet.ParameterSetName表示了当前所使用的Parameter Set。用例如下:

PS > Get-Data 1
ByInt
PS > Get-Data “a”
ByArray
PS > Get-Data -boolData
BySwitch

更多关于PowerShell函数参数的介绍,可以看TechNet上的相关介绍,或者在PowerShell控制台中运行命令:help about_Functions_Advanced_Parameters

 

COM (Component Object Model) 技术中,类型库(Type Library)中记录了数据类型的元数据,用于在不同的语言环境中传递数据,也就是说类型库定义了把字节流转换成数据对象的格式。于是这也就限定了,类型库一旦公布出来,(理论上)就不能被改变,类型库的改变可能会导致现有程序出现不稳定的行为,而类型库本身,在不同的平台上也需要是一致的。

ADO (ActiveX Data Object)的类型库中,就存在这么一个不一致性,比如RecordSet.AbsolutePosition属性,它在32位的Windows中,返回的是一个32位的整型,但在64位的Windows中,它返回了一个64位的整型。不难想象,一个在32位上运行得好好的程序,在64位Windows中重新编译过之后,就可能出现整型溢出(截断)等奇怪的现象。具体的细节,可以通过OleView工具查看msado15.dll来获得。这个不一致性存在很长一段时间,但由于ADO的用户多数使用的是32位的Office(中的VBA)和VB6,所以64位上的问题迟迟没有被发现。随着64位Windows的普及,这个问题才渐渐暴露出来……

而修复的方法也比较诡异,由于ADO的类型库已经公开了很长一段时间,没办法把64位的类型库直接改成和32位一致,只能在类型库中添加新的类型,也就是说,原来类型的定义保持不变,同时新的32/64一致的类型被加入了类型库。为了鼓励用户使用新的类型,类型的名称有所改变,以_Connection类为例:

  • 旧的类型库(Windows 7 RTM及之前版本)中,_Connection的IID是{00000550-0000-0010-8000-00AA006D2EA4}
  • 新的类型库(在Windows 7 SP1中发布)中,_Connection的IID是{00001550-0000-0010-8000-00AA006D2EA4},而之前的IID被赋予了另一个名称:_Connection_Deprecated。

在应用程序中通常记录下的是IID,而不是它的名称,所以已编译好的应用程序,在Windows 7 SP1上运行完全没有问题。唯一的问题是,新的IID在之前版本的Windows中不存在,所以在Windows 7 SP1上编译的程序,在之前版本的Windows中,可能无法运行。这个问题可能表现为在创建ADO对象时,系统返回出错代码,如REGDB_E_CLASSNOTREG (0×80040154)、E_POINTER (0×80004003)、E_NOINTERFACE (0×80004002)。这个问题的解决方法也可以在那篇文章中查到,原理无非就是让在Windows 7 SP1上编译的程序,记录下老版本的IID,或者使之前版本的Windows能理解新版本的IID。

 

SQL Server提供了两种验证方式,一种是通过Windows域帐号(即Windows Authentication),另一种是通过SQL Server自带的帐号系统(SQL Authentication)。两种方式各有优缺点,比如Windows Authentication只能在加入域的机器上使用,但它更安全;相比之下在SQL Authentication中密码可能会以明文的形式保存或传输,从而降低了安全性。具体的细节这里就不多提了。

连接SQL Server数据库一般是通过连接字符串(Connection String),要使用SQL Authentication连接数据库,通常使用UID/PWD这两个关键字(ODBC中)来指定用户名和密码,(或者在OleDB中的User ID和Password);而使用Windows Authentication的话,一般是Trusted_Connection=Yes,(或者Integrated Security=SSPI)。这样就产生一个问题了,如果在连接字符串中,同时指定了UID/PWD和Trusted_Connection=Yes,会怎么样?当然,这是不推荐的做法,不过非要这么玩的话,结果也不是不可以预测的。常规Driver/Provider的实现是,只要指定了Windows Authentication,即Trusted_Connection=Yes或者Integrated Security=SSPI,不论UID/PWD的值是什么,连接方式都是Windows Authentication。

还有一个更搞的问题是,如果连接字符串中使用了数据源名称(DSN,Data Source Name),而DSN中指定使用Windows Authentication,连接字符串中使用UID/PWD,会发生什么情况?原理同上,只要指定了Windows Authentication,无论是在DSN还是在连接字符串中,这种模式就会被使用,因为它更安全……

所以说,如果发现实际使用的验证方式和预期的不一样,请检查连接字符串和所用的DSN……

PS:这个问题还有很多变种,比如在DSN中指定Trusted_Connection=Yes,而在连接字符串中指定Trusted_Connect=No,并且使用UID/PWD,会怎么样?

不要浪费脑细胞了,洗洗睡吧:P

 

终于入手了,嘿嘿……

第一个蔡司的镜头,才知道专业的镜头是有专门的人员验收并签名的……

附样张:

 

《编程方法》系列课程

  1. 《编程方法》第一课 欢迎来到CS106A
  2. 《编程方法》第二课 Karel的世界
  3. 《编程方法》第三课 Karel与Java
  4. 《编程方法》习题1
  5. 《编程方法》第四课 计算机科学发展史
  6. 《编程方法》第五课 变量

如果你喜欢这门课程,请在新开学网站上支持一下,使译者更有积极性。顺便也请支持一下《算法导论》课程,非常希望这门课能推广出去……

以下视频来自优酷:http://v.youku.com/v_show/id_XMjQzMzM1OTg0.html

以下是笔记:
[01:30] 在计算机中,变量就像一个盒子,可以存放可变的内容。
[02:00] 变量的三元素:名称、类型和值
[02:20] Java的变量可以用下划线或者字母开头,之后可以跟字母、数字、下划线。(如果没记错的话,Java的变量可以使用Unicode字符,只不过这是美国人在讲课-_-)
[04:20] 原始类型:int(范围从-20亿到+20亿)、double
[06:00] 变量的声明:类型 名称 = 值;
[07:00] “=” (等号)表示赋值:变量 = 表达式;
[14:00] 变量可以要存放类的实例
[16:00] 类的实例通过new操作符生成
[17:00] 调用方法:变量.方法();
[18:30] (貌似英文字幕有错,应该是IM,Instant Messenger,而不是I am)
[22:30] 方法和参数:变量.方法(参数1, 参数2, … );
[24:30] 变量在使用之前一定要先定义
[25:00] java.awt中预先定义的Color实例
剩下的内容都是在讲解一些图形的类如何使用,方法的定义和例子之类的,就不一一记录了,有兴趣的同学自己观摩吧:P
[39:00] 表达式的种类 变量 = 变量 操作符 变量,如a = b + c,操作符有+ – * /(整除) %(取余)

 

最新的一集Big Bang里面(S04E17),他们拿billg和Vista开涮了……以下是剧透……

 

在一个内部产品中看到这段话,看上去像一句完全没有意义的话,不过Google之后,发现在实际上完全不是这样。以下内容摘自Wikipedia

Lorem ipsum从西元15世纪开始就被广泛地使用在西方的印刷、设计领域中,在电脑排版盛行之后,这段被传统印刷产业使用几百年的无意义文字又再度流行。由于这段文字以“Lorem ipsum”起头,并且常被用于标题的测试中,所以一般称为Lorem ipsum,简称为Lipsum。

常见的Lorem ipsum起头如下:

Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.

原先大家以为这段拉丁文只是没有意义的组合,目的是让阅读者不要被文章内容所影响,而只专注于观察字型或版型,并借此填满空间。但根据美国拉丁学者Richard McClintock的研究,Lorem ipsum原来起源于西赛罗的《善恶之尽》(De finibus bonorum et malorum):

Neque porro quisquam est qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit…

(中译:无人爱苦,亦无人寻之欲之,乃因其苦…)

© 2004 - 2011 Leona+Suffusion theme by Sayontan Sinha