【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 Modifiers)
i -可同時匹配大小寫字母
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。