易栈网-膘叔

浏览模式: 标准 | 列表 | 图文
天狗食(吞)日

天狗食(吞)日

500年一遇的日全食就这么被一场大雨给阻隔了。
下次要看再等三百年吧,准备考虑开始修真,可以多活几年。哈哈

随便说说关于日全食的笑话:

1、天宫用了盗版windows,被微软300年黑屏一次

2、天宫操作系统被黑客入侵,全黑了

3、为什么这次黑屏有五分钟?因为天狗吃太阳时,太烫,不象以前吃月亮,冷的,一口就可以干掉

4、老天和人玩:天黑请闭眼

5、日全食事件,显然是别有用心的太阳,煽动不明真相的月亮,利用地球自传和公转的机会,实施的一起有组织有预谋的破坏中国稳定的颠覆活动。我XX已经派出乌云部队进行拦截,同时对月亮进行宣传教育,在我XX强大的ZZ攻势和宣传教育下,月亮深刻明白了自身的错误,弃暗投明,并劝说太阳为宇宙建设发光发热。目前太阳月亮地球情绪稳定。乌云部队也已经返回基地。

6、嫦娥驾着月亮想与太阳神私会,却惹得地球人怨声载道,嫦娥不喜,结果不欢而散 (评论:美女傍老外,自然那么多人不开心了)

7、太阳:“亮,我们又见面了,很多话想跟你说,却不知道从何说起。”(月亮一下子扑入太阳怀中)月亮:“日,什么都不用说了!”地球及其他星体:[安静并感叹]我们五百年才看一次A片啊!

8、太阳:“亮,五百年了,我们终于又在一起了。 ”月亮:“日,什么都不用说了 ” (关灯,一头扑入怀中)。。。。。。。。(一会儿)月亮:“怎么才五分钟? ”太阳:“地球上看的人太多了,我紧张

其他的后来人补上。。

Wordpress MYSQL数据库优化技巧

Wordpress MYSQL数据库优化技巧

一直在考虑是不是要换到wordpress, sablog用了这么长时间,也算是有感情了的。只是,他一直不更新,而且前台模板用的那种定界符做模板处理,我很不习惯。
以前coolcode.cn也是用的wordpress,后来转到了sablog上面。如今,我却想转到wordpress上面。。。不知道是进步还是退步。

也曾想过重写前台,请了两个朋友帮我做页面,结果现在是程序写了一半,页面做了一半,离完成看来是遥遥无期了。。

所以,记录下这个文章,方便以后真的要转换的时候,也能做个参考。。

原文地址:http://www.phpweblog.net/haix/archive/2009/07/20/6769.html,作者是haix
内容如下:
WordPress系统使用时间长了,数据库中的冗余数据就会很多,定期优化和清理Wordpress的数据库,可以保证Wordpress能够快速工作。

  首先,停用一些无用的插件,将WordPress系统表之外的数据表都删除,只保留wp_posts, wp_comments, wp_terms, wp_term_relationships, wp_term_taxonomy 等系统数据表。

  其次,打开phpMyadmin,通过SQL语句进行冗余数据删除操作。删除前记得先备份一下。

  删除脚本是:

  DELETE FROM wp_posts WHERE post_type = 'revision';

  DELETE FROM wp_postmeta WHERE meta_key = '_edit_lock';

  DELETE FROM wp_postmeta WHERE meta_key = '_edit_last';

  最后,在phpMyAdmin中,选中所有表,点“优化表”。

  经过这一番优化操作,就可以将WordPress数据库中的冗余数据删除,优化了数据库的性能。

以上操作,需要用户懂一些SQL语句,不要进行误操作,如果用户SQL比较熟的话,还可以看看这篇文章

八个有用的WordPress的SQL语句

在过去的十年中,MySQL已经成为广受欢迎的数据库,而WordPress博客使用的是MySQL数据库,虽然使用插件可以解决一些问题,但是实 现某些特殊任务的时候,在phpMyAdmin中执行SQL语句是最简洁的方法,这里就总结八个有用的WordPress系统的SQL语句,用于解决一些 实际碰到的问题。

   1、创建备份数据库

  备份数据库是首先要做的事情,只需要通过以下方法就可以简单备份数据库:

  登录phpMyAdmin后。选择你的WordPress数据库,然后点击“导出”按钮,选择一种压缩方式(可以使用gzip)并单击“执行”按钮,当浏览器提示是否下载的时候,点“是”,将数据库文件下载到本地。

   2、批量删除文章修订

  WordPress2.6以后的版本增加了一个Post revisions功能,虽然有点用,但文章修订增加了你数据库的大小,我们可以选择批量删除。

  登录phpMyAdmin后执行下面的SQL语句即可批量删除。

DELETE FROM wp_posts WHERE post_type = "revision";

   3、批量删除垃圾评论

  一个真实的故事是,我的一个朋友在网上建立了一个博客,有次他花了几天时间外出度假,没有上网,当他回来的时候,登录自己的博客,看到有5000多条评论等待审核,当然,大多数都是垃圾评论,要手动删除这些评论要花大量时间,因此我们可以使用以下办法。

  登录phpMyAdmin后执行下面的SQL语句。

DELETE from wp_comments WHERE comment_approved = '0';

  要小心,虽然这种解决方案对于处理数百万的垃圾平邮非常有用,但是也会清除未经批准的评论,因此最好还是安装使用Akismet来对付垃圾评论。

   4、修改文章属性

  你安装WordPress后,admin账户就创建了,不少人都错误的使用这个帐号来写博客,直到他们认识到,这并不是个人帐号。

  解决的方法,每篇文章修改作者属性需要大量的时间,下面的这个SQL语句可以帮你快速完成这个功能。

  首先你要找到你正确的用户名,使用下面的SQL语句可以找到你的用户ID号。

SELECT ID, display_name FROM wp_users;

  假设这个ID为NEW_AUTHOR_ID,而管理员admin的ID为OLD_AUTHOR_ID,接着,运行下面的SQL语句。

UPDATE wp_posts SET post_author=NEW_AUTHOR_ID WHERE post_author=OLD_AUTHOR_ID;

   5、手动重设密码

  很多人为了保护自己的博客不被人黑掉,使用了很复杂的密码,这虽然是一件好事,但也经常会发生遗忘管理员密码的事情。

  当然,通过电子邮件可以发送给你WordPress重设密码的链接,但如果你无法访问你的邮件地址,那么就只好使用下面的SQL语句来重设你的密码了。

UPDATE wp_users SET user_pass = MD5('PASSWORD') WHERE wp_users.user_login ='admin' LIMIT 1;

  MD5是MySQL内置的哈希函数,用于将密码转换为散列值。

   6、更改WordPress的域名

  你可能有时候会想要更改你博客的域名,但是WordPress会将你的域名存储在数据库中,因此你要使用下面的SQL语句来修改。

UPDATE wp_options SET option_value = replace(option_value, 'http://www.oldsite.com', 'http://www.newsite.com') WHERE option_name = 'home' OR option_name = 'siteurl';

  接着,你还要使用下面的SQL将文章的GUID也进行修改。

UPDATE wp_posts SET guid = replace(guid, 'http://www.oldsite.com','http://www.newsite.com');

  最后,使用下面的语句将文章里所有旧域名替换为新域名。

UPDATE wp_posts SET post_content = replace(post_content, 'http://www.oldsite.com', 'http://www.newsite.com');

   7、显示SQL查询数量

  在你有话博客性能的时候,了解到查询数据库的数量是非常重要的,为了减少数据库查询,我们需要知道在一个页面上到底有多少个查询。

  这一次,不需要登录phpMyAdmin了,你只需要修改footer.php文件,在文件结尾增加下面几行代码即可。

<?php if (is_user_logged_in()) { ?>
<?php echo get_num_queries(); ?> queries in <?php timer_stop(1); ?> seconds.
<?php } ?>

   8、恢复你的WordPress数据库

  当你的数据库因为某些原因(黑客或者升级错误)被损坏或者丢失了,如果你有备份的话,那可以恢复你的WordPress数据库。

  登录phpMyAdmin,选择你的WordPress数据库,点“导入”按钮,点“浏览”按钮,然后从你的硬盘选择备份文件,点“执行”按钮就可以将数据库导入。

  如果顺利的话,你的WordPress功能将会恢复正常。


来源月光博客:

A*算法的JS实现

A*算法的JS实现

网上找来的代码,经典的东西哦。做网游的人可能会用到。。

<html><head><title>use A* to find path...</title></head>
<body style="margin:0px">
<script>
/*
written by hjjboy
email:tianmashuangyi@163.com
qq:156809986
*/
var closelist=new Array(),openlist=new Array();//closelist保存最终结果。openlist保存临时生成的点;
var gw=10,gh=10,gwh=14;//参数 gh是水平附加参数 gwh是四角的附加参数。
var p_start=new Array(2),p_end=new Array(2);//p_start为起点,p_end为终点
var s_path,n_path="";//s_path为当前点 n_path为障碍物数组样式的字符串.
var num,bg,flag=0;
var w=30,h=20;
function GetRound(pos){//返回原点周围的8个点
var a=new Array();
a[0]=(pos[0]+1)+","+(pos[1]-1);
a[1]=(pos[0]+1)+","+pos[1];
a[2]=(pos[0]+1)+","+(pos[1]+1);
a[3]=pos[0]+","+(pos[1]+1);
a[4]=(pos[0]-1)+","+(pos[1]+1);
a[5]=(pos[0]-1)+","+pos[1];
a[6]=(pos[0]-1)+","+(pos[1]-1);
a[7]=pos[0]+","+(pos[1]-1);
return a;
}
function GetF(arr){ //参数为原点周围的8个点
var t,G,H,F;//F,综合的距离值,H,距离值 G,水平\角落附加计算
for(var i=0;i<arr.length;i++){
t=arr[i].split(",");
t[0]=parseInt(t[0]);
t[1]=parseInt(t[1]);
if(IsOutScreen([t[0],t[1]])||IsPass(arr[i])||InClose([t[0],t[1]])||IsStart([t[0],t[1]])||!IsInTurn([t[0],t[1]]))
continue;//如果上面条件有一满足,则跳过本次循环,进行下一次。
if((t[0]-s_path[3][0])*(t[1]-s_path[3][1])!=0)//判断该点是否处于起点的垂直或横向位置上
G=s_path[1]+gwh;//如果不在G=14;
else
G=s_path[1]+gw;//如果在G=10;
if(InOpen([t[0],t[1]])){//如果当前点已存在openlist数组中
if(G<openlist[num][1]){
maptt.rows[openlist[num][4][1]].cells[openlist[num][4][0]].style.backgroundColor="blue";//调试
openlist[num][0]=(G+openlist[num][2]);
openlist[num][1]=G;
openlist[num][4]=s_path[3];
}
else{G=openlist[num][1];}
}
else{
H=(Math.abs(p_end[0]-t[0])+Math.abs(p_end[1]-t[1]))*gw;
F=G+H;
arr[i]=new Array();
arr[i][0]=F;
arr[i][1]=G;
arr[i][2]=H;
arr[i][3]=[t[0],t[1]];
arr[i][4]=s_path[3];
openlist[openlist.length]=arr[i];//将F等信息保存到openlist
}
if(maptt.rows[t[1]].cells[t[0]].style.backgroundColor!="#cccccc"&&maptt.rows[t[1]].cells[t[0]].style.backgroundColor!="#0000ff"&&maptt.rows[t[1]].cells[t[0]].style.backgroundColor!="#ff0000"&&maptt.rows[t[1]].cells[t[0]].style.backgroundColor!="#00ff00")
{
maptt.rows[t[1]].cells[t[0]].style.backgroundColor="#FF00FF";
if(F!=undefined)
maptt.rows[t[1]].cells[t[0]].innerHTML="<font color='black'>"+F+"</font>";
}
}
}
function IsStart(arr){ //判断该点是不是起点
if(arr[0]==p_start[0]&&arr[1]==p_start[1])
return true;
return false;
}
function IsInTurn(arr){ //判断是否是拐角
if(arr[0]>s_path[3][0]){
if(arr[1]>s_path[3][1]){
if(IsPass((arr[0]-1)+","+arr[1])||IsPass(arr[0]+","+(arr[1]-1)))
return false;
}
else if(arr[1]<s_path[3][1]){
if(IsPass((arr[0]-1)+","+arr[1])||IsPass(arr[0]+","+(arr[1]+1)))
return false;
}
}
else if(arr[0]<s_path[3][0]){
if(arr[1]>s_path[3][1]){
if(IsPass((arr[0]+1)+","+arr[1])||IsPass(arr[0]+","+(arr[1]-1)))
return false;
}
else if(arr[1]<s_path[3][1]){
if(IsPass((arr[0]+1)+","+arr[1])||IsPass(arr[0]+","+(arr[1]+1)))
return false;
}
}
return true;
}
function IsOutScreen(arr){ //是否超出场景范围
if(arr[0]<0||arr[1]<0||arr[0]>(w-1)||arr[1]>(h-1))
return true;
return false;
}
function InOpen(arr){//获得传入在openlist数组的位置,如不存在返回false,存在为true,位置索引保存全局变量num中。
var bool=false;
for(var i=0;i<openlist.length;i++){
if(arr[0]==openlist[i][3][0]&&arr[1]==openlist[i][3][1]){
bool=true;num=i;break;}
}
return bool;
}
function InClose(arr){
var bool=false;
for(var i=0;i<closelist.length;i++){
if((arr[0]==closelist[i][3][0])&&(arr[1]==closelist[i][3][1])){
bool=true;break;}
}
return bool;
}
function IsPass(pos){ //pos这个点是否和障碍点重合
if((";"+n_path+";").indexOf(";"+pos+";")!=-1)
return true;
return false;
}
function Sort(arr){//整理数组,找出最小的F,放在最后的位置。
var temp;
for(var i=0;i<arr.length;i++){
if(arr.length==1)break;
if(arr[i][0]<=arr[i+1][0]){
temp=arr[i];
arr[i]=arr[i+1];
arr[i+1]=temp;
}
if((i+1)==(arr.length-1))
break;
}
}
function main(){//主函数
// alert('');
GetF(//把原点周围8点传入GetF进行处理。算A*核心函数了 :),进行求F,更新openlist数组
GetRound(s_path[3]) //求原点周围8点
);
// debugdiv.innerHTML+="A:"+openlist.join('|')+"<br />";//调试
Sort(openlist);//整理数组,找出最小的F,放在最后的位置。
//debugdiv.innerHTML+="B:"+openlist.join('|')+"<br />";//调试
s_path=openlist[openlist.length-1];//设置当前原点为F最小的点
closelist[closelist.length]=s_path;//讲当前原点增加进closelist数组中
openlist[openlist.length-1]=null;//从openlist中清除F最小的点
//debugdiv.innerHTML+="C:"+openlist.join('|')+"<br />";//调试
if(openlist.length==0){alert("Can't Find the way");return;}//如果openlist数组中没有数据了,则找不到路径
openlistopenlist.length=openlist.length-1;//上次删除把数据删了,位置还保留了,这里删除
if((s_path[3][0]==p_end[0])&&(s_path[3][1]==p_end[1])){//如果到到终点了,描绘路径
getPath();
}
else{//否则循环执行,标准原点
maptt.rows[s_path[3][1]].cells[s_path[3][0]].style.backgroundColor="green";setTimeout("main()",100);
}
}
function getPath(){//描绘路径
var str="";
var t=closelist[closelist.length-1][4];
while(1){
str+=t.join(",")+";";
maptt.rows[t[1]].cells[t[0]].style.backgroundColor="#ffff00";
for(var i=0;i<closelist.length;i++){
if(closelist[i][3][0]==t[0]&&closelist[i][3][1]==t[1])
t=closelist[i][4];
}
if(t[0]==p_start[0]&&t[1]==p_start[1])
break;
}
alert(str);
}
function setPos(){//初始原点为起点
var h=(Math.abs(p_end[0]-p_start[0])+Math.abs(p_end[1]-p_start[1]))*gw;
s_path=[h,0,h,p_start,p_start];
}
function set(id,arr){//设置点的类型
switch(id){
case 1:
p_start=arr;
maptt.rows[arr[1]].cells[arr[0]].style.backgroundColor="#ff0000";break;
case 2:
p_end=arr;maptt.rows[arr[1]].cells[arr[0]].style.backgroundColor="#0000ff";break;
case 3:
n_path+=arr.join(",")+";";maptt.rows[arr[1]].cells[arr[0]].style.backgroundColor="#cccccc";break;
default:
break;
}
}
function setflag(id){flag=id;}
</script>
<table id="maptt" cellspacing="1" cellpadding="0" border="0" bgcolor="#000000">
<script>
for(var i=0;i<h;i++){
document.write("<tr>");
for(var j=0;j<w;j++){
document.write('<td onclick="set(flag,['+j+','+i+']);" bgcolor="#ffffff" width="20" height="20"></td>');
}
document.write("</tr>");
}
</script>
</table>
<a href="javascript:setflag(1);">StarPoint</a><br>
<a href='javascript:setflag(2);'>EndPoint</a><br>
<a href='javascript:setflag(3);'>Wall</a><br>
<input type="button" onclick="setPos();main();this.disabled=true;" value="find">
<div id="debugdiv"></div>

</body>
</html>

原文连接:http://www.gamedev.net/reference/articles/article2003.asp
中文翻译:http://data.gameres.com/message.asp?TopicID=25439

我是从http://www.cnblogs.com/jimtomjim/archive/2009/07/20/1527112.html拷贝来的

符合w3c 的 strict标准,用 rel 替换_blank打开新窗口

符合w3c 的 strict标准,用 rel 替换_blank打开新窗口

说实话,我没有用过这种方法,也不知道是否非常有用。但总体来说,它的效率肯定不如直接target="_blank"好吧?

如果不用JS,那以后的版本里怎么办才好呢?难道不开新窗了?怎么办?未来该如何操作?

原文如下:

现在一般网站打开新窗口采用的是target="_blank",这在过渡型DOCTYPE(xh tml1-transitional. dtd)下是允许的,但也不符合W3C的strict(xhtml1-strict.dtd)标准。

如果你去验证,会发现有下面的错误提示:

"there is no attribute target for this element(in this HTML version)"

这是因为W3C认为如果不经过用户同意,没有明确提示就打开一个新窗口是不礼貌的。所以我们只好用下面的rel属性来解决这个问题。rel是 HTML4.0新增加的一个属性,这个属性用来说明链接和包含此链接页面的关系,以及链接打开的目标。rel有许多的属性值,比如next、 previous,、chapter、section等等。

我们用rel属性的external和一个js脚本来解决问题,代码如下:

<a href=”http://www.kepu8.com“ rel="external"> 打开一个新窗口</a>

* 大量古细菌在海底被发现
* 英开发致命超级病菌-绿脓杆菌早期检测技术
* 无需 DNA 细菌也变身
* 小袋鼠育儿袋内吃奶照片
* 大白鲨类似连环杀手-捕食方式揭秘
* 蚂蚁长寿差异之谜:蚁后更长寿的秘诀在于多睡觉
* 张启发院士:培育绿色超级稻可缓解农业生态问题
* 广西反季节龙眼新品种挂果枝率达98%以上
* 日本专家从柚子皮中提取出能抑制过敏的物质
* 水稻精确定量栽培技术实现新突破


我们把js文件存储为external.js,然后通过<script type="text/javascript" src="external.js"></script>调用

下面是js文件

function externallinks() {
if (!document.getElementsByTagName) return;
var anchors = document.getElementsByTagName("a");
for (var i=0; i<anchors.length; i++) {
var anchor = anchors[i];
if (anchor.getAttribute("href") &&
anchor.getAttribute("rel") == "external")
anchor.target = "_blank";
}
}
window.onload = externallinks;
感谢老王的:Object-C之Windows版Hello, World!

感谢老王的:Object-C之Windows版Hello, World!

感谢老王这篇文章,本来有自己想办法看看是不是能搞个ipt来玩玩。然后想自己学点苹果的开发语言的。
结果买了本object-c的书回来一看,人家上面就写了object-c是安装在mac下面的。当时,心都碎了
书也扔在那里几个月了。本以为这将进40块钱的书就算是扔了水里了。谁知道老王又贡献了这么一篇文章。很是感动。。。

老王说:

Mac笔记本实在是太贵了,所以一直没舍得买,如此一来,就只能在我的Windows操作系统上学Object-C了。

安装GNUstep

GNUstep Windows Installer提供了Windows平台下的Object-C的模拟开发环境,一共有四个软件包,其中GNUstep System和GNUstep Core是必装的,GNUstep Devel和Cairo Backend是选装的。甭管必装选装,一次性全安上,免得以后麻烦。

编写Hello, World!

安装完成后,在开始菜单里的GNUstep选项里执行shell,就能打开命令行,在这里就可以使用vi编写Object-C程序了,不过操作起来总有些繁琐,其实也可以直接在Windows里进入C:\GNUstep\home\username目录,在这里用你喜欢的工具编写Object-C程序,然后再进入shell里编译。

直接给出helloworld.m文件内容,取自Programming in Objective-C 2.0一书:

#import <Foundation/Foundation.h>

int main (int argc, const char *argv[]) {
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
NSLog(@"Hello World!");
[pool drain];

return 0;
}


第一次编译:

gcc -o helloworld helloworld.m

结果出现错误信息,找不到头文件:

helloworld.m:1:34: Foundation/Foundation.h: No such file or directory
helloworld.m: In function `main':
helloworld.m:4: error: `NSAutoreleasePool' undeclared (first use in this function)
helloworld.m:4: error: (Each undeclared identifier is reported only once
helloworld.m:4: error: for each function it appears in.)
helloworld.m:4: error: `pool' undeclared (first use in this function)
helloworld.m:5: error: cannot find interface declaration for `NXConstantString'

第二次编译:

gcc -o helloworld helloworld.m \
-I /GNUstep/System/Library/Headers/

结果出现错误信息,找不到接口声明:

helloworld.m: In function `main':
helloworld.m:5: error: cannot find interface declaration for `NXConstantString'

第三次编译:

gcc -o helloworld helloworld.m \
-fconstant-string-class=NSConstantString \
-I /GNUstep/System/Library/Headers/

结果出现错误信息,找不到链接库:

helloworld.m:(.text+0x33): undefined reference to `_objc_get_class'
helloworld.m:(.text+0x45): undefined reference to `_objc_msg_lookup'
helloworld.m:(.text+0x64): undefined reference to `_objc_msg_lookup'
helloworld.m:(.text+0x80): undefined reference to `_NSLog'
helloworld.m:(.text+0x93): undefined reference to `_objc_msg_lookup'
helloworld.m:(.text+0xbc): undefined reference to `___objc_exec_class'
helloworld.m:(.data+0x74): undefined reference to `___objc_class_name_NSAutoreleasePool'
helloworld.m:(.data+0x78): undefined reference to `___objc_class_name_NSConstantString'
collect2: ld returned 1 exit status

第四次编译:

gcc -o helloworld helloworld.m \
-fconstant-string-class=NSConstantString \
-I /GNUstep/System/Library/Headers/ \
-L /GNUstep/System/Library/Libraries/ \
-lobjc \
-lgnustep-base

注意:helloworld.m必须出现在-lobjc和-lgnustep-base的前面,否则会出错。

此时会出现一些info提示信息,不过不碍事,终于成功了生成了可执行文件,执行./helloworld.exe看结果。

参考链接:Compile Objective-C Programs Using gcc

微软的防XSS攻击类库

微软的防XSS攻击类库

微软自己开发了一个anti-cross site scripting ,放在MSDN上面

相信,如果使用asp.net的朋友,都会考虑去下载了查看一下。

在该主页上,它介绍了什么是跨站脚本攻击,同时提供了自已的类库下载,还有一些类库的使用方法。。

这对我们搞PHP的来说,没有什么用处,但是,它的一些处理方法还是值得了解一下的。

例如:

XSS Libray 包含如下的方法:

Encoding Method Description
HtmlEncode Encodes input strings for use in HTML
HtmlAttributeEncode Encodes input strings for use in HTML attributes
JavaScriptEncode Encodes input strings for use in JavaScript
UrlEncode Encodes input strings for use in Universal Resource Locators (URLs)
VisualBasicScriptEncode Encodes input strings for use in Visual Basic Script
XmlEncode Encodes input strings for use in XML
XmlAttributeEncode Encodes input strings for use in XML attributes

以上方法来原于微软网页:Microsoft Anti-Cross Site Scripting Library V1.5: Protecting the Contoso Bookmark Page 。

了解了这些字面意思,那么在代码中也可以就有针对性的处理了。。利用PHP对输入或者可能出现的输入进行一下处理,会安全很多。

PHP5.3的新特性(一):对象接口的变化

PHP5.3的新特性(一):对象接口的变化

这是一篇翻译文章,申明,不是我翻译的,我不翻译文章,我只是文章的搬运工(仿某广告)
原文是IBM网上某作者的英文版,在这里,是风之缘网站的一篇转载(是我从他网上转载啦)

PHP V5和面向对象编程

2004年PHP V5发布,和PHP V4相比,它在面向对象编程(OOP)和设计方面有了巨大的进步,增加了一些必要的特性,如类的可见性、正确的构造函数与析构函数、类型提示和类反射 API。PHP5为高级面向对象编程开启了方便之门,使得开发者可以更简单地实现各种设计模式,设计出更好的类和API。

在PHP V5.3中,继续大幅加强OOP能力,这些改进包括语法的进化和性能的改善等方面。首先让我们来看静态方法和属性相关的新特性。

改进后的静态方法与属性的处理方式

PHP V5中一个实用的新增特性是可以指定类的一个方法或属性为静态成员(PHP V4支持静态地访问类的方法和属性,但是无法指定它们是为静态访问而设计的)。静态访问在实现单例模式时非常有用,此时,类只存在一个实例。

PHP V5.3增加了若干特性,以加强对类的静态方法和属性的支持。首先,我们来分析新增的魔术方法:__callStatic()。

__callStatic()魔术方法

PHP V5包含了若干个可以用于类内部的魔术方法。如果在类中定义了这些方法,它们可以提供特殊的功能,从而实现重载(允许一个方法接收不同类型的参数)和多态 (允许不同数据类型使用相同的接口)功能。同时,它们也让PHP中的面向对象编程(OOP)和设计模式的实现变得更加简单。

在PHP V5.3中,新增了一个魔术方法:__callStatic()。它和__call()魔术方法类似,后者用于处理类中不存在或不可见的方法调用。而__callStatic()用于处理类似的静态方法调用,方便开发者实现方法的重载。下面是一个如何使用的例子。

Listing 1. Example of using __callStatic() vs. __call()

class Foo
{
public static function __callStatic(
$name,
$args
)
{
echo "Called method $name statically";
}

public function __call(
$name,
$args
)
{
echo "Called method $name";
}
}

Foo::dog(); // 输出"Called method dog statically"
$foo = new Foo;
$foo->dog(); // 输出"Called method dog"
需要注意,PHP要求__callStatic()方法必须是public,而且是static。类似的,__call()魔术方法也要求定义为public,其实所有的魔术方法都要求定义为public。

动态的静态调用

PHP中有一个实用的特性是变量的变量。它意味着你可以用一个变量的字符串值作为另外一个变量的名字。换句话说,你可以完成下面的功能。

Listing 2. Variable variables
x = 'y';
$$x = 'z';
echo $x; // 输出'y'
echo $$x; // 输出'z'

同样的概念可以用于函数,甚至类的成员函数,如下例所示。

Listing 3. Variable function and class method names

class Dog
{
public function bark()
{
echo "Woof!";
}
}

$class = 'Dog'
$action = 'bark';
$x = new $class(); // 实例化类'Dog'
$x->$action(); // 输出"Woof!"
在PHP V5.3中增加了一个功能,静态调用中的类名可以通过一个变量来指定。由此引入了一些新的编程方法,如下所示。 Listing 4. Variable class naming
class Dog
{
public static function bark()
{
echo "Woof!";
}
}

$class = 'Dog';
$action = 'bark';
$class::$action(); //输出"Woof!"
这个新增功能使得PHP中变量的变量这个特性成为一个完备特性,可用于各种环境。

接下来让我们关注另外一个更加实用的关于静态方法和属性方面的功能改善:静态调用的晚绑定。

静态调用的晚绑定(膘叔:是否叫后绑定或者延迟绑定较好?)

PHP V5.3之前一个令人恼火的事情是静态方法和属性的处理。到目前为止,静态引用,包括使用self或__CLASS__,都是在函数定义所在类的范围内解析。当继承一个类,并在子类中调用静态函数时,将会发生解析错误。PHP V5.3中新增的静态调用晚绑定特性解决了这个问题。为了更好的说明这个问题,我们创建如下一个包含静态方法的类。

Listing 5. Class Foo with static method test()
 
class Foo
{
protected static $name = 'Foo';

public static function test()
{
return self::$name;
}
}
然后继承这个类,并在子类中重定义$name属性。 Listing 6. Child class Bar that extends parent class Foo
class Bar extends Foo
{
protected static $name = 'Bar';
}
最后进行一个静态调用。

Listing 7. Static method call test()
这个调用的输出将是字符串Foo。因为test()方法中的self::$name引用是在 Foo这个类中解析。而PHP解释器这么做是因为test()方法是在类Foo中定义的。

PHP V5.3通过使用static关键字,使得该引用可以在当前类中解析。将上面的类Foo改写为如下定义(译注:注意红色部分),输出将变为Bar。

Listing 8. Using the static keyword
class Foo
{
protected static $name = 'Foo';

public static function test()
{
return static::$name;
}
}

class Bar extends Foo
{
protected static $name = 'Bar';
}

echo Bar::test(); // 输出'Bar'
需要注意的是,static关键字的这种用法在非静态上下文中无效。也就是说普通的继承规则对静态调用无效。static关键字将简单的去尝试在当前类中进行解析,而不是函数定义所在的类。这是一个需要我们注意的事情。

在分析了一些有关静态方法和属性方面的改善之后,我们来看看PHP V5中非常重要的部分:标准PHP库中新增的一些类。

标准PHP库

PHP V5中新增的标准PHP库是用于解决标准问题的一组类和接口。这些问题包括可迭代对象、数组对象和链表等。使用这些类和接口的好处是:它们是PHP的原生 方法,比用PHP实现的效率要高。 同时,它们使得许多PHP内置函数和语言结构可以直接使用这些对象,比如你可以通过foreach结构遍历一个实现了迭代器接口的对象。

PHP V5.3在SPL中增加了若干个类。如早前提到过的双向链表SplDoublyLinkedList。SPL中新增的栈和队列类:SplStack和SplQueue的实现中都使用了该类。

下面看一下如何使用SplStack类实现一个栈。

Listing 9. Using SplStack

$stack = new SplStack();

// push a few new items on the stack
$stack->push('a');
$stack->push('b');
$stack->push('c');

// see how many items are on the stack
echo count($stack); // returns 3

// iterate over the items in the stack
foreach ( $stack as $item )
echo "[$item],";
// the above outputs: [c],[b],[a]

// pop an item off the stack
echo $stack->pop(); // returns 'c'

// now see how many items are on the stack
echo count($stack); // returns 2
SplQueue类与SplStack相似,实现了队列功能(先进先出,而栈是先进后出)。此外,还实现了堆(SplHeap)以及一些特殊的队列和堆实现,如(SplMinHeap、SplMaxHeap和SplPriorityQueue)。

另外新增的一个实用类是SplFixedArray,如名字暗示的那样,它是一个固定大小的数组实现。不过,它的速度比PHP内置的数组要快20-30%,原因是它是固定大小的,而内置数组是变长的,并且它只允许数字索引。下面演示了它的用法。

Listing 10. SplFixedArray
$array = new SplFixedArray(3);
$array[0] = 'dog';
$array[1] = 'cat';
$array[2] = 'bird';
$a->setSize(4); // increase the size on the fly
$array[3] = 'mouse';
foreach ( $array as $value )
echo "[$value],";

Output:
[dog],[cat],[bird],[mouse]
此外,还增加了两个迭代器类:FilesystemIterator和GlobIterator。它们的行为与PHP中的其它迭代器一致,只不过它们是为特定目的而定制的。

另外一个变化是SPL在PHP V5.3中将强制启用。以前的PHP V5版本,你可以在编译的时候禁止SPL,但是这个选项现在没有了。

SPL的改善提高了PHP的易用性,并实现了数据结构如双向链表、栈、堆和队列等。它们可以替换用户自己实现的这些数据结构,这样不但可以提高效率,而且还可以促进PHP函数和语言结构的整合。

讨论完SPL的改进之后,我们看看PHP V5.3如何通过采用循环垃圾回收技术来提高OOP的性能与内存消耗。

循环垃圾回收

PHP开发者经常碰到的一个性能瓶颈是垃圾回收。PHP有一个非常简单的垃圾回收器,用于回收不在作用域内的对象。它的原理是通过引用计数,当计数到达0时(意味着不再有引用指向该对象),该对象被回收,释放占用的内存。

这种方式简单高效,但是在父子关系的对象引用中会产生问题。此时,这些对象的引用计数器不为0,所以不会被回收,一直存在到请求的结束。下面我们来看这个问题的一个例子。

Listing 11. Parent-child class relationship not properly garbage collected in PHP V5.2 and earlier

class Parent
{
public function __construct()
{
$this->child = new Child($this);
}
}

class Child
{
public function __construct(
Parent $parent
)
{
$this->parent = $parent;
}
}

for ($i = 0; $i < 1000; $i++) {
new Parent();
}
在这个例子中,你每次创建一个Parent对象,然后该对象不再被引用,但是内存不会被释放,所以脚本的内存消耗持续增加。在用户空间,存在一些方法来解 决该问题,比如为Parent类提供一个析构函数,直接释放引用的子对象。但是你必须在释放Parent对象前显式调用该析构函数,如果一直这么做,将使 你的代码变得非常复杂。

在PHP V5.3中,垃圾回收器将会检测这种循环引用并释放它们,从而使该脚本的内存使用保持在正常状态。当Parent对象的引用计数为0时,Parent内部引用的Child对象也将被回收。

总结

PHP在支持面向对象编程方面走过了漫漫长路,从PHP V4时的弱支持到PHP V5中的飞跃以及后续版本的改进。现在PHP V5.3又加入了一些令人兴奋的改进,包括语法上的改进,如新的__callStatic() 魔术方法、动态的静态调用、静态调用的晚绑定和静态方法和属性的支持。SPL上则增加了双向链表、栈、堆和队列的实现,为开发者提供了现成的常用数据结构 并提高它们的易用性。最后,期盼已久的循环垃圾回收器修复了自引用类导致的内存和性能问题,通过这个大幅改进的垃圾回收器,正确释放循环引用的对象。上述 的特性,让PHP V5.3成为一个更强大的面向对象编程语言。

原文链接:http://www.ibm.com/developerworks/opensource/library/os-php-5.3new1/index.html

[转]《我的青春谁做主》经典台词汇总

[转]《我的青春谁做主》经典台词汇总

钱小样,好象是奋斗一中的米莱吧,挺有个性的女孩。虽然我不太喜欢看连续剧,但并不代表我不喜欢其中的台词。。。


“钱小样”算是剧中语言特色最强烈的一个角色

哲理篇:
1、小样:谁都有个性,谁也不是生下来就适应社会,环境像是一条河,咱都是河里的石头,一开始各有各形状,头上长角、身上生刺,天长日久被喝水冲刷,角啊,刺啊的就都磨成圆的了。
2、霹雳:幸福就是猫爱吃鱼,狗爱吃肉,奥特曼爱打小怪兽。
3、姥姥:如果不能改变结果,那就完善过程。
4、姥姥:现在社会给人灌输的成功观念太单一,你们年轻人追求的无外乎是赚钱、成名,给自己贴上成功标签,千篇一律、千人一面,这是典型的唯结果论。其实不是所有得到结果的都成功,也不是没结果的就失败,我一辈子的体验,是成功藏在过程里,将来回头看,乐趣不在最后撞线那一下,结果是买东西的赠品,好了算赚的,不好也没什么!
5、霹雳:成长的经验是是要靠我们自己获得的, 不是家长的强行灌输。 如果我不载跟头等于没有经验。早晚有一天还是会跌倒的 ,父母的经验是很宝贵,但是仅供参考 。
6、小样:高齐说的对,我们不仅是自己的,还有责任。
7、雷蕾:她知道她幼稚,但不让她幼稚,她就会一直幼稚下去。
8、姥姥:理智与情感,是人生最难做的一道题。用感情覆盖理智是幼稚,完全理智是空谈,成熟的标志是把两者分开。可以用感性去看问题,但是必须用理智去解决问题。
9、霹雳男朋友:一个人最惨的是什么?就是干他不喜欢的事。比最惨更惨的是,还要干一辈子!
10、周晋:如果说犯错是成长比如付出的代价,那么改错就是成熟的过程。人只有犯过错,才能够知道如何避免以后不犯,即使是这样,也可能永远失去改正的机会,改不了错最折磨人,就像一根刺永远扎在心里,一想就疼。


“杨尔”和“杨杉”是家中的主力
家庭篇:
1、杨尔:你小姨就是不求上进的性格,不懂得实现自我价值,哪像我,事业心这么强,这就是燕雀跟鸿鹄的区别。
李霹雳:我从小就觉得小姨家比咱家温馨,家庭气氛特好。
杨尔:那是他们家俩燕雀凑一块儿了,不像咱家,我一鸿鹄结果也找一燕雀。
2、谁在年轻的时候都只想离开父母,走得越远越好,不知不觉就走出很远,跟他们隔着千山万水。有一天你猛一回头,发现不管走了多远,始终有一根线连着你和他们,那时候父母已经变老,腿脚不再利索。于是你又得折回头,重回他们身边,跟过去不同的是,你变成大人,他们成了孩子,所有人都是这种轨迹,离开、再回来、分离、再团聚,这就是——家。
3、杨怡:儿女的人生是一艘船,掌舵的应该是有经验的水手,就是父母。
4、姥姥:家就是一个合作社、互助组,一方有难,八方支援。
家是什么?家是中国人几千年赖以生存的条件。家是每个人的安全伞、保护罩,什么都没有了,只要还有家就不至于一无所有。
5、杨尔:我跟你爸离了,你得接受现实。
霹雳:接受呀,离婚的时候我是被缺席宣判的,现在趁3个人都在,补办个遗体告别仪式,瞻仰一下遗容,完了就跟过去彻底告别了。
6、雷蕾对霹雳:父母的爱就是湿棉袄,穿上难受,脱了冷。当他们俩都围着你转的时候,你就会觉得你涝了。
7、杨尔:小样家的命运告诉我们,教育是人生的第一道底册,妈给上什么颜料,孩子身上就落什么色儿。
8、雷蕾:你觉得父母理所当然都应该为你考虑,可他们也是人啊,当他们的需求跟你的发生冲突时,你要求他们一切为你着想,是不是太自私了?
9、青楚妈:沟通啊!你看我跟青楚沟通的多好。有些事说着说着就开了。
小样:对,好多矛盾就是说着说着说出来的。
10、霹雳对妈妈说:最让我感动的是,你和雷力来同志,为乐道西餐厅的死去活来,做出了不可磨灭的贡献。
杨尔:这是咱闺女头回说人话,我算知道软刀子怎么杀人了。

爱情永远是青春的主题
爱情篇:
1、小样:你个大傻帽,分明就是一只蜗牛,却偏要抢人家乌龟的壳,你不怕超重压死了你啊。
方宇:“比喻很贴切,可是我听着很别扭,能不能换成螃蟹的壳啊?”
2、李霹雳:你们还有没有可能复合?
李父李母同时回答:没有。
李母:离了再复那不是历史倒退吗。
李父:我跟你妈用了二十年时间证明一个错误,不用再证明了。
3、方宇:我不帅,本事不大,挣钱不多,背一身债,还犯过错,你愿意嫁给我吗。
小样:愿意。
小样:我不漂亮,会点京剧、护理和速记,连累你为我背一身的债,还为我犯错,你愿意娶我吗?
方宇:愿意。
4、李博怀:强势男人不合适你,两人都强早晚是个斗。
杨尔:你不强,咱俩也没少斗。
李博怀:那净是你斗我了,这么多年你这个脾气只涨不跌,你跟别人过能习惯才怪。
杨尔:你说实话,跟我过特委屈是吧。
李博怀:是倒是,不过什么态势一长也就习惯了,咱们分手以后,我还老梦见你。
杨尔笑。
李博怀: 都是噩梦。
5、小样:不能提你,连方字都不行,我在家看到桌子角都能想起你来。
方宇:你何苦这么自虐呢?那我不来,你还能把家具都磨成圆的?
6、方宇:一会儿冰,一会儿火的,你还真把我当钢炼啊。
7、方宇:爱你,老婆。
小样:我喜欢这个职称
8、小样:我们喜欢的正经里面带一点不正经,但这一点不正经又不能耽误正经的那种。 女孩都追求安稳,但是又不能太安稳,这安稳里带一点不安分,但这点不安分又不能破坏安稳。
9、方宇:说,你是喜欢他还是喜欢我?
小样:你先说,你是喜欢我呀,还是喜欢我?
10、方宇:阿姨,叔叔,让我给你们家当一辈子包身工吧。

小样和方宇为了梦想而奋斗
励志篇:
1、小样:别人撞了南墙才回头,而我撞了也不回头,我要跨过去。
2、杨尔:怎么不能合作?内衣跟房产就不能接轨吗?只有想不到的,没有做不到的。
3、小样:我每天吃的有限,穿的有限,花的也可以有限,但是开心必须无限。
4、小样:幸福就是跟我觉得最帅的蚂蚁,为别人眼里的小草,我们眼里的大树,一起努力奋斗。
5、霹雳:在我潜意识里面,有对强权的恐惧,又有得过且过的鸵鸟心态,另一方面,我理想的小火苗这台一闪一闪的不肯熄灭。
6、霹雳:不是父母认为的理想就是理想,理想没有高低贵贱之分。我只是没有实现我妈的理想,不代表我的理想就一样没价值。
7、小样:现在不是倡导张扬个性自我实现呢?可我张扬了,也实现了,后果就灭亡了呢?
8、小样:只要有恒心,铁杵磨成针。
方宇:那得看本身是什么材料,咱俩是木杵顶多磨成牙签。
9、小样:你知道蚂蚁的幸福是什么吗?
方宇:知道,胃口小不贪婪。
小样:我们知足,别人吃一碗还吃不饱,咱俩有一粒就乐半年。
10、小样:渺小怎么了?我们俩都渺小,永远没有推土机成功。咱俩就是奋斗半辈子,也就只是人家那么一撮子。

贫嘴的一家人
贫嘴篇:
1、方宇:北京有一KTV名字特吉利,叫钱柜,自打开业那天起就哗哗往里进钱,你那么爱挣钱,我帮你改一名,保证也吉利。
钱小样:叫钱箱。
方宇:没那么好听——叫钱缸。
2、方宇:你真不枉姓钱,长了一钱串子脑袋。
3、小样:这么多花啊,真好看,一看就知道是假的。
4、小样:首先不是我主动提出出卖的假条,是学生软磨硬泡求我开的,被拒绝之后他们用金钱利惑我。这买方和卖方市场需求一致交易就这么达成了,可是我没想到着市场需求迅速扩大,好多学生闻风而至,我被架上去,我就没下来
5、我搁这儿坐一下午了,我越琢磨越觉着大盘跟人生一样。每个人都是一只股票,看到那绿莹莹的一片了吗?我就在里边都快跌停了。这人往高处走,水往低处流,不能只下看这样永远也没有进步,不看那几只红的多扎眼呀!就好比周晋是蓝筹股,青楚是绩优股,霹雳是潜力股,我一个垃圾股。
6、你就剩30块钱了还穷横穷横的,真帅!
7、周晋:明白,糖衣吃掉,炮弹打回。
8、霹雳:你喜欢我们这里(西餐厅)什么特色啊?
顾客:人少,而且我喜欢一堆人围着我转的感觉。
9、钱进来:夫人哪,告诉你一个振奋人心的消息,你家姑娘离家出走了。
10、青楚:死亡就是进入了另一个人生阶段,就好比你推开一扇门走进另一扇门,其实没什么可怕的。
小样:就是说出了这屋进那屋呗。那没准那屋要什么有什么,比这儿还乐呵呢。
青楚:不知道,反正去了那屋的人还没有回来过的。
小样:那是,随便往回溜达也怪吓人的。

一篇介绍招聘的文章:如何面试应届生求职者

看到PHP5研究室上这篇文章,总还是有点感慨的。特别是最后那几句话:还是在 ngacn 上看到的一句话,团队需要两种人,要么 NB 的,要么听话的。


原文地址:http://www.phpv.net/html/1696.html
作者:Platinum
内容如下:

为什么要招应届生?不是因为便宜,有人说还没跳过槽的人忠诚度能搞些,这也不尽然,有些人没经受过工作的压力,总以为自己碰巧找到个压力大的工作, 换换会好些。我的原因是……应届生好调教。在他们没有被各种枯燥乏味的工作折磨的以为写程序本来就这么 SB 之前好好洗洗脑子。


1、2、3 是基础题,4、5、6 问的是数据库操作,7 算是综合能力吧。

1. 进制运算

可以是让他模拟一些简单的字符串函数,类似 bin2hex、base_convert、base64_encode,或者单纯的,让他手动算一下 7 进制的 54321 显示为 9 进制是多少。

应该高中或者之前就能接触到 2 进制 10 进制之间的换算了吧,当然,他当时很可能没听懂。通常的情况,如果以前没留意这个问题但有理解能力的,可能能在几分钟的做出一些成功不成功的尝试。至少不应该很茫然。最糟糕的情况,连整数的最大值是多少都不知道,那就算了。

2. 描述一下常见的关于读取文件内容的操作,及各自的特点

应 该不用迟疑太久就把 file、fopen、file_get_contents、readfile 列出来。表现好点还可以提下 readfile 的流式读取不占内存之类的。如果看的教材太老,可能只会说 fopen。最糟糕的辩解是不说跟数据库打交道比较多,文件操作没怎么接触过,完全无视文件静态化的存在。

3. 怎么模拟一个 POST 表单提交

答 socket 或者 cURL 都可以。

4. 列举一些常规优化方式

正 确索引(就不强求完全理解多列索引了,最好能知道每个查询只能用到一个索引),知道索引提高查询速度、降低插入速度。正确的字段类型(能知道 char 和 varchar 的区别和优缺点)。text 类字段可以单放一个表用主键关联。总之他能说的越多越好。顺便问问他他所知道的最大处理能力是每秒多少条,哪怕是测试环境里的 benchmarking(今天看到份简历,号称三年工作经验,将半个月三万条插入形容为他所遇到的最高的负载,写在简历的醒目位置)。

5. “你知道,把时间存在数据库里有两种方法,一种是用时间戳,就是 PHP 函数 time() 产生的那种整数,另一种是 MySQL 里字段类型设成 datetime。那么,为什么一定要后一种方式?”

最简单的一个例子,如果存的是时间戳,你无法按类似“所有周三的数据”这种方式显示内容。这表明了他的学习阶段:是否接触了类似日志分析类的东西。因为这些是早晚都要接触到的。

6. 简单联表查询

有这么两个表

user 表:

id name
1 张三
2 李四
3 王五
4 赵六

apple 表:

id user number
1 1 5
2 3 3
3 1 8
4 4 6
5 3 2
6 4 2

apple 表的 user 字段跟 user 表的 id 对应,一条 SQL 语句查出每个人都有多少苹果

如果他不知道 join,可能会这么写

SELECT user.name, SUM(apple.number) FROM user, apple WHERE user.id = apple.user GROUP BY user.id

正确答案应该是这样

SELECT user.name, SUM(apple.number) FROM user LEFT JOIN apple ON user.id = apple.user GROUP BY id

这两条语句的差别是,不用 join 无法显示出李四有 0 个苹果 -_-

7. 假设我们要做一个公交系统的常见服务,就是做查公交车怎么倒车的。假设完全由你自己来搞,我只关心最后结果,你会怎么做这个项目。说的越详细越好。

可能需要不断提示。考查一个人的做事能力,比方说他首先会想到需要数据,数据库应该怎么设计,有几个表,什么样的字段。
可 以加分的地方可以有这么几个点。给站名编 id,匹配数字的速度要远大于匹配字符串。站点之间要距离的数据,这样计算最优倒车路线应该能考虑到站数,倒车次数、距离等权值。如果很有远见,任意两点 之间的数据应该是提前算好的,比方说有 200 条公交线路和 2000 个站点,始发终点的组合可能是 2000 * 1000,每种线路可能有 1 - 6 种方案,有个表是来装这近一千万行结果的,如果有线路变化,再用本地的机器重新算一遍线路。这样整个系统才有实用价值。不然可能每次查询都需要耗费数秒或 者更长时间,只能当单机软件用。


这些题本身是交流的话题,而不是“做对 5 道以上我就招你”这种门槛。我面试时每道题都会给予充分的时间,如果他做不上来,也起码能判断他的思考方式,而忌讳说“如果你不知道就明说,咱们赶紧做下 一题”。同时也能观察出性格等方面。比方说第 6 题,有人把 SUM 写成 COUNT,我就问他你看看前面写的是否有问题,同时又怕太明显,又补充一句“也可能什么错误也没有、我在误导你,你自己判断”,于是他就不再理会、继续 接着写完整个 SQL。再综合他的其他一些表现,我的结论是此人主见极强的,我不会用。属于出了 BUG 第一念头是 BUG 在解释器上、做出来的程序跟产品需求不符时会说是你产品没说明白的那种。相反,我很欣赏那些在做完第一道题的 7 进制转换后还知道验算的,因为既然是笔算就很容易出错。我觉得这种人思考严谨、负责任。

其他的一些知识,比方说 memcache、SVN、单元测试这些,都属于经验问题,应届生很少需要接触到这些东西(甚至文件静态化也很少碰到),不像上面,我需要以此来判断面试者对编程是否已经入门。

还是在 ngacn 上看到的一句话,团队需要两种人,要么 NB 的,要么听话的。

ipod 黑屏

ipod 黑屏

买回ipod classic 120G也有两个多月了吧。昨天晚上听完歌后,就直接睡眠了。
今天早上乘公车发现黑屏。以为是昨天晚上误按导致启动后电全部用完。

因为身边没带数据线,所以无法操作。
晚上回到家中,插上机器,发现仍然是黑屏(上次没电的时候,还是可以点亮,并提示不要拔机器的。)这回,全黑了,一点反应没有。。。

紧张啊。itunes打开一看,发现quicktime被我删除,无法启动。。。

只能先google了。找到相应的提示:按住MENU+当中的按钮。长按,过了好久,终于出现一个暗暗的苹果标志。

然后打开移动硬盘(也就是苹果的磁盘),数据还在。。。
激动啊。看来苹果的东西也是会经常死机的嘛。。

看到网上很多人都说无法激活,然后送修,花了N多钱后,还是很安慰。省下一笔开销了。虽然可能在保修期内是免费的,但要跑到售后点,太累了。天又热。

解决了。安心了。睡觉了。