2009年5月7日星期四

JavaScript判断输入框是否为浮点数

今天遇到了这样一个问题,我们在进行验证一个文本输入框中输入的数据是不是有效的浮点数时,刚开始准备用 if(!(parseFloat(sNumber)))或者if(isNaN(parseFloat(sNumber)))进行判断,后来却发现这个parseFloat竟然在你输入的sNumber中有数字,也有非法字符的时候,将其中的有效数字留下来,其余的全部丢掉,这样它返回的就不再是NaN了,这样我的判断就是错误的了,所以不得不自己去写一个function来判断输入的是否为浮点数。

最开始想的方法就是用正则表达式,自己写了一个简单的测试浮点数的正则表达式:如下


function checkFloat(str)
{
var regexFloat = /^(\-){0,1}[0-9]{1,5}\.{0,1}[0-9]+$/;
if(regexFloat.test(str))
{
alert('true');
return true;
}
else
{
alert('false');
return false;
}
}
checkFloat("-234.5");
checkFloat("0.3423");
checkFloat("1234");
checkFloat("--1234");
checkFloat("12.3.4");


以上只是一个最最初步的检测,实际上还是有很多问题的,比如“001”这种有多余零的情况会被判断正确,这个就很不爽了,必须又加几条if语句进行判断,比较不爽。实验室另外一位同学采用了String对象中的一些方法也解决这个判断Float的类型,我觉得还是有点过于复杂。这是突然想骂骂这个parseFloat,它为什么要这样做呢,有非法字符返回个NaN岂不是很好的事情吗,突然灵光一亮,我想到一个更简单的方法。
既然parseFloat会丢弃其中的一部分不合法字符,那我们何不就利用它的这个性质进行Float类型的判断呢? 代码如下:


function checkFloat(sNumber)
{
var nFloatNum = parseFloat(sNumber);
if(nFloatNum.toString() != sNumber)
{
return false;
}
else
{
return true;
}
}



至此问题比较简单的解决了。原来有时候一个方法的“缺点”也可以好好利用。^_^

……

[阅读全文]

2009年4月25日星期六

xsl递归

昨天晚上我们项目组的一个同学希望我将我们的配置页面的列表修改一下,他提出了两个要求:

1、在传给我们一些字符串时,要是不传东西我们,我们列表中要显示未绑定,传的字符串过长时,要显示其中的一部分,后面内容省略。

2、有一个列表的显示值的底层本应发字符串给我们的,他们却是发一个ulong的数字给我,其中从最低位到从左往右第四位,分别表示的一种状态,这样一组合就有16种情况,要我们上层去将数字转化为相应的页面显示。

第一个问题比较简单,我们在写自定义列的时候,用xpath的一个函数string-length去获取字符串的长度,然后再用<xsl:choose>判断一下就可以了,代码如下:

<xsl:choose>

<xsl:when test="string-length($str) > 14"><!--$str可以使xpath路径-->

<xsl:value-of select="substring($str,1,14)"/>

<xsl:value-of select="'...'"/>

</xsl:when>
<xsl:when test="string-length($str) = 0">

<xsl:value-of select="xpath"/>

</xsl:when>

<xsl:otherwise>

<xsl:value-of select="$str"/>

</xsl:otherwise>

</xsl:choose>


第二个问题就比较麻烦了,(要是用C,就相当简单了,可是对于我们页面上来说,还是不那么容易的)看到第二个问题,我想到的方法有两种,第一种,用js获取值,然后进行转化,在动态的赋给每一个table中的那一列数据。用js写的话,会比较容易,基本语法和C一样,在页面加载后调用的初始化函数中去初始化那些显示值,这样首先用js去存储这么多数据就是一种浪费空间,然后就是对于行数比较多的,这个也会降低速度。那么就自然的引出了第二个方法,用xsl,结合xpath的方法和它的一些逻辑函数,这个实际上也是包含两种方法的,一是用xml将16种情况的显示值全部列出来,然后到时候通过取集合中的元素的方法就可以了,我个人不太喜欢这样做,因为不通用,要是有一个状态位数更多的情况就又得修改。于是我选择的是让xml存储的是每一位所代表的状态字符,然后通过判断传上来的ulong数据,对这些数据进行组装。

所以,一开始我就决定了用最后一种方法,今天刚调试出来,我是怎么做的呢?


我刚开始试过用<xsl:variable>去存储那些ulong值,然后通过修改变量的值来处理的方法,空口说不好,写出下段代码帮助理解:

<xsl:variabe name="str" select="''"/><!--str用于存储转化后的字符-->

<xsl:variable name="num" select="."/><!--用num变量存储那个ulong型数的值-->

(xsl和xpath中没有移位这种操作)下面的逻辑用伪码表示

if($num-8>0){$num = $num-8; $str = $str+"相应字符串"}

if($num-4>0){$num = $num-4; $str = $str+"相应字符串"}

if($num-2>0){$num = $num-2; $str = $str+"相应字符串"}

if($num-1>0){$num = $num-1; $str = $str+"相应字符串"}

至此,str就保存了完整的转换后的字符串了。

想的很轻松,写成了之后,页面什么显示都没有,在调试了不少时间,发现了原来xsl中的变量是不允许改变的。这个实在是有点“没人性”,好端端的变量名,只允许一次赋值,又不能够改变,这算什么变量嘛,干脆叫宏、常量得了,^_^

这下我就晕掉了,变量竟然不能够改变,我们如何处理呢,岂不就是宣告此路不通,这时,想到了强大的call-template,apply-templates这些类似函数的东东。

竟然通过变量改变搞不定,我也来学学我们这个项目中随处可见的call-template,
apply-templates这样的东西,用递归来帮助解决问题。

先把调用代码的主体copy看看

<xsl:variable name="str">

<xsl:call-template name="findGlobleString">

<xsl:with-param name="num" select="$num"/><!--要转化的ulong型的数字-->

<xsl:with-param name="step" select="'8'"/> <!--解析开始的最高位,二进制"1000”-->

<xsl:with-param name="maxstep" select="'16'"/><!--能够解析数字的上限+1-->

</xsl:call-template>

</xsl:variable>

下面我将template用伪码写出来,便于理解,更加简洁

<xsl:template name="findGlobleString">

<xsl:param name="num"/>

<xsl:param name="step"/>

<xsl:param name="maxstep"/>


/*伪码逻辑 begin*/

if($num >= $step and $num < $maxstep)//如果num的step位上为1

{

if($step == $maxstep/2) 打印相应字符串


else if($step == $maxstep/4) 打印相应字符串

...


else if($step == 0) 输出空


if($step / 2 >0)//如果step不在最低位,继续调用自己

{

/*调用自己

传参为 1.$num-$step作为num参数传入

2.$step/2 作为step参数传入

3.$maxstep 作为maxstep参数传入

*/

}

else//step已在最低位,解析结束

{

打印空

}

}

else if($num =0 or $step =0)//解析结束标志

{

打印空

}

else if($step < $maxstep and $step>1 and $num<$maxstep)//num的$step位上数字为0,且不是最低位,$step右移一位,再次调用自己解析

{


/*调用自己

传参为 1.$num作为num参数传入

2.$step/2 作为step参数传入

3.$maxstep 作为maxstep参数传入

*/

}

else

{

打印错误信息

}


/*伪码逻辑 end*/



</xsl:template>

这样执行完这些代码之后str这个variable种存储的就是我们想要转化的字符串了。同时这个template的可扩展性也是较强的,对于位数更多的情况,直接将传入的step参数和maxstep参数做相应的修改就可以了。

上面我写的这些逻辑符都是xsl中有的,这里就不贴出源码了,要转化很容易。自己对递归也没多少认识,有更好办法的,欢迎指教!

2009-04-25


……

[阅读全文]

2009年4月10日星期五

强大的二进制数

今天实验室轮到我来发“每日一招”,(ps:解释下,这是我们项目组的一个内部活动,用来让大家在工作中将自己各方面好的经验和方法共享,同时也能活跃实验室的气氛),想了一会儿找不到什么好的东西,就将我当初在电视上看到的李开复在面试清华北大的两名计算机专业的学生时问的一个问题,如下:

有1000个苹果,现在给你十个箱子,将所有的苹果都装到箱子中,假设每个箱子都是可以装任意多的苹果的,现在要你提出一种装苹果的方案,使得要任意个苹果,都可以用其中的几个箱子搭配给出!

实验室的童鞋们果然都很聪明,很多人都在十分钟内就给出了正确的答案。同时有另外一个同学也由此引出了第二个问题:

一个奴隶主有1000坛酒,其中有1坛被人投了毒(很慢性的毒)。现在他要用他的奴隶来试毒,请问用怎么样的方法可以用尽量少的奴隶并且最少的时间把有毒的那坛找出来?

第一个问题的答案很简单,估计大部分人也能够很轻松的解决,就是让箱子装苹果的个数依次为1,2,4,8,......256, 489,大概原理就是1000个苹果用二进制表示的话是有十位,511用2进制表示是9个1,这样如果我们用前九个箱子装上2进制前九位每位数字代表的大小,我们就可以用其中的组合配出任意的一个<=511 的数了,再将最后的苹果数装入到最后的一个箱子中,如果需要的苹果数大于511而小于1000,就可以直接先将最后一个箱子的苹果给出,这样剩下来需要的苹果数就必然在511内了,这样就又可以由前面九个箱子组合配出。

第二个问题我刚开始始终不明白,只知道这题肯定与第一题极为相似,但是想了很久都不会(sigh!),最终还是请教他才得以解决。不得不承认二进制数是多么强大。题目是这样解决的:
首先呢,对1000坛酒编号,二进制号,十位即可,如“1010111010”,全部表示成十位,不足的补零。然后拿出十个奴隶,让第一个奴隶去喝把所有的编号右边第一位为0的酒喝一口,这样如果他死了说明毒酒编号的最后一位为0,否则为1;然后让第二个奴隶去将编号右边第二位为0的酒喝一口,这样就又可以确定毒酒右边第二位的数字,依次下去,就可以确定毒酒的编号了,看到没有,当我们这样分配后,可以在发现一个奴隶毒发身亡后就确定毒酒的编号了,效率够强大吧!
二进制数果真是强大!
……

[阅读全文]

两道程序员面试题

1.能否不利用额外的辅助空间,将两个int型数交换顺序?

2.现有两根不均匀的香,它们每根都能燃烧整整一个小时,现在给你两跟这样的香,你能用它确定15分钟的间隔吗?

上次跟一个同学一起去吃饭,他问了我以上两个传说中是面试题的问题,觉得很有意思!不过可惜的是这两题是在他的提示下才搞定了。

第一题相对容易一点:通过下面三步操作就可以搞定了
a = a + b;
b = a - b;
a = a - b;
但是这个我感觉是有点问题的,因为要是a,b相加正好超过了int的上限,岂不是出现数据丢失,何谈两者交换呢?

第二题有点像脑筋急转弯,我费了好大劲都想不出来,在同学提醒了我一炷香两头一起烧就能确定半个小时了,我才恍然大悟。想了一会,便给出了答案:先将一炷香两头同时点燃,这是也将另一根香的一头点燃,在第一根香烧完后,就只有确定了第二根香还能烧半个小时了,这时将它的另外一边也点燃,它就只能支持15分钟了。

两道题其实都比较简单,但是需要脑袋要灵活,善于跳出常规的思路!^_^
……

[阅读全文]

2009年3月25日星期三

做“超级毕业生”

今天中午上了一下喻信,突然看到了《超级毕业生》这篇帖子,下面还有一篇《女毕业生的死亡日记》,这两篇文章是《南方周末》上报道的,好久没上喻信,趁着中午还有点时间,就将这两篇帖子读完了,读第一篇,我几乎是张着嘴巴读完的,第二篇却几乎落泪,同样是大学生,前后的反差引起了我的深思。

可以这样说,义乌商学院的教育可以深深的打击了我们当代的这些还自以为是在重点大学的学生,“一个高职学生今年顶40个本科生,明天还会顶80个!”,这样“震撼人心”的话语让我不禁打了一个寒颤。但是他们确确实实做到了,贾少华这位副院长真的是个好院士,不管他的举措是否有些过于激进,但我们从中是可以看出他是的的确确为当代的大学生着想的,而且也确确实实取得了相当不错的效果,诚然,很多人会说,并不是每个人都适合去淘宝开店,怎么能够那么偏激的大肆鼓励学生去淘宝创业,呼吁“淘宝改变命运”呢?但是你若是不试试,你如何知道你不适合,一个根本就没有尝试过某件事的人,是根本不会真正对它有体会的,偏激一点说,像这样的人根本就没有资格去评价别人!何况这样也可以让一些人了解到自己并不适合这个方向,对自己的未来也就多了一分明确,更重要的是这样让大批的大学生能够摆脱网游的困扰,真正的将自己的青春为自己的未来去挥洒,就凭这一点就可以说明这个方法至少不是错的!

现在的大学年年扩招,重点大学的学生出去找工作照样是很难,如何真正的让大学生能够适应这个竞争日益激烈的社会,确实是一个非常严重的问题。虽然大学现在不断扩招,但是师资力量却是不敢让人恭维,一些老师上课几乎只能靠点名来保持到课率,这样难道都是我们学生贪玩,不想去上课吗?肯定是有一部分学生比较堕落,在大学这种相对自由的环境下管不住自己,但另一方面有可能是老师本身讲课质量有问题,也有可能是,课本陈旧的知识与现实严重的脱节,导致大家对这样的课产生了天然的反感,学了又如何,在考试中能取得更好的成绩?考前突击个一两周貌似就可以达到不错的效果了,那我又何必去听课呢?再者,即使考试取得了好的成绩又如何呢?可能成绩相当不错的学生,能够拿到学校的这个奖学金那个奖学金,不错不错,但是这是在学校,一天你走出了学校又会怎样呢?你还能靠你记得的那几个公式让公司聘用你吗?可能我说的比较偏激。但是我确实也是看到大学与我刚进大学时想象中的巨大反差。以前以为上了大学就可以真正学到许许多多实用的东西,十分兴奋!可是结果呢?等待我的还是计算电压电流,求电场磁场。而且每学期都会有一大堆的书学完,过了就忘了!眼睁睁的看着自己与现实社会的差距越来越远,很是痛苦!

我从来没有鄙视过读书,我也知道要真正的实践的好是需要一定的理论基础的,但是何必要在大学里面把所有的理论疯狂的往学生头上灌呢,大学不比高中,我们需要的不再是理论知识本身,我们更需要的是快速学习新知识的能力,和将知识运用于实践的能力,如何增强我们的快速学习能力,如何将知识与理论结合,三个字,多实践。在实践中,我们能够看到自己的知识的威力,能够将知识掌握的更牢固,在实践中我们也能够发现自己理论知识的不足,为了能够跟上,我们会为自己充电,这样又可以极大的提高我们的快速学习能力。当然我现在是站在一个学工的人的角度在看问题,学理的同学可能就不大一样。我想说的是并不是每个人都适合去学好这一大堆的理论,去在将来发现一个**定理,弄出一个**猜想。工与理一定要分清楚。尤其是我们现在处在这种并不发达的城市中,想要找到一个不错的实习的地方是不太容易的,相比那些像上海、北京之类的发达城市,我们首先在地理优势上就已经落后于别人,机会数目不能和他们相提并论。所以在实践环节我们要是再不加大力度,就可能永远不是别人的对手了。

贾院长说的好,杨甫当初市场营销只拿了三四十分,(人家在淘宝上开店,已经能达到月薪4万了)你能说他不懂市场营销?不仅仅是市场营销,还有好多的知识并不是你在上课能够学到的,这些就是实践得来的经验,而这些东西往往比知识本身更重要,不是你通过记住一些概念,多做两道选择题或问答题能够解决的。所以我们一定要抓住一切可以锻炼自己实践能力的机会,这才是你将来能与别人竞争的资本。

大学应该是一个能够真正因材施教的地方,这是中国的需要,也是当代大学生的需要。在大学中,做研究的要踏踏实实做研究,做工程的要认认真真做工程,这样才能让每个人都能够找到自己的兴趣点,发挥出自己的潜能。考试现在不应该成为大学生好坏的唯一衡量标准,大学里也不应该以考试来逼迫学生去学习。大学要真正让学生能够在其中学到东西,不仅仅是技术,还有现在社会急缺的各种道德品质。大学生处在青春的最旺盛期,这个时间段是及其宝贵的,希望我们都能抓住各种机会去锻炼自己,提高自己。也希望我们的大学能够通过改革日趋完善,这样才能让超级大学生能够真正的“批量生产”,这样也可以真正的让像刘伟这样的悲剧尽可能少的发生,甚至不发生!
……

[阅读全文]

2009年3月22日星期日

javascript 内置对象

虽说自己之前在刚进入web组的时候接触过一丁点的JavaScript,但是那个时候由于时间紧迫,自己其实对它一无所知。其实真正开始学习JavaScript应该还是上学期的暑假的前几周,和语音web组的几个兄弟姐妹们一起在武汉这边进行自我培训。我们的语音web项目主要是做对路由器上VOIP相关业务进行配置的一个项目,以web页面进行配置去代替原来的命令行。其中分为两个方向,一个是C,另一个是web。Web方向主要是通过利用xsl+xml+JavaScript来做。因为在大三上学期有几个月的时间自己还是学过一些web相关的东西(主要是jsp),自己不想就这丢弃它,再者自己也觉得web这个东西确实也是很有意思的,于是我就选择了其中web这个方向,这样也就少不了对JavaScript的学习了。

JavaScript的语法很简单,可以说是我见过的语言中最最简单的了(其实我也没见过多少语言^_^),基本上学过C的人,很快就能学会它。它是在客户端浏览器上执行的一种脚本语言,基本语法和C一样,但是对类型分类不是特别明确,所有的类型一个var就可以进行初始化,对于写代码的每一行应该有的分号写掉了,这也是允许的,字符串可以进行加减运算也可以直接比大小的……。就这几点就足以说明它比C语言的语法简单了吧!但是真是由于它的这些简单,造就了它的灵活与复杂,大家可别小看它的强大哟!

恩,学就要脚踏实地的学,我们先研究一下js与浏览器打交道的几个顶层DOM对象:
window---好强大的一个东东,里面有document,history,location,Navigator,Screen属性,常用方法有alert(),confirm(),prompt(),setTimeout(),clearTimeout(),open,close()……,都是很不错的东西。
Navigator---现在浏览器版本不少啊,每个浏览器对html、css的解析也不完全一样,这样为了保持代码的兼容性,这个对象就可以派上用场了
Screen---能够得到你显示屏幕的一些相关属性
History---记录页面跳转的历史记录,可用于页面回跳
Location---可以控制页面跳转,进入http://www.sina.com/abcdefg,让你5秒钟回到主页这就是靠这个东西控制的页面跳转啦!下面是我实现的一个小小的实例:


<html>
<head>
<script language="javascript">
var i = 5;
function goAway()
{
location = "http://www.g.cn";
}
function changeTime()
{
document.getElementById("wait").innerText = --i;
setTimeout("changeTime()",1000);
}

setTimeout("goAway()",5000);
setTimeout("changeTime()",1000);
</script>
</head>
<body onload="document.getElementById('wait').innerText=i">
<h1>test1</h1>
<span id="wait">
</span>
秒钟将会跳转到google
</body>
</html>

Document---代表整个html文档,可以控制和访问页面中的所有元素,实现各种动态效果,很厉害!
……

你应该可以发现window中就已经包含了下面的五个属性,是的,window对象中的五个属性都是对下面只读引用(也就是说可以使用其中的方法和属性,不能动态的为其添加方法和属性了,至于这个为一个对象动态的添加方法和属性以后讲对象的时候再说),其实这样已经足够了,所以我们只需要一个window对象就够了,其余的就可以不用管了。因为window对象表示一个浏览器窗口或一个框架,对象会在 <body> 或 <frameset> 每次出现时被自动创建。使用它的属性和方法可以直接使用,不用在加上”window”这个前缀了。window.location = "http://www.baidu.com"可以直接写成location = "http://www.baidu.com"。

好了,以上是HTML DOM的几个对象,要想学习它,w3shool中的教程讲的还是很细致的,我也就不多赘述的了。里面document这个属性是最最重要的了,它代表了就是你当前显示的页面,可以控制一切!

然后就是真正JavaScript的内置对象了,JavaScript的内置对象有这么几个:
String---最常用,也比较简单,它里面的方法也比较多和java中的String差不多。但是需要注意的是它和java中还是有些区别的,比如trim这种方法就没有,不过你自己也可以为它动态的添加这个方法比较灵活。实现如下:
<html>
<head>
<script language="javascript">
function test() {
var txt = " 你好,Welcome to my blog! ";
document.getElementById("input1").value=txt;
var newtxt = "";

//未加上trim方法之前
try {
newtxt = txt.trim();
document.getElementById("input2").value=newtxt;
}catch(e) {
alert("sorry, trim method is not exist!");
}

//为String加上trim方法
String.prototype.trim = function()
{
var str = "";
var len = this.length;
var i = len-1;
var j = 0;
while( i >= 0 && this.charAt(i) == " " ) {
i--;
}
i = i+1;
while( j < i && this.charAt(j) == " " ) {
j++;
}
if( i>=0) {
var str = this.substring(j,i);
}

return str;
}

//加上trim方法之后
try {
newtxt = txt.trim();
document.getElementById("input2").value=newtxt;
}catch(e) {
alert("sorry, trim method is not exist!");
}
}
</script>
</head>
<body onload="test()">
input1: <input id="input1" type="text" style="width:300px"/><br/>
input2: <input id="input2" type="text" style="width:300px"/><br/>
</body>
</html>


Array---JavaScript中的数组异常强大,即可以当作stack来用,又可以当作ArrayList来用,很不错,它里面已经提供了这类的方法,push,pop方法它有,然后还有一个splice方法,这个方法可以实现对数组里面数据的精确插入和删除!当然它里面还有其它一些好方法,你可以拿的api看看!^_^
Math---是一个封装了基本的数学运算的函数,这里的Math对象是一个不能实例化的对象,如果你想用它对它的数据进行操作,直接像这样:var a = Math.round(12/5),就可以了,当然比较多的时候就可以这样with(Math){/*这里可以随便使用它的属性和方法,不用加前缀了*/}。
Date---一个日期的对象,看到网上经常有一些显示日历或时间的网站的吗?大多都是利用这个对象做成的,自己也写过小日历玩,在网上也可以下到不少这样的牛X代码,很强大,我就不把我自己的鹾东西放上去丢人了!^_^,只提醒像我这样的初学者,getYear和getFullYear在IE中都可以获取年数,但是在firefox中就不同了,getYear只是获取从1900到现在的年数,getFullYear才是获取当前年数。所以为了兼容性,最好还是用getFullYear来获取当前年数了,^_^,getDay是获取的星期,而且星期日是返回0的,getDate才是获取月份中的某一天,getMonth是返回月份数-1的用的时候加1就可以了。
RegExp---正则表达式对象,这个东西很多语言都支持,JavaScript中这个可以用于对表单中一些输入数据的合法性进行验证等等,下面是我写的一个检验Email合法性的例子:
<html>
<head>
<script language="javascript">
/*check email*/
function checkEmail(str)
{
var valid = /^[a-z1-9A-Z_]+@[a-z1-9A-Z_]+(\.[a-z1-9A-Z_]+)*\.[a-z1-9A-Z_]{2,3}$/
if(valid.test(str)) {
alert("good, your email format is right!");
}
else {
alert("sorry, your email format is wrong!");
}
}
</script>
</head>
<body>
<h2>在Email中输入你想输入的Email,然后点击页面任何的其它地方一下,看看效果</h2>
Email: <input id="input1" type="text" style="width:300px" onchange="checkEmail(this.value)"/>
</body>
</html>


Boolean---这个就是最最普通的一个对象了,大家应该都再清楚不过了,我也不多说了,只说明逻辑对象中初始化为空,0,null,””,false,NaN,undefined都会被认为是false,其实在if这种判断中也是这样,如果是那些值,都会被认为是false,其余则都会被认为是true。Java中的if判断十分严格,必须是true 或false,有时候一不小心把一个null的东西丢到if中判断,就会报错了。JavaScript还是比它随意一点吧!^_^

好了,今天就暂时讲这些了,哇,有点长哦,嘿嘿!也只是刚学了点JavaScript,里面肯定有一大堆不对的地方,还望各位高手指正!

……

[阅读全文]

2009年3月17日星期二

开博第一篇

一直都太懒,很多东西都懒得整理,记录,这样导致我总是忙忙碌碌,但是却没有什么输出,很多好的经验随着时间的流逝都忘记了,很是可惜。所以今天特开此博,希望能够定期记录下自己的灵感和想法,总结自己的得与失!

千里之行,始于足下。那么就先走出这第一步吧!……

[阅读全文]