1. 程式人生 > >php面試中的經典問題

php面試中的經典問題

本文講述14個經典的php面試題.

問題一

問題描述

考慮下面程式碼:

$str1 = 'yabadabadoo';
$str2 = 'yaba';
if (strpos($str1,$str2)) {
    echo "\"" . $str1 . "\" contains \"" . $str2 . "\"";
} else {
    echo "\"" . $str1 . "\" does not contain \"" . $str2 . "\"";
}

輸出的結果是什麼??為什麼會出現這個結果?? 如何處理這種情況??

問題解答

輸出結果為:

"yabadabadoo" does not contain "yaba"

這個問題考察的是”strpos()”的使用.
這個函式返回變數$str2在$str1中的位置.
如果未找到就返回false.
但是, 本次呼叫時, 這個函式返回的值為0,
對於if語句來說, 0等同於false.

對於這種情況, 需要在if語句中判斷函式返回值是否為false, 修改的程式碼如下:

$str1 = 'yabadabadoo';
$str2 = 'yaba';
if (strpos($str1,$str2) !== false) {
    echo "\"" . $str1 . "\" contains \"" . $str2 . "\"";
} else {
    echo "\"" . $str1 . "\" does not contain \"" . $str2 . "\"";
}

注意, 在這裡我們”!==”操作符, 而不是”!=”操作符.
如果我們使用”!=”, 我們就遇到這樣一個問題, 0為強制轉化為布林表示式時, 0對應的是false.
所以”0 != false”的結果為”false”.

問題二

問題描述

下面的程式碼的輸出結果是什麼??

$x = 5;
echo $x;
echo "<br />";
echo $x+++$x++;
echo "<br />";
echo $x;
echo "<br />";
echo $x---$x--;
echo "<br />";
echo $x;

問題解答

輸出結果是:

5
11
7
1
5

本題考察”後++”和”後–”的使用與”++”操作符和”+”操作符的優先順序.

“後++”和”後–”先返回數值, 然後執行加一或者減一操作.
當同時出現”++”和”+”操作符時, 因為”++”操作符比”+”操作符高, 所以先執行”++”操作, 後執行”+”操作.

問題三

問題描述

執行完下面的程式碼後, 變數”$a”和變數”$b”的值時多少??

$a = '1';
$b = &$a;
$b = "2$b";

問題解答

變數”$a”和變數”$b”的值都將等於字串”21”.
在執行程式碼”$b = &$a;”時, 變數”$b”就賦值為變數”$a”的引用, 變數”$b”修改時, 變數”$a”的值也將修改.
當變數賦值是出現雙引號時, php將執行雙引號中的表示式, 即”2$b”的結果實際為字串”2”和變數”$b”的連線, 也就是字串”21”.

問題四

問題描述

下面各行的輸出結果是什麼???

var_dump(0123 == 123);
var_dump('0123' == 123);
var_dump('0123' === 123);

問題解答

執行的結果如下:

bool(false)
bool(true)
bool(false)

對於語句”var_dump(0123 == 123)”, 輸出結果為”bool(false)”.
因為以0開頭的陣列在php直譯器看來, 是八進位制數字.
八進位制的”123”與十進位制的”123”不相等.

對於語句”var_dump(‘0123’ == 123)”, 其輸出結果為”bool(true)”.
因為字串”0123”與數值”123”比較時, 字串”0123”將自動轉化為數值型, 字串中的”0”將被忽略.
所以這個字串將被轉化為數值型別的”123”. 這個數值與數值”123”相等, 最後返回的結果為true.

對於語句”var_dump(‘0123’ === 123)”, 其輸出結果為”bool(false)”.
在這個語句中引入了嚴格比較符”===”, 這個比較符會先比較兩個變數的資料型別.
對於當前語句而言, 前者為字串, 後者為數值型, 兩個變數的型別不同, 所以返回false.

問題五

問題描述

下面的程式碼的結果是什麼???有什麼問題???如何修改??

$referenceTable = array();
$referenceTable['val1'] = array(1, 2);
$referenceTable['val2'] = 3;
$referenceTable['val3'] = array(4, 5);

$testArray = array();

$testArray = array_merge($testArray, $referenceTable['val1']);
var_dump($testArray);
$testArray = array_merge($testArray, $referenceTable['val2']);
var_dump($testArray);
$testArray = array_merge($testArray, $referenceTable['val3']);
var_dump($testArray);

問題解答

輸出結果如下所是:

array(2) { [0]=> int(1) [1]=> int(2) }
NULL
NULL

同時將會出現兩個警告:

Warning: array_merge(): Argument #2 is not an array
Warning: array_merge(): Argument #1 is not an array

本題的關鍵是, 如果”array_merge()”函式的兩個引數中有一個不是陣列型別, 這個函式的返回值將返回”NULL”.
在一般邏輯下, 形如語句”array_merge($someValidArray, NULL)”的結果為”$someValidArray”,
然而, 這個函式實際的返回結果是”NULL”, 而且, 這一點在php的官方文件中也很少提到.

As a result, the call to testArray=arraymerge(testArray, referenceTable[val2])evaluatestotestArray = array_merge(testArray,3)and,since3isnotoftypearray,thiscalltoarraymerge()returnsNULL,whichinturnendsupsettingtestArray equal to NULL.
Then, when we get to the next call to array_merge(), $testArray is now NULL
so array_merge() again returns NULL.
(This also explains why the first warning complains about argument #2
and the second warning complains about argument #1.)

執行語句”$testArray = array_merge($testArray, $referenceTable[‘val2’])”時,
這個語句將轉化為”$testArray = array_merge($testArray, 3)”.
由於上面提到的原因, 變數”$testArray”的值被賦值為”NULL”.
執行語句”$testArray = array_merge($testArray, $referenceTable[‘val3’]);”時,
這個語句等同於”$testArray = array_merge(NULL, $referenceTable[‘val3’]);”.
這個語句中, 第一個引數的值為NULL, 不是陣列型別, 函式呼叫的結果為”NULL”.
所以, 最後變數”$testArray”的值為”NULL”.
這也說明了, 為什麼兩個警告中, 一個時引數2, 一個是引數1了.

面對這種情況, 修改的措施也是簡單的.
直接對引數進行型別轉化, 我們就可以實現原有的要求:

$testArray = array_merge($testArray, (array)$referenceTable['val1']);
var_dump($testArray);
$testArray = array_merge($testArray, (array)$referenceTable['val2']);
var_dump($testArray);
$testArray = array_merge($testArray, (array)$referenceTable['val3']);
var_dump($testArray);

這樣的輸出結果如下:

array(2) { [0]=> int(1) [1]=> int(2) } 
array(3) { [0]=> int(1) [1]=> int(2) [2]=> int(3) } 
array(5) { [0]=> int(1) [1]=> int(2) [2]=> int(3) [3]=> int(4) [4]=> int(5) }

問題六

問題描述

下面程式碼輸出的結果是什麼??為什麼??

$x = true and false;
var_dump($x);

問題解答

出乎意料的, 上面的程式碼將輸出”bool(true)”, 看似”and”操作符表現的跟”or”操作符相同 .

The issue here is that the = operator takes precedence over the and operator in order of operations, so the statement $x = true and false ends up being functionally equivalent to:

事實上, “=”操作符的優先順序比”and”操作符高.
因此, 語句”$x = true and false”可以等同下面語句:

$x = true;       // 將"$x"變數賦值為true, 由於賦值成功, 返回true.
true and false;  // 結果是false, 但是這個結果與$x無關.

為了使自己的表示式更加清晰, 適當新增括號是一個很好的習慣.
例如, 形如上面的表示式”$x = true and false”用”$x = (true and false)”代替,
那麼”$x”就被設定為”false”了.

問題七

問題描述

下面執行下面的語句, 變數”$x”的值為:

$x = 3 + "15%" + "$25"

問題解決

變數”$x”的值為18.

Here’s why:

PHP supports automatic type conversion based on the context in which a variable or value is being used.

php支援根據語境自動變數型別轉化.

如果你在一個表示式中使用算術運算, 並且這個表示式中包含字串.
那麼這些字串將被轉化為相應的數字, 以完成算術運算.
如果一個字串由數字開頭, 那麼這個字串將忽略非數字部分, 將數字部分的字元轉化為相應的數值.
如果一個字串以非數字開頭, 那麼這個字串將被轉化為0.

基於上面的原因, 字串”15%”將被轉化為”15”, 字串”$25”將被轉化為”0”.
那麼原來的計算表示式”\$x = 3 + “15%” + “\$25”“將轉化為”\$x=3+15+0”, 最後的結果為”18”.

問題八

執行下面程式碼後, 變數”$text”的值是什麼, 語句”strlen($text)”的返回值是什麼??

$text = 'John ';
$text[10] = 'Doe';

執行完上面的程式碼, 變數”$text”的值為”John D”, 即字串”john”後面跟著五個空格, 然後加一個字元”D”.
並且程式碼”strlen($text)”的返回值為11.

這裡有兩點需要注意:

首先, 變數”$text”是一個字串, 設定這個變數中的一個元素的值, 就是設定這個變數中的一個字元.
程式碼”$text[10] = ‘Doe’”, 用於替換的字元為原字元中的第一個, 即”Doe”中的’D’.

第二, 程式碼”$text[10] = ‘Doe’”執行時, 將修改變數’$text’的第11個字元, 將其設定為’D’.
更重要的是, 原始字串的長度為5, 對於其他編譯器或者直譯器而言, 這種操作會出現陣列越界情況.
但是對於php而言, 這個操作是允許的.
php會自動適應這種情況, 並將其他字元位置置空.

問題九

問題描述

“PHP_INT_MAX”是php的一個常量, 用於標識所支援的最大整數(這個值與php的版本和作業系統的架構有關).

假設程式碼”var_dump(PHP_INT_MAX)”的輸出值為”9223372036854775807”.

依據上面這種情況, 下面的程式碼的執行結果是什麼??

var_dump(PHP_INT_MAX + 1)
var_dump((int)(PHP_INT_MAX + 1))

問題解答

程式碼”var_dump(PHP_INT_MAX + 1)”的結果將被轉化為double型別, 在上面的情況中, 輸出的結果為”double(9.2233720368548E+18)”.
這個問題的關鍵是考察面試者對於php對於大整數的處理, 即將整型無法處理的資料轉化為double型別.

程式碼”var_dump((int)(PHP_INT_MAX + 1))”將輸出結果為一個負數, 在上面那種情況下, 輸出的結果為”int(-9223372036854775808))”.

問題十

問題描述

如何對一個字串陣列根據值在忽略大小寫的情況下進行排序, 並不打亂鍵與值的關係.
例如給出下面的陣列:

array(
    '0' => 'z1',
    '1' => 'Z10',
    '2' => 'z12',
    '3' => 'Z2',
    '4' => 'z3',
)

排序完的結果為:

array(
    '0' => 'z1',
    '3' => 'Z2',
    '4' => 'z3',
    '1' => 'Z10',
    '2' => 'z12',
)

The trick to solving this problem is to use three special flags with the standard asort() library function:

解決這個問題的關鍵是, 在”asort()”庫函式中設定特殊的標識:

asort($arr, SORT_STRING|SORT_FLAG_CASE|SORT_NATURAL)

函式”asort()”函式是標準函式”sort()”的一個變形, 這個函式會保持原有資料的鍵值關係.
三個標識”SORT_STRING”, “SORT_FLAG_CASE”和”SORT_NATURAL”設定了排序的要求,
將元素視為字串, 忽略大小寫, 保持原有的鍵值關係.

注意, 使用函式”natcasesort()”並不能得到預期的效果, 因為它會打亂原有的鍵值關係.

問題十一

問題描述

在php中, PEAR是什麼???

問題解答

PEAR(PHP Extension and Application Repository)是一個可複用的php元件庫.
這個資源庫中包含了各種各樣的php程式碼摘要和庫.

PEAR同時提供了一個自動下載包的命令列工具.

問題十二

What are the differences between echo and print in PHP?

問題描述

在php中”echo”和”print”的區別是什麼???

echo and print are largely the same in PHP. Both are used to output data to the screen.

問題解答

在php中, “echo”和”print”有著及其相似的功能.
他們都能將資料展現在螢幕上.

他們的不同如下所是:

The only differences are as follows:

  • “echo”使用時, 沒有返回值, 而”print”會返回1. 這也使得”print”可以在表示式中使用.
  • “echo”可以接受多個引數, 但是, 這種方式使用很少. “print”只接收一個引數
  • “echo”是一個關鍵字, 而”print”是一個特殊的函式.

問題十三

問題描述

下面的程式碼段的結果是什麼:

$v = 1;
$m = 2;
$l = 3;

if( $l > $m > $v){
    echo "yes";
}else{
    echo "no";
}

問題解答

一般人會認為3>2>1, 那麼最後輸出的結果為”yes”.
事實上, 最後輸出的結果為”no”.

首先, 式子”$l > $m”將被執行, 並返回一個布林值1, 即true.
接著比較這個布林值和一個整型1, 即式子等同於”bool(1) > $v”, 結果為NULL, 所以最後的結果是”no”.

問題十四

問題描述

當執行完下面的程式碼後, 變數”$x”的值是什麼?

$x = NULL;

if ('0xFF' == 255) {
    $x = (int)'0xFF';
}

問題解答

最後的答案既不是NULL, 也不是255.
最後的結果是”$x”為0.

首先, 我們需要判斷表示式“‘0xFF’ == 255”的結果是true還是’false’.
當一個十六進位制的字串與一個整型資料比較時, 這個字串將轉為一個整型.
在內部, php會使用”is_numeric_string”判斷這個字串, 並將它轉化為一個整型(因為另一個時引數時整型).
在這種情況下, 字串”0xFF”將轉化為255.
這時, 255與255比較, 結果為true.
這種情況只支援十六進位制的字串, 不支援八進位制和二進位制的字串.

變數’$x’的值並不是’0xFF’的整型值.
在顯式的將字串轉化為整型時, 底層將使用”convert_to_long”函式, 而不是”is_numeric_string”函式.
函式”convert_to_long”對字串進行轉化時, 從左往右依次轉化, 直到遇到第一個非數值字元.
對於’0xFF’字元, 第一個非數字字元是’x’.
那麼整個轉化過程的結果為’0’.
所以”(int)’0xFF’”的結果是0, 即’$x’的值為0.