2009/03/17

没事做了几道PHP的面试题,传说是新浪的

1. 写一个函数,尽可能高效的,从一个标准 url 里取出文件的扩展名

思路:是标准URL,应该是符合规范的。所以没有考虑复杂的情况。从左边寻找到第一次出现‘?’的位置,然后从此位置向前寻找‘.’号,中间部分既是扩展名。


<?php
function findFileTypeFromUrl( $url )
{
if( $url == "" )
  return false;

$r = strpos($url, '?');

if( $r != false )
{
  $l = strrpos( substr($url, 0, $r), '.');
  //echo '1';
  return substr($url, $l+1, $r-$l-1);
}
else
{
  $l = strrpos($url, '.');
  //echo '2';
  return substr($url, $l+1);
}
}
?>



2.在 HTML 语言中,页面头部的 meta 标记可以用来输出文件的编码格式,以下是一个标准的 meta 语句
<META http-equiv='Content-Type' content='text/html; charset=gbk'>
请使用 PHP 语言写一个函数,把一个标准 HTML 页面中的类似 meta 标记中的 charset 部分值改为 big5
请注意:
(1) 需要处理完整的 html 页面,即不光此 meta 语句
(2) 忽略大小写
(3) ' 和 " 在此处是可以互换的
(4) 'Content-Type' 两侧的引号是可以忽略的,但 'text/html; charset=gbk' 两侧的不行
(5) 注意处理多余空格

思路:这个写的比较弱,就替换而已。


<?php
function replaceCharset( $string )
{

    echo preg_replace( "/(\<meta\40+http\-equiv\=[\'|\"]?content\-type[\'|\"]?\40+content\=[\'|\"]text\/html;\40*charset\=)(gbk)[\'|\"]\40*\>/i","\${1}big5>",$string );
}


3. 写一个函数,算出两个文件的相对路径
如 $a = '/a/b/c/d/e.php';
$b = '/a/b/12/34/c.php';
计算出 $b 相对于 $a 的相对路径应该是 ../../c/d将()添上

思路:从两个文件的根目录开始比较,找到不一致的地方,然后计算第一个文件需要返回至此的‘../’步数,再就是打开另一个文件的目录路径。函数返回-1表示两个路径完全一致。


<?php
function findDirDiff($a, $b)
{
    if( $a{0} != '/' || $b{0} != '/' )
    {
        return false;
    }
   
    $a_array = explode('/', $a);
    $b_array = explode('/', $b);
   
    $a_size = count($a_array)-1;
    $b_size = count($b_array)-1;
       
    for( $i=0 ; $i <= $a_size; $i++)
    {
        if( (!isset($b_array[$i])) || $a_array[$i] != $b_array[$i] )
        {
            $i--;
            break;
        }
    }
   
    $a_upSteps = $a_size - $i;
       
    if( $a_upSteps == -1)
    {
        return -1;
    }
   
    for( $i++; $i < $b_size ; $i++ )
    {
        $b_upDir .= '/'.$b_array[$i];
    }
   
    return str_repeat('../', $a_upSteps-1).substr($b_upDir,1);
}


4.简要说明PHP的垃圾回收机制

答:引用计数。引用数为零时即销毁。

5.如何高并发写文件?

答:加锁。一种可以用flock()来操作,还是就写一个xxx.lock的文件或目录作为锁。有锁时等待,写入时加锁,写完释放锁。高并发可以写入副本,再合并文件,这样会比较复杂一点。

6.找猴王。N个猴子围成一圈,从第一开始报数,1、2、3...,报M者退出,然后重新报数,M者退出,重复此操作直到剩下一只猴,此猴为猴王,问猴王的编号?

思路:猴子看成元素值为1,2,3...N的一维数组。M%N求余,余数即本轮退出者,unset()此元素,继续下一轮,直到数组元素为一,此元素的值即为猴王编号。在M%N过程中,N的数目为剩下猴子的总数,每轮递减一。PHP注意点:使用array_splice()而不是unset(),array_splice()的key值会自动计算,而unset()则保持原始的索引。

PHP语言: 找猴王

<?php
/**
* 找猴王。N个猴子围成一圈,从第一开始报数,1、2、3...,报M者退出,然后重新报数,M者退出,重复此操作直到剩下一只猴,此猴为猴王,问猴王的编号?
*/
function findKing($n, $m)
{
    $q = range(1, $n);
   
    while( ($n=count($q)) > 1 )
    {
        array_splice($q, $m%$n-1, 1);
    }
   
    return $q[0];
}

2009/03/06

沉浮的兄弟

《疯狂的赛车》插曲:搞笑黑社会之《沉浮的兄弟》。


《沉浮的兄弟》

词:芊合

曲:戎祥

踏入江湖是我的命

不是甘愿做坏子

做兄弟好过时

打刚(每天)穿金又戴银

有时嘛会手头紧

结拜兄弟逗撒挺(帮忙过难关)

那是遇到垃圾的兄弟

丫撒不鲁归大堆(烂七八糟一大堆)

谁知命运的安排

乎阮(让我)失败一次搁(又)一次

拿出兄弟的勇气

总会等到出头天


简评:

这是一首新创的闽南风格的歌曲,戎祥在电影《疯狂的赛车》中饰演一位台湾黑社会老大,就是那个胖子。为了这部电影,他创作并演唱的了这首风格独特的歌曲,使得其在剧中的人物更具喜剧和搞笑色彩,为电影增添了许多别样的味道,看过之后,依然会为那些镜头,那歌声所征服!
(以上内容均来自互联网)

2009/02/25

cookie读写类

JavaScript语言: cookie操作代码

smartclick_Cookie = {

    get: function(name) {
        var cookieValue = null;
        if (document.cookie && document.cookie != '') {
            var cookies = document.cookie.split(';');
            for (var i = 0; i < cookies.length; i++) {
                var cookie = smartclick_Cookie.trim(cookies[i]);
                // Does this cookie string begin with the name we want?
                if (cookie.substring(0, name.length + 1) == (name + '=')) {
                    cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
                    break;
                }
            }
        }
        return cookieValue;
    },
    set: function(key, value, ttl, path, domain, secure) {
        cookie = [key+'='+    encodeURIComponent(value),
                   'path='+    ((!path   || path=='')  ? '/' : path),
                   'domain='+  ((!domain || domain=='')?  window.location.hostname : domain)];
       
        if (ttl)         cookie.push( 'expires='+smartclick_Cookie.hoursToExpireDate(ttl));
        if (secure)      cookie.push('secure');
       
        return document.cookie = cookie.join('; ');
    },

    //@param integer    ttl        Time To Live (hours)
    hoursToExpireDate: function(ttl) {
        if (parseInt(ttl) == 'NaN' ) return '';
        else {
            now = new Date();
            now.setTime(now.getTime() + (parseInt(ttl) * 60 * 60 * 1000));
            return now.toGMTString();
        }
    },
    trim: function( text ) {
        return (text || "").replace( /^\s+|\s+$/g, "" );
    }
}

几点说明:
1.ttl生存期时间单位是小时。
2.get方法的原理是字符串匹配,对[key=]value的中括号部分进行匹配,优于使用正则进行匹配,正则如有特殊字符的情况会很麻烦。

2009/02/21

周末看了两部电影,歌舞青春3和史密斯夫妇


晚上拖着看了看《歌舞青春3》,比较喜欢这部个中文名字,还是比较感慨老美的,能拍出这样的电影。记得大宝曾经说过,青春是要挥霍的。年少时候还是感性一点嘛,这样以后能够多回忆一些东西。




《史密斯夫妇》,恩,属于老早就上映了自己一直没看的电影。08暑假才看《疯狂的石头》,觉得宁浩很NB,所以《疯狂的石头》一上映就看,肯定不后悔。喜欢朱利皮特,好莱坞模范夫妻啊,是不是挺羡慕的?


Posted by Picasa

2009/02/18

最近看了本书《赚钱机器,Money Machine》

笔记

1.财富的定义:停止你现在的工作,能够继续生存多久?

2.做有积累性的工作。无积累性的工作:有十年出租车驾龄的司机和一天驾龄的司机的价格是一样的,别人不会因为你开了十年而多付钱。

3.使用你的钱来赚钱。

4.终极目标:打造属于你的赚钱机器,最终得到财富自由和时间自由。

5.没有捷径,勤奋努力的工作吧(个人想法)。

晚上两个小时瞎倒腾,原来IE设置了代理。。。

现象
1.写python使用urllib2模块,出现如下错误:urllib2.URLError: <urlopen error (10054, 'Connection reset by peer')>。

2.朋友汇款,使用招行专业版无法登陆,具体表现为,“通讯故障(#12):(*5)请检查您的通讯线路”。

检测网络,傲游浏览器一直可以上网、试试火狐也可以、飞信一直可以使、ping命令可以ping通,纳闷啊,反复google,检查本机服务,登陆路由器更改设置、更改网络连接、关闭防火墙、切换有线无线。。。未果,后来无意点开IE,无法打开网页,不会是设置了代理了吧?果然是!顿时泪奔,一晚上就浪费了啊,还以为python有问题,真可以把IE拖出去斩了!

2009/02/14

堆排序,C版


#include <stdio.h>
#include <math.h>


#define LEFT(i)        ((i)<<1)
#define RIGHT(i)    (((i)<<1) + 1)

void max_heapify(int a[], int i, int heapsize);
void heap_sort(int a[], int heapsize);
void build_max_heap(int a[], int heapsize);
void exchange(int *x, int *y);

//交换两个数的值
void exchange(int *x, int *y) {
    int temp;

    temp = *x;
    *x = *y;
    *y = temp;
}

//保持最大堆性质
void max_heapify(int a[], int i, int heapsize) {
    int left, right, largerest;

    left = LEFT(i);
    right = RIGHT(i);

    if (left <= heapsize && a[left]>a[i])
    {
        largerest = left;
    }else{
        largerest = i;
    }

    if (right <= heapsize && a[right]>a[largerest])
    {
        largerest = right;
    }

    if(largerest != i) {
        exchange(&a[i], &a[largerest]);
        max_heapify(a, largerest, heapsize);
    }

}

//建造最大堆
void build_max_heap(int a[], int heapsize) {
    int i;

    for (i=(int)ceil(heapsize/2); i >=1 ; i--)
    {
        max_heapify(a, i, heapsize);
    }
}

//堆排序
void heap_sort(int a[], int heapsize) {

    //build heap
    build_max_heap(a, heapsize);

    while(heapsize>1)
    {
        //exchange max
        exchange(&a[1], &a[heapsize]);
        heapsize--;
        max_heapify(a, 1, heapsize);
    }
   
}

int main() {
    int a[] = {0,    2,        0,        23,        38,        19,
                    98,        203,    803,    3,        78,
                    34,        68,        49,        9,        55};
   
    int array_size = sizeof(a)/sizeof(int);
    int i,heapsize;

    heapsize = array_size - 1;

    heap_sort(a, heapsize);
   
    //打印排序后的数组
    for (i=1; i<=heapsize ; i++)
    {
        printf("%d\t",a[i]);
    }
    printf("\n");
    getchar();
    return 0;

}

2009/02/06

支持中文的截取字符函数,不同编码下中文字符的范围一目了然

有时候经常需要查找某个编码下中文字符的编码范围,下面这个函数一目了然,省事!

PHP语言: 中文截取

<?php
/*
* 中文截取,支持gb2312,gbk,utf-8,big5
*
* @param string $str 要截取的字串
* @param int $start 截取起始位置
* @param int $length 截取长度
* @param string $charset utf-8|gb2312|gbk|big5 编码
* @param $suffix 是否加尾缀
*/
public function csubstr($str, $start=0, $length, $charset="utf-8", $suffix=true)
{
    if(function_exists("mb_substr"))
        return mb_substr($str, $start, $length, $charset);

    $re['utf-8'] = "/[\x01-\x7f]|[\xc2-\xdf][\x80-\xbf]|[\xe0-\xef][\x80-\xbf]{2}|[\xf0-\xff][\x80-\xbf]{3}/";
    $re['gb2312'] = "/[\x01-\x7f]|[\xb0-\xf7][\xa0-\xfe]/";
    $re['gbk'] = "/[\x01-\x7f]|[\x81-\xfe][\x40-\xfe]/";
    $re['big5'] = "/[\x01-\x7f]|[\x81-\xfe]([\x40-\x7e]|\xa1-\xfe])/";

    preg_match_all($re[$charset], $str, $match);
    $slice = join("",array_slice($match[0], $start, $length));
    if($suffix) return $slice."…";
   
    return $slice;
}
?>