Dream for future
语言
DWORD是无符号的
Jul 13th
今天刚知道。一直都以为DWORD就是long,没想到它是unsigned long。
具体定义在WinDef.h中:
typedef unsigned long DWORD;
更多的Windows数据类型可以在这里查。
强大的批处理 (4) 使用数组
Jun 17th
批处理指令中并没有原生支持数组,但这不代表不能模拟出来。
来看下面的代码:
SET Obj_Length=2 SET Obj[0].Name=Test1 SET Obj[0].Value=Hello World SET Obj[1].Name=Test2 SET Obj[1].Value=blahblah
这样就定义了一个数组了,而且是结构体的数组。
在需要取值的时候,可以这么玩:
SET Obj_Index=0
:LoopStart
IF %Obj_Index% EQU %Obj_Length% GOTO :EOF
SET Obj_Current.Name=0
SET Obj_Current.Value=0
FOR /F "usebackq delims==. tokens=1-3" %%I IN (`SET Obj[%Obj_Index%]`) DO (
SET Obj_Current.%%J=%%K
)
ECHO Name = %Obj_Current.Name%
ECHO Value = %Obj_Current.Value%
ECHO.
SET /A Obj_Index=%Obj_Index% + 1
GOTO LoopStart
输出结果:
Name = Test1
Value = Hello World
Name = Test2
Value = blahblah
怎么样,很不错吧~~
在C#中使用@声明变量 – 逐字标识符
Apr 16th
在C#中,@符号不仅可以加在字符串常量之前,使字符串不作转义之用,还可以加在变量名之前,使变量名与关键字不冲突,这种用法称为“逐字标识符”。请看下面的代码:
class @class
{
public static void @static(bool @bool) {
if (@bool)
System.Console.WriteLine("true");
else
System.Console.WriteLine("false");
}
}
这里使用到@的地方有三处,@class,@static和@bool,如果不加@的话,他们都是关键字,编译就会报错。加了@之后,他们和普通的变量名没有区别了,可以正常使用。当然@也可以加在非关键字之前,比如:
static void Test(string @str)
{
Console.WriteLine(str);
}
这样@就一点效果也没有,@str等价于str。
当然,使用关键字作为变量名是非常不推荐的,除非特殊情况,比如和其它语言交互,一般不鼓励使用。
强大的批处理 (3) 判断目录在%Path%中
Mar 25th
貌似没有很优美的做法,只能把%Path%按分号分割,然后一段一段地比较。
:InPath [In]Path [Out]0/1
SETLOCAL
SET LocalPathCopy=%PATH%
SET Result=0
:WHILE
IF "%LocalPathCopy%" == "" GOTO WEND
FOR /F "delims=;" %%I IN ("%LocalPathCopy%") DO (
IF /I "%%~I" == "%~1" (
SET Result=1
GOTO WEND
)
)
FOR /F "delims=; tokens=1,*" %%I IN ("%LocalPathCopy%") DO (
SET LocalPathCopy=%%~J
)
GOTO WHILE
:WEND
:InPathRet
ENDLOCAL & SET %2=%Result% & GOTO :EOF
使用方法:
SET x=C:\Windows Call :InPath %x% Result IF %Result% == 0 SET Path=%Path%;%x%
在命令行中以管理员权限启用应用程序
Mar 21st
自从Vista带来了UAC之后,应用程序就变成了两种,有管理员权限的,和没有管理员权限的。一些老的应用程序会莫名其妙地出错,这时候就要考虑右击应用程序,然后“以管理员身份运行”。这还不是什么大问题,exe文件的右键菜单里都会有这个,但是对于一些脚本文件(cmd, js一类)来说,就没那么方便了。通常需要重新开一个带管理员权限的命令行窗口,然后打很多cd回到刚的文件夹,然后再运行脚本,相当麻烦。
搜了一下,找到一个解决办法。把下面的代码保存为Elevate.js:
var command = WScript.Arguments.Item(0);
var argument = "";
for (var i = 0; i < WScript.Arguments.Count(); ++i){
argument += WScript.Arguments.Item(i) + " ";
}
try{
var shellapp = new ActiveXObject("Shell.Application");
shellapp.ShellExecute(command, argument, null, "runas", 1);
}
catch(e){
WScript.Echo("Something wrong: " + e.description);
}
以后要以管理员身份运行程序的时候,只要输入“Elevate <exefile> <arguments>”就可以了,比如“Elevate cmd /k”。
当然,这个逃不过UAC的检查,还是会有一个对话框弹出来要点“确定”的。
强大的批处理 (2) Fibonacci函数
Mar 4th
小无聊一下,不过真的很强大……
@ECHO OFF
SETLOCAL
SET X=10
CALL :Fib %X% Y
ECHO Fib^(%X%^)=%Y%
GOTO :EOF
:Fib [In]X [Out]Result
SETLOCAL
SET A=%1
SET D=1
SET E=0
IF %A% LEQ 1 (
GOTO FibRet
)
SET /A B=%A%-1
SET /A C=%A%-2
CALL :Fib %B% D
CALL :Fib %C% E
:FibRet
ENDLOCAL & SET /A %2=%D%+%E% & GOTO :EOF
输出是“Fib(10)=89”
强大的批处理 (1) 字符串截取
Mar 4th
获取当前的小时数:
@ECHO OFF
SET Hour=%TIME:~0,2%
IF %Hour% GTR 12 (
ECHO Afternoon
) ELSE (
ECHO Morning
)
打印Windows的版本:
@ECHO OFF
FOR /F "tokens=1,2,3,4" %%I IN ('VER') DO (
SET Ver_Temp=%%L
)
SET Ver_Major=%Ver_Temp:~0,1%
SET Ver_Minor=%Ver_Temp:~2,1%
SET Ver_Build=%Ver_Temp:~-5,4%
ECHO Windows Version:
ECHO Major %Ver_Major%
ECHO Major %Ver_Minor%
ECHO Build %Ver_Build%
C#中重载相等运算符
Jan 18th
运算符重载一直是一个很诡异事情,因为在写代码的时候,不知道某个运算符有没有被重载过。在C++里面,运算符重载可以写在类的外面,当intellisense不工作的时候,找到一个运算符的重载函数是一件相当头疼的事情。这个问题在C#中改善了不少,因为运算符重载一定要写在类内,而且intellisense很强大。不过另一个问题又产生了……
先来看C++中的“==”重载:
struct A{
int x;
int y;
};
inline
bool operator == (const A& a, const A& b){
return a.x == b.x && a.y == b.y;
}
上面这段代码中,由于声明的关系,a和b永远不可能为NULL,所以直接调用a.x和b.x是没有问题的。
而在C#中:
struct A
{
public int x, y;
public static bool operator ==(A a, A b)
{
return a.x == b.x && a.y == b.y;
}
public static bool operator !=(A a, A b)
{
return !(a == b);
}
}
这段代码是没问题的,因为A是struct,而struct不可能为null。但换成class就有问题了,比如:
class A
{
public int x, y;
public static bool operator ==(A a, A b)
{
if (a == null && b == null)
{
return true;
}
if (a == null || b == null)
{
return false;
}
return a.x == b.x && a.y == b.y;
}
public static bool operator !=(A a, A b)
{
return !(a == b);
}
}
由于reference type可以为null,所以要先检查a和b是不是null,但是“a == null”这一句又会去调用“operator ==”,于是就无限递归下去了……想了很久都没想出来变通的方法,而且System.String的实现也很诡异:
public static bool operator ==(string a, string b)
{
return Equals(a, b);
}
public static bool Equals(string a, string b)
{
return ((a == b) || (((a != null) && (b != null)) && EqualsHelper(a, b)));
}
看上去也会无限递归的(Reflector出来的,不一定准),很神奇……
虽然对于Referece type不建议重载==,但是不建议并不代表不能用吧,这个设计太挫了……
Javascript学习心得
May 7th
这几天做Ajax,顺便研究了一下Javascript,发现以前对Javascript是完全不了解=.=
总结如下(以下简称Js):
1、Js中没有Class,只有Function,一个Function可以看成一个类的构造函数,new Function即new Class。每个Function有一个对象prototype,new Function的时候,自动把这个Function的prototype复制到新的对象中。
2、Function中可以使用this关键字,指代的是包含这个Function的类,不过this是动态绑定的,比如
var x = {
value:"x",
a:function(){
alert(this.value);
}
};
var y = {
value:"y",
a:x.a
};
y.a();
运行结果是y。这种模式在Lua中见过,如果要让运行结果是x,要对x.a做一个Binder,显示指定this为x,并调用a.x.apply(obj, …)。
3、Js中没有继承,要实现继承的功能,有N种比较猥琐的方法。一种是在新的对象中放一个base指针,指向它的父类。还有一种是复制prototype。不过看上去都很恶心。以前看过Lua中有一种继承的方法是做一个索引表,调用函数的时候查找它父类的函数,不过Js不支持运算符重载=.=
4、Js中唯一的网络组件是XMLHttpRequest,在IE7和Firefox 中可用,IE6要用new ActiveXObject(“Msxml2.XMLHTTP”)。XMLHttpRequest可以产生一个异步通讯的线程,是Ajax的主要工具之一。线程的管理依赖于浏览器,具体的说明可以看Ray的一篇文章。
5、Js中数值0等价于false,也就是if (0){}等价于if (false){},在写Array.Contains的时候总算明白了为什么Lua中0不等价于false,因为Array.Contains可以返回null表示没有找到,而调用的时候可以写If (obj.Contains(val)){},而不用写if (obj.Contains(val)!=null){},但是Js中就只有写后一种了=.=
6、Js中有delete关键字,但不是用来进行垃圾回收的,只能用来在类中删除一个元素。垃圾回收是自动的。
7、Js中有很多保留字(因为ECMA规范的缘故),比如class,IE7会认为var class=0是错误而停止执行。
8、Firefox中的String重载了[]运算符,等价于charAt,但这不是标准。
9、Js和Java同宗,N多相似的地方,比如Date中月份从0开始,0表示一月;String是不可变类;函数的命名和Java几乎完全相同。
10、Firefox下不允许修改Object.prototype,而IE下可以。
先写到这,以后再补……
简体中文
English