Ruanyifeng.com/blog/2008/12/the_perils_of_javaschools.html

指针和递归式计算机语言难以理解的地方。

PHP中没有指针的概念,但递归仍是重要内容

题目:求1N的和?

方法一:

function sum($n){

for ($i=1,$sum=0; $i <=$n; $i++) {

$sum=$sum+$i;

}

return $sum;

}

echo sum(100);

方法二:

array_sum()计算数组中所有值的和

*/

function sum1($n){

return array_sum(range(1,$n));

}

echo sum1(100);

方法三:

function sub($n){

if ($n>1) {

return sub($n-1)+$n;

}

else

{

return 1;

}

}

echo sub(100);

递归打印级联目录

<?php

/****

递归打印级联目录

****/

//打印一层目录----如果还是目录,继续调用自身,直到不是目录

function recdir($path){

$handle = opendir($path);  //打开目录,获取文件句柄

while (($res = readdir($handle)) !== false) {  读到的文件不等于false,则输出目录名

       //首先读到的是当前目录和上级目录 ,要过滤掉

if ($res =="." || $res =="..") {

continue;

}

echo $res."<br/>";

       //如果$res还是目录,继续调用

if (is_dir($path."/".$res)) {

recdir($path."/".$res);

}

}

closedir($handle);

}

recdir("./");

?>

函数调用

开始执行 碰到return 或者执行到最后结束

递归调用函数,耗费资源,如果层数太深,不宜用递归

递归必须有一个终止条件

仿tree

<?php

function recdir($path,$lev){  //增加一个层次计数器,每进入一层加一

$handle = opendir($path);

while (($res = readdir($handle)) !== false) {

if ($res =="." || $res =="..") {

continue;

}

echo '--'.str_repeat('----', $lev).$res."<br/>";

if (is_dir($path."/".$res)) {

recdir($path."/".$res,$lev+1);

}

}

closedir($handle);

}

recdir(".",1);

?>

递归创建普通目录

创建目录

echo mkdir("./".date("ymd"));

echo mkdir("./b/c")?"ok":"fail";

失败,如果父目录不存在,子目录不能创建

Warning: mkdir() [function.mkdir]:

No such file or directory in C:\wamp\www\eshop\20140318\01_.php on line 6

Fail

第一种方法:

自定义函数,完成一次创建.a/b/c/d/e 级联目录

function createDir($path){

   //判断是否是目录is_dir()

if (is_dir($path)) {//如果目录已经存在,直接返回true

return true;

}

//截取父目录dirname(),如果父目录存在,直接创建子目录

//目录已经存在,创建子目录

if (is_dir(dirname($path))) {

return mkdir($path);

}

//父目录不存在,创建父目录

else{

createDir(dirname($path));

return mkdir($path);

}

}

createDir("./z/x/c/v/b/n/m");

第二种:

1>如果目录存在,直接返回

2>如果目录不存在,创建:

只需要父目录存在,或者创建了父目录,才创建子目录

*/

/*function mk_dir($path){

if (is_dir($path)) {

return true;

}

       //目录不存在,判断父目录是否存在、

        //父目录存在则创建子目录,不存在,则创建目录

if(is_dir(dirname($path)) || mk_dir(dirname($path))){

mkdir($path);

return true;

}

else

return false;

}

mk_dir("q/w/e/r");

第三种:

mkdir(pathname)PHP5.0,增加了第三个参数可以级联创建目录

第二个参数,是权限*/

mkdir("./new/new1/a/c/v",0777,true);

递归删除目录:

<?php

/****

递归删除目录

****/

function del_dir($path){

//不是目录,直接返回

if (!is_dir($path)) {

return false;

}

   //是目录,打开目录

$handle = opendir($path);

   //读取目录

while (($row = readdir($handle)) !==false) {

       //过滤当前目录和上级目录

if ($row == "." || $row=="..") {

continue;

}

      // 读到的不是目录,则是普通文件,直接删除

if (!is_dir($path."/".$row)) {

unlink($path."/".$row);

}

       //如果还是目录,再调用函数删除

else

{

del_dir($path."/".$row);

}

}

//关闭文件资源

closedir($handle);

//删除目录

rmdir($path);

return true;

}

del_dir("./z");

?>

递归和迭代的区别:

<?php

function rec_sum($n){

if ($n>1) {

return $n+rec_sum($n-1);

}

else

return 1;

}

//在递归调用计算出结果前,共有十个函数同时执行

echo rec_sum(10);

//迭代实现

//迭代就是在某个范围内,反复执行完成相同工作

//递归 耗费资源

function it_sum($n){

for ($i=1; $i < $n; $i++) {

$sum+=$i;

}

return $sum;

}

?>

迭代创建目录

<?php

/****

迭代创建级联目录

借助栈,递归都可以转化为迭代

****/

function mk_dir($path){

$arr = array();

while (!is_dir($path)) {

//传入的不是目录,放入数组

array_push($arr, $path);

$path = dirname($path);

}

if (empty($arr)) {

return true;

}

else

{

while (count($arr)) {

mkdir(array_pop($arr));

}

return true;

}

}

mk_dir("./cc/dd/ee/ff");

?>

框架改进------递归转义:

利用系统函数转义:

<?php

if (!get_magic_quotes_gpc()) {

function _addslashes(&$v,$k){

$v = addslashes($v);

}

array_walk_recursive(&$_GET, '_addslashes');

array_walk_recursive(&$_POST, '_addslashes');

array_walk_recursive(&$_COOKIE, '_addslashes');

}

?>

引用传参:

$age = 10;

function grow($age){

$age+=1;

return $age;

}

echo grow($age);//11

echo $age;//10

$age = 10;

function grow($age){

$age+=1;

return $age;

}

echo grow(&$age);//11

echo $age;//11

引用传值

内部函数的$age 和全局的$age 指向同一个变量地址

内部变化,影响外部变化

违反了封装性,

函数运行讲究对外部环境没有副作用

&  传递的是地址*/

Warning: Call-time pass-by-reference has been deprecated;

If you would like to pass it by reference,

modify the declaration of grow().

If you would like to enable call-time pass-by-reference,

you can set allow_call_time_pass_reference to true

in your INI file in

PHP 5.0以上不推荐使用

在配置文件中

设置引用传参就警告

allow_call_time_pass_reference = on

error_reporting(E_ALL | E_STRICT)

PHP5.4 删除了这个引用传参功能

大于此版本,对此功能不支持了,

会出现fatal error

解决方法:

1. allow_call_time_pass_reference = on,并重启apache

2.不引用传参,自己写方法递归转义数组

利用递归实现转义

<?php

/****

递归转义数组

****/

$arr = array('a"b',array("'c'd",array('e"f')));

//先转义一维数组,再判断还是数组,在调用自身转义

function _addslashes($arr){

foreach($arr as $k=>$v){

if (is_string($v)) {

$arr[$k] = addslashes($v);

}

else if (is_array($v)) {

$arr[$k] = _addslashes($v);

}

}

return $arr;

}

print_r(_addslashes($arr));

//如果要改变全局$arr的值,需要重新赋值

?>

Array

(

   [0] => a\"b

   [1] => Array

       (

           [0] => \'c\'d

           [1] => Array

               (

                   [0] => e\"f

               )

       )

)

商城项目改进:

创建lib_base.php

// 递归转义数组

function _addslashes($arr) {

   foreach($arr as $k=>$v) {

       if(is_string($v)) {

           $arr[$k] = addslashes($v);

       } else if(is_array($v)) {  // 再加判断,如果是数组,调用自身,再转

           $arr[$k] = _addslashes($v);

       }

   }

   return $arr;

}

init.php中修改:

// 过滤参数,用递归的方式过滤$_GET,$_POST,$_COOKIE,暂时不会

$_GET = _addslashes($_GET);

$_POST = _addslashes($_POST);

$_COOKIE = _addslashes($_COOKIE);

测试递归转义

$t1 = $_GET["t1"];

$t2 = $_GET["t2"];

$sql = "insert into test(t1,t2) values('$t1','$t2')";

var_dump($mysql->query($sql));*/

var_dump($mysql->autoExcute('test',$_GET,'insert'));