1. 程式人生 > >【PHP】高階面試題之十萬個為什麼?(一)

【PHP】高階面試題之十萬個為什麼?(一)

成功不是將來才有的,而是從決定去做的那一刻起,持續累積而成。

這裡寫圖片描述

現在也已經工作三年時間了,PHP在平時工作中天天都會使用,但是內心總是感覺差點什麼,覺得自己對PHP這門語言瞭解的還不夠,故下定決心,整理了一下平時工作所學所用,提出各種各樣的問題,然後再一一的解決這些問題,加深自己對PHP這門語言的理解!!!

1、substr()、strpos()、strlen()、htmlentities() 處理字串時依據的編碼方式是相同的?

答:不是相同的,substr() 處理中文會亂碼

2、如果一個指令碼的編碼是 ISO-8859-1,則其中的字串也會被編碼為 ISO-8859-1?

答案:是的

3、一個布林值 Boolean 的 true 被轉換成 string 的 “ 1 ”,false 被轉換成空字串?

$boolean_Foo = (boolean)true;
$boolean_Fcc = (boolean)false;  
echo (string)$boolean_Foo;    // echo '1';
echo (string)$boolean_Fcc;    // echo '';

4、PHP的字串在內部是位元組組成的陣列,用花括號訪問或修改字串對多位元組字符集很不安全?

解析:很多時候我們都使用 PHP字串 而php字串是如何組成的呢,這個估計很少人去了解~
其實PHP 字串就是 字元陣列 假設我們定義一個字串
$string ="hello world";
    //這個字串是由 h , e , l ,  l , o , 空格 , w ,o,r,l,d 這幾個字元組成,我們可以驗證一下看看:
    echo $string[1];   //  輸出結果是 e

    //擴充套件:1、那麼我們能不能去改變其中的某個值呢?
    $string[1] = "H";
    echo $string;  //  輸出結果是 hHllo world

    //2、如何我們將一個位置賦予多個值會怎樣呢?
    $string[1] = "HHHHH";
    echo $string;      //  輸出結果是 hHllo world 看來PHP做了安全處理

5、“ $@ ”將函式中所有引數當成單個字串,“ $* ”把函式的所有引數當一個數組?

答:都是取所有引數,前者是存到列表,後者作為一個字串(原理還不是很理解/(ㄒoㄒ)/~~)

6、PERL風格正則預設的非貪婪模式儘可能少的匹配所搜尋的字串?

答:不是儘可能少,而是儘可能多的匹配所搜尋的字串(詳解請引數:PHP -- Perl風格正則表示式)

7、{n,},n是一個非負整數,意思是至少匹配n次; ?等價於匹配長度{0,1} ?

答:{n,} 表示前面的原子出現不少於n次; ?標識前面的原子匹配0次或1次

8、在執行效率上 preg_match 比ereg的速度要略快一些嗎?

從執行效率上來對比POSIX風格的ereg和相容Perl風格的preg_match     
我們都知道ereg是PHP的正則函式,而preg_match 是perl移植過來的, 兩者的寫法上都有些區別。
現在我們從執行效率上看看兩者的區別為了讓時間上區別更明顯 我們講函式執行1000次 並對比3次看看他們的區別
public function index(){
    $datetime = "2008-08-03";
    $loopnum = 1000;
    $num  = 5;
    echo "從時間轉換來看各函式對字元處理效率:".'<br>';
    for ($k = 0; $k < $num; $k++){
            $time_start = $this->microtime_float();
            for($i = 0; $i < $loopnum; $i++){
                preg_match('/([/d]{4})-([/d]{2})-([/d]{2})/i', $datetime, $outarr);
                $result  = mktime(0, 0, 0, $outarr[2], $outarr[3], $outarr[1]);
            }
            $time_1 = $this->microtime_float();
            for($i = 0; $i < $loopnum; $i++){
                ereg ("([0-9]{4})-([0-9]{1,2})-([0-9]{1,2})", $datetime, $outarr);
                $result  = mktime(0, 0, 0, $outarr[2], $outarr[3], $outarr[1]);
            }
            $time_2 = $this->microtime_float();
            echo "1:preg_match: " . ($time_1 - $time_start) . "  ";echo '<br>';
            echo "2:ereg: " . ($time_2 - $time_1) . "  ";echo '<br>';
            echo '<hr />';
}
}

/**
 *  時間統計函式
 */
function microtime_float($time = null)
{
   list($usec, $sec) = explode(' ', $time ? $time : microtime());
   return ((float)$usec + (float)$sec);
}

實驗結果
從時間轉換來看各函式對字元處理效率:
1:preg_match: 0.012001037597656
2:ereg: 0.016000986099243

1:preg_match: 0.013000011444092
2:ereg: 0.018000841140747

1:preg_match: 0.012001037597656
2:ereg: 0.017000913619995

1:preg_match: 0.012001037597656
2:ereg: 0.017001152038574

1:preg_match: 0.013000011444092
2:ereg: 0.017000913619995

我們可以看出 在執行效率上 preg_match 還是比ereg的速度好略快一些
實際上在PHP手冊中 也有建議說:“注: 使用 Perl 相容正則表示式語法的 preg_match() 函式通常是比 ereg() 更快的替代方案。可見 PHP也是推薦使用preg_match的

9、POSIX相容正則沒有修正符,PERL相容正則中可能用到修正符?

答:正則表示式作為一個匹配的模版,是由原子(普通字元,例如a-z),有特殊功能的字元(元字元,例如*、+ 和?等),以及模式修正符三個部分組成。
修正符:
POSIX相容正則沒有修正符。
PERL相容正則中可能使用的修正符(修正符中的空格和換行被忽略,其它字元會導致錯誤):
i (PCRE_CASELESS):
匹配時忽略大小寫。
m (PCRE_MULTILINE):
當 設定了此修正符,行起始(^)和行結束($)除了匹配整個字串開頭和結束外,還分別匹配其中的換行符(\n)的之後和之前。
s (PCRE_DOTALL):
如 果設定了此修正符,模式中的圓點元字元(.)匹配所有的字元,包括換行符。沒有此設定的話,則不包括換行符。
x (PCRE_EXTENDED):
如 果設定了此修正符,模式中的空白字元除了被轉義的或在字元類中的以外完全被忽略。
e :
如果設 定了此修正符,preg_replace() 在替換字串中對逆向引用作正常的替換,將其作為 php 程式碼求值,並用其結果來替換所搜尋的字串。 只有 preg_replace() 使用此修正符,其它 PCRE 函式將忽略之。
A (PCRE_ANCHORED):
如 果設定了此修正符,模式被強制為“anchored”,即強制僅從目標字串的開頭開始匹配。
D (PCRE_DOLLAR_ENDONLY):
如 果設定了此修正符,模式中的行結束($)僅匹配目標字串的結尾。沒有此選項時,如果最後一個字元是換行符的話,也會被匹配在裡面。如果設定了 m 修正符則忽略此選項。
S :
當一個模式將被使用若干次時,為加速匹配起見值得先對其進行分析。 如果設定了此修正符則會進行額外的分析。目前,分析一個模式僅對沒有單一固定起始字元的 non-anchored 模式有用。
U (PCRE_UNGREEDY):
使 “?”的預設匹配成為貪婪狀態的。
X (PCRE_EXTRA):
模式中的任何反斜線後面跟上 一個沒有特殊意義的字母導致一個錯誤,從而保留此組合以備將來擴充。預設情況下,一個反斜線後面跟一個沒有特殊意義的字母被當成該字母本身。
u (PCRE_UTF8):
模 式字串被當成UTF-8。
注意:
模式修正符(Pattern Modifiersi     -可同時匹配大小寫字母
M     -將字串視為多行
S     -將字串視為單行,換行符做普通字元看待,使“.”匹配任何字元
X     -模式中的空白忽略不計    
U     -匹配到最近的字串
e     -將替換的字串作為表達使用

10、無論是 array(1, 2, 3) 還是array(1 => 2, 2=> 4)等,本質上都是hash_table?

答:在回答這個問題之前,我們需要了解一下什麼是hash_table?

Hash Table 是電腦科學中很重要的一種資料結構,其時間複雜度為O(1),主要是通過把關鍵字Key 對映到陣列中的一個位置來訪問記錄,所以速度相當快。對映函式稱為 Hash函式。

Hash Table 的實現步驟是:

1、建立一個固定大小的陣列用於存放資料

2、設計良好的 Hash 函式

3、通過 Hash 函式把資料按照關鍵字 key 對映到陣列中的某一個位置,並在此資料上進行資料存取

結論:無論是 array(1, 2, 3) 還是array(1 => 2, 2=> 4)等,本質上都是key=>value形式, array(1, 2, 3),實際上是 array(0=>1,1=> 2, 2=>3),所以它與array(1 => 2, 2=> 4)本質上都是hash_table。