笔试易入雷区
基础篇
1.写出如下程序的输出结果
<?php
$test = ‘aaaaaa’;
$abc = & $test;
unset($test);
echo $abc;
输出结果是“aaaaaa”分析如下:
首先PHP内置有一种规则是:当有两个变量同时指向一个内存地址时,这时若其中一个被销毁,但另一个仍然指向该地址。那么内存中存放的数据不会被回收机制处理。因此仍然输入aaaaaa。
网上别人的理解:
因为变量abc引用的是指向aaaaa的路径,而不是引用变量text本身。就好比路径是钥匙的话。现在$abc是配的钥匙, aaaaaa是门后面的内容。现在你毁坏了原装的钥匙,但是门后面的内容,和配的钥匙是不变的。因为还有变量指向aaaaaa,所以aaaaaa也不会被php回收机制销毁。
2.写出如下程序的输出结果
<?php
$count = 5;
function get_count(){
static $count = 0;
return $count++;
}
echo $count;
echo get_count();
echo get_count();
?>
上方代码答案是:5 0 1 。重点分析后两个:由于在函数内定义的是静态变量count,因此每次函数结束之后仍能保持原来的值。又由于是return $count++,所以第一次返回的是0,之后再在之前的基础上加一。
3.$GLOBALS[‘a’]与global ¥a的区别
<?php
$GLOBALS['var1']=5;
$var2=1;
function get_value(){
global $var2;
$var1 = 0;
return $var2++;
}
get_value();
echo $var1;
echo $var2;
?>
<?php
$var1 = 1;
$var2 = 2;
function test(){
global $var1, $var2;
$var2 = &$var1;
echo $var2;
$var2 = 'snsgou.com';
}
test(); // 输出 1
echo $var2; // 输出 2
echo $var1; // 输出 snsgou.com
?>
分析:global 其实是将全局变量 var1 和 var2 的引用赋给了局部变量 var1,var2,而后 全局变量 var1 的引用又赋给了局部变量 var2,因此局部变量 var2 的改变会影响到全局变量 va1。
附上参考链接:有关上述两者的区别
易错题
$a = "hello";
function test()
{
global $a;
$a = "huang";
echo $a;
}
echo $a;
test();
echo $a;
结果:hello huang huang
解析:第一个输出hello,毋庸置疑,因为函数体还没有执行;第二个输出是在函数体内的输出,由于使用了 global 关键字,将 $a 申明为了全局变量,因此函数内的局部变量 a 会被覆盖,自然是输出 huang,最后一个通过函数申明全局变量的方式改变了外面的 a ,因此也是输出 huang。
4.下面输出结果是多少?
$arr = array(0=>1,"aa"=>2, 3, 4);
foreach($arr as $key=>$val){
print($key == "aa" ? 5 : $val);
}
结果:5534
解析:遍历每一个元素的key看等不等于aa,等于就用5替代。当我告诉你答案是5534的时候,你会不会有点惊讶!难道0等于”aa”吗?是的,0就等于”aa”,这道题重点就考你这个。在PHP中两个值进行逻辑判断时,如果两个值的类型不一致PHP会自动把右边的值转换到左边的类型,然后再进行判断。因此”aa”转换整形等于0,自然也就等于左边的0了。
延伸思考:如果将 $key == “aa” 换成 ==“2aa”呢?结果又是如何。
5.请指出下面结果
$a = 3;
$b = 5;
if($a = 5 || $b = 7) {
$a++;
$b++;
}
echo $a . " " . $b;
结果:1 6
解析:执行结果是多少?如果你回答 6 8 or 4 6 or 6 6,那你就掉入陷阱了。
第一个陷阱,认为答案等于 4 6 。估计你粗心把 $a = 5 || $b = 7
看成 $a == 5 || $b == 7
,这是新手常犯的错误。
第二个陷阱,认为答案等于 6 8。 你识破了 $a = 5 || $b = 7
这个骗局,但你没有注意到,逻辑或里只要依次执行直到某个表达式结果为true,表达式后边的就不再执行,$a = 5
返回true,后边的$b=7就不执行了。
第三个陷阱,认为答案等于 6 6。 OK,你识破了 逻辑或的规则,于是$a=5
执行,$b=7
不执行,但是你没有考虑到这里是逻辑表达式,返回给$a的值是要转换为布尔值的。这样看。
所以经过以上三个陷阱,你应该知道答案是多少了,其实 $a
等于true以后,echo $a
输出就是1 ,$b
值不变,结果就是 1 6 。
解题方法:熟悉运算符的优先级,通过()来协助理解程序执行顺序。
6.输出结果
$a = count ("567") + count(null) + count(false);
echo $a;
结果:2
解析:如果你回答 3 or 1,恭喜,掉入陷阱了。
因为count(null)等于0,false也算一个值。所以count(false)等于1。
数组篇
数组作为 php 8大基本数据类型之一,其重要性不言而喻。下面将列举一些数组定义及使用过程中需要注意的地方。
a.以下情况数组键类型会发生强制转化:
- 包含有合法整型值的字符串会被转换为整型。例如键名 “8” 实际会被储存为 8。但是 “08” 则不会强制转换,因为其不是一个合法的十进制数值。
- 浮点数也会被转换为整型,意味着其小数部分会被舍去。例如键名 8.7 实际会被储存为 8。
- 布尔值也会被转换成整型。即键名 true 实际会被储存为 1 而键名 false 会被储存为 0。
- Null 会被转换为空字符串,即键名 null 实际会被储存为 “”。
b.清空数组后键值问题:
直接上例子
$arr = [32,232,11,32,'dff'];
foreach ($arr as $key => $value) {
unset($arr[$key]);
}
$arr[] = 4;
print_r($arr);
/*Array
(
[5] => 4
)*/
先思考一下,为什么键是从5开始呢?正常人的理解大概是数组清空后,再去将这个数组添加新元素,键会从0开始,但是结果并非如此。来看一下官方文档的说明:
如果给出方括号但没有指定键名,则取当前最大整数索引值,新的键名将是该值加上 1(但是最小为 0)。如果当前还没有整数索引,则键名将为 0。注意这里所使用的最大整数键名不一定当前就在数组中。它只要在上次数组重新生成索引后曾经存在过就行了
重点在最后一句话:注意这里所使用的最大整数键名不一定当前就在数组中。它只要在上次数组重新生成索引后曾经存在过就行了。
因此如果想重新从0开始索引,可以直接 unset($arr) ,或者使用 array_values() 新建一个数组。
算法篇
二、算法题
1. 使用 PHP 描述冒泡排序和快速排序算法,对象可以是一个数组
//冒泡排序(数组排序)
function bubble_sort($array)
{
$count = count($array);
if ($count <= 0) return false;
for($i=0; $i<$count; $i++){
for($j=$count-1; $j>$i; $j--){
if ($array[$j] < $array[$j-1]){
$tmp = $array[$j];
$array[$j] = $array[$j-1];
$array[$j-1] = $tmp;
}
}
}
return $array;
}
开发过程中遇到的真实案例
这个需求大概是这样的:前端要求接口返回的数据是按照二维数组中的某一个值来排序的(就比如代金券列表按照卡券减免金额从低到高排序)。之前是使用了 array_multisort 函数实现的。后面发现完全可以用冒泡排序代替啊。一个类似的 demo 如下:
function arr_bobble_sort($arr)
{
if(!is_array($arr)) {
throw new Exception('参数必须是数组类型');
}
$length = count($arr);
for ($i=0;$i<$length;$i++) {
for ($j=$length-1;$j>$i;$j--) {
if(strlen($arr[$j]['name']) > strlen($arr[$j-1]['name'])) {
$temp = $arr[$j];
$arr[$j] = $arr[$j-1];
$arr[$j-1] = $temp;
}
}
}
return $arr;
}
$cars = array
(
array('id'=>3,'name'=>'12345'),
array('id'=>4,'name'=>'123'),
array('id'=>5,'name'=>'12345645454'),
array('id'=>6,'name'=>'1145asd')
);
print_r(arr_bobble_sort($cars));
解析:这是一个需要按照二维数组名称 name 长度排序的案例,只需要修改一下交换条件即可。这样就实现了用冒泡排序完成根据二维数组某个值大小来排序的需求了。
//快速排序(数组排序)
function quick_sort($array) {
if (count($array) <= 1) return $array;
$key = $array[0];
$left_arr = array();
$right_arr = array();
for ($i=1; $i<count($array); $i++){
if ($array[$i] <= $key)
$left_arr[] = $array[$i];
else
$right_arr[] = $array[$i];
}
$left_arr = quick_sort($left_arr);
$right_arr = quick_sort($right_arr);
return array_merge($left_arr, array($key), $right_arr);
}
注意,for 循环的 $i 的初始值是1,因为是拿数组第一的值作为参考点的。。(每次都写成0 ) : )
2 .使用 PHP 描述顺序查找和二分查找(也叫做折半查找)算法,顺序查找必须考虑效率,
对象可以是一个有序数组
//二分查找(数组里查找某个元素)
function bin_sch($array, $low, $high, $k){
if ($low <= $high){
$mid = intval(($low+$high)/2);
if ($array[$mid] == $k){
return $mid;
}elseif ($k < $array[$mid]){
return bin_sch($array, $low, $mid-1, $k);
}else{
return bin_sch($array, $mid+1, $high, $k);
}
}
return -1;
}
//顺序查找(数组里查找某个元素)
function seq_sch($array, $n, $k){
$array[$n] = $k;
for($i=0; $i<$n; $i++){
if($array[$i]==$k){
break;
}
}
if ($i<$n){
return $i;
}else{
return -1;
}
}
3 . 写一个二维数组排序算法函数,能够具有通用性,可以调用 php 内置函数
//二维数组排序,
arr是数据,
a
r
r
是
数
据
,
keys 是排序的健值,$order 是排序规则,1 是升序,0是降序
function array_sort($arr, $keys, $order=0) {
if (!is_array($arr)) {
return false;
}
$keysvalue = array();
foreach($arr as $key => $val) {
$keysvalue[$key] = $val[$keys];
}
if($order == 0){
asort($keysvalue);
}else {
arsort($keysvalue);
}
reset($keysvalue);
foreach($keysvalue as $key => $vals) {
$keysort[$key] = $key;
}
$new_array = array();
foreach($keysort as $key => $val) {
$new_array[$key] = $arr[$val];
}
return $new_array;
}
都是基本又常见的算法题,好好看,好好练。
今天在刷题时发现了一个小坑,不小心就会栽进去。
当我们用echo指令输出布尔类型时,如果是true则输出的是1,false则什么也不输出。我们可以使用var_dump函数,获取它真正的数据类型。