第5天 PHP函數(shù)與遞歸

7. 函數(shù)

7.1. 函數(shù)的概念與作用

var_dump() 、sqrt()、floor() 、ceil() 在PHP中凡是帶()都可以理解為函數(shù)
函數(shù)分為系統(tǒng)函數(shù)和自定義函數(shù),系統(tǒng)函數(shù)是語言封裝好的,直接拿來使用即可,自定義函數(shù)需要事先定義,然后才能使用
函數(shù)不是數(shù)!
函數(shù)是一種代碼形式(語法形式),也即一種結(jié)構(gòu)。只要結(jié)構(gòu)****不執(zhí)行****,它是沒有任何意義的。
函數(shù)是將“若干行代碼”以一種語法形式包裝成的一個(gè)整體。
該整體可以做到“需要的時(shí)候就去執(zhí)行它”(就是執(zhí)行其中的若干行代碼)。
函數(shù)是解決在不同情形(不同代碼位置)下需要執(zhí)行相同代碼的有效方式——即所謂代碼重用。
入門:
輸出4行4列,5行5列,6行6列需要這么做:

image.png

改進(jìn):
image.png

7.2. 函數(shù)的定義與調(diào)用

定義語法形式:

image.png

說明
1,函數(shù)名的命名規(guī)則,跟變量名一樣;
2,定義函數(shù)的目的就是為了以后能夠調(diào)用;
3,調(diào)用函數(shù),其實(shí)就是執(zhí)行函數(shù)中代碼;
4,形參,其實(shí)就是變量,是只能在該函數(shù)內(nèi)部使用的變量;
5,實(shí)參,其實(shí)就是數(shù)據(jù),是會(huì)傳入函數(shù)內(nèi)部的數(shù)據(jù)(是一一對(duì)應(yīng)地賦值給形參變量);
<u>案例演示:</u>
寫一個(gè)函數(shù),可以給定一個(gè)半徑,求對(duì)應(yīng)圓面積。
image.png

<u>課堂練習(xí):</u>
寫一個(gè)函數(shù),可以給定長寬高,求對(duì)應(yīng)一個(gè)長方體的表面積。
image.png

7.3. 函數(shù)參數(shù)(重點(diǎn))

7.3.1. 形參(形式參數(shù))

就是定義函數(shù)的時(shí)候,在函數(shù)名后的小括號(hào)中給出的變量名。
形參,只能在函數(shù)內(nèi)部使用——即該變量的使用范圍僅僅局限于當(dāng)前函數(shù)內(nèi)部。
形參的本質(zhì)是變量!


image.png

7.3.2. 實(shí)參(實(shí)際參數(shù))

就是調(diào)用函數(shù)的時(shí)候,在函數(shù)名后的小括號(hào)中給出的數(shù)據(jù)值。
實(shí)參的本質(zhì)是數(shù)據(jù)!


image.png

7.3.3. 函數(shù)參數(shù)的傳值方式

含義:
實(shí)參變量的值,以什么方式傳給形參。
說明:
其前提是:實(shí)參是一個(gè)變量的情況。
所以其實(shí)這里討論的是:兩個(gè)變量的傳值方式問題。
默認(rèn)情況下是值傳遞。
可以使用“&”符號(hào)設(shè)定為引用傳遞,形式如下:

function  f1( $p1, &$p2, .... ){  
。。。。。
}

此時(shí),在函數(shù)內(nèi)部,對(duì)該形參變量改變其值,則對(duì)應(yīng)的實(shí)參變量(在函數(shù)外部)的值也改變了。
<u>案例演示:</u>

 //值傳遞
   function test1($a){
       $a=200;  //形參$a只能在內(nèi)部使用
   }
   $a=100;  // 實(shí)參
   test1($a);
   echo $a;   // 100  //輸出的是實(shí)參  
  //引用傳遞  形參和實(shí)參共用一個(gè)內(nèi)存地址
    function  test(&$a){
      //重新給形參賦值
      $a=200;     
    }
    $a=100;
    test($a);  //作用是給形參$a賦值
    echo $a;   //200

7.3.4. 形參的默認(rèn)值

形參可以設(shè)定默認(rèn)值。形式為:$形參名 = 某值。
設(shè)定默認(rèn)值的形參,只能放在沒有設(shè)定默認(rèn)值的形參的后面(右邊)。
設(shè)定了默認(rèn)值的形參對(duì)應(yīng)的實(shí)參可以不提供數(shù)據(jù),此時(shí)函數(shù)就會(huì)使用該默認(rèn)值當(dāng)做實(shí)參的值。

function  f1($p1,  $p2,  $p3 = 3,  $p4=true ){
//函數(shù)體語句塊
}
image.png

<u>案例演示:</u>
定義一個(gè)函數(shù),該函數(shù)可以計(jì)算給定半徑的球的體積,其中圓周率π默認(rèn)使用3.14,也可以根據(jù)不同精度的需要給定不同的圓周率。

image.png

7.4. 函數(shù)返回值(重點(diǎn))

含義:
一個(gè)函數(shù)在執(zhí)行結(jié)束時(shí),可以讓其返回一個(gè)數(shù)據(jù),這就是函數(shù)的返回值。
語法:
return 要返回的數(shù)據(jù);
說明:
1,一般情況下一個(gè)函數(shù)執(zhí)行結(jié)束都是需要返回一個(gè)數(shù)據(jù)值的。
2,函數(shù)也可以在執(zhí)行的中途返回?cái)?shù)據(jù),此時(shí),函數(shù)也是結(jié)束了的。
3,一個(gè)函數(shù)執(zhí)行得到的返回值,可以在任何需要數(shù)據(jù)的場(chǎng)合使用,跟使用一個(gè)變量數(shù)據(jù)一樣。
<u>演示:</u>
計(jì)算兩數(shù)的平方和與兩數(shù)的平方差相除的結(jié)果。

image.png

另外,return語句也可以不帶后面的數(shù)據(jù),此時(shí),就只是單純地結(jié)束函數(shù),并不返回?cái)?shù)據(jù)(也可以說返回null這個(gè)空數(shù)據(jù))。


image.png

7.5. 匿名函數(shù)

含義:
就是一個(gè)“定義時(shí)沒有名字”的函數(shù)。
此時(shí),就面臨一個(gè)問題,那就是:沒有名字,怎么調(diào)用呢?
實(shí)際上,此時(shí)它通過另一個(gè)方式來調(diào)用,如下所示:
形式一:

$f1 = function (形參...) {  .......  }  //這是定義匿名函數(shù)的形式。
$f1(實(shí)參);  //這就是調(diào)用該調(diào)用??梢娖湔{(diào)用,跟可變函數(shù)的寫法非常類似。

形式二:

   (function(形參){

      //函數(shù)體

})(實(shí)參)

<u>案例:</u>

定義一個(gè)匿名函數(shù),該函數(shù)可以計(jì)算兩個(gè)數(shù)的和。


image.png

image.png

7.5.1. 靜態(tài)變量

什么是靜態(tài)變量?(僅限于在函數(shù)內(nèi)部)
在初始化時(shí)只會(huì)初始化一次,后面的值會(huì)一直跟著改變
在函數(shù)內(nèi)部使用static關(guān)鍵字修飾的變量,函數(shù)在多次調(diào)用的時(shí)候能夠共同使用該變量(跨函數(shù)共享變量)
語法:static $變量


image.png

7.6. 系統(tǒng)常用函數(shù)介紹

PHP語言,以函數(shù)極大豐富而聞名于世。
看手冊(cè),查手冊(cè),并作為一種學(xué)習(xí)的習(xí)慣:


image.png

image.png

7.6.1. 跟函數(shù)有關(guān)的函數(shù)

?function_exists(“函數(shù)名”):判斷一個(gè)函數(shù)是否已經(jīng)存在;
?func_get_arg( $n ): 在函數(shù)內(nèi)部可用,用于獲得第n個(gè)實(shí)參(n從0開始算起)
?func_get_args(): 在函數(shù)內(nèi)部可用,用于獲得所有實(shí)參,結(jié)果是一個(gè)數(shù)組
?func_num_args(): 在函數(shù)內(nèi)部可用,用于獲得實(shí)參的個(gè)數(shù)
上面3個(gè)函數(shù),可以讓我們?cè)谧远x的函數(shù)內(nèi)部,直接訪問(使用)實(shí)參數(shù)據(jù),而不依賴于形參變量。
這種特性,可以給我們定義某種“不確定有幾個(gè)數(shù)據(jù)需要計(jì)算的”場(chǎng)合。


image.png

定義一個(gè)函數(shù),該函數(shù)可以求出所給定的若干個(gè)數(shù)據(jù)中的奇數(shù)的和。
1,3,27,22,33,68,100


image.png

7.6.2. 字符串有關(guān)常用函數(shù)

·輸出與格式化:echo , print, printf, print_r, var_dump.
·字符串去除與填充:trim, ltrim, rtrim, str_pad
·字符串連接與分割:implode, join, explode, str_split
·字符串截?。簊ubstr, strchr, strrchr,
·字符串替換:str_replace, substr_replace
·字符串長度與位置: strlen, strpos, strrpos,
·字符轉(zhuǎn)換:strtolower, strtoupper, lcfirst, ucfirst, ucwords
·特殊字符處理:nl2br, addslashes, htmlspecialchars, htmlspecialchars_decode,

手冊(cè)》函數(shù)參考》文本處理》字符串》字符串函數(shù)

7.6.3. 常用數(shù)學(xué)函數(shù)(重點(diǎn))

max:  取得若干個(gè)數(shù)據(jù)中的最大值
min:  取得若干個(gè)數(shù)據(jù)中的最小值
round:  對(duì)某個(gè)數(shù)據(jù)進(jìn)行四舍五入(可以設(shè)定保留幾位小數(shù))
ceil:  對(duì)某個(gè)數(shù)“向上取整”:將一個(gè)數(shù)據(jù)往上找出其小的一個(gè)整數(shù)(含其本身)。
floor:  對(duì)某個(gè)數(shù)“向下取整”:將一個(gè)數(shù)據(jù)往下找出其大的一個(gè)整數(shù)(含其本身)
$n1 = floor(4.1);  //4
$n2 = floor(4.9);  //4
$n3 = floor(4);  //4
$n4 = floor(-4.1);  //-5
abs:  取得某個(gè)數(shù)據(jù)的絕對(duì)值
sqrt:  計(jì)算某個(gè)數(shù)的開方值
pow:  對(duì)某個(gè)數(shù)進(jìn)行“冪運(yùn)算”(就是獲得某個(gè)數(shù)的若干次方)
$n1 = pow(3, 2);  //3的2次方,9
$n2 = pow(2, 3);  //8
$n3 = pow(1.5, 2);  //2.25
$n4 = pow(1.5, 2.5);  //。。。。。1.5的2.5次方
$n5 = pow(9, 0.5);  //3,就是開方,相當(dāng)于sqrt()
rand:  獲得某兩個(gè)數(shù)之間的隨機(jī)整數(shù)(含該兩個(gè)數(shù))
mt_rand:  獲得某兩個(gè)數(shù)之間的隨機(jī)整數(shù)(含該兩個(gè)數(shù)),  。
$n1 = mt_rand(0, 10);  //隨機(jī)數(shù)在0-10之間(含)

手冊(cè)》函數(shù)參考》數(shù)學(xué)擴(kuò)展》Math》Math函數(shù)。
<u>演示案例:</u>
定義一個(gè)函數(shù),該函數(shù)可以返回所給定的任意兩個(gè)數(shù)字之間的隨機(jī)整數(shù)。

image.png

7.6.4. 常用時(shí)間函數(shù)

·time:獲得當(dāng)前時(shí)間(精確到秒),結(jié)果其實(shí)一個(gè)“整數(shù)”而已,代表從1970年1月1日0:0:0秒到當(dāng)前時(shí)刻的秒數(shù)。
·microtime:獲得當(dāng)前時(shí)間(可以精確到微秒)
·mktime:創(chuàng)建一個(gè)時(shí)間數(shù)據(jù),參數(shù)為:時(shí)、分、秒,月、日、年
·date:將一個(gè)時(shí)間轉(zhuǎn)換為某種字符串形式

image.png

·idate:取得一個(gè)時(shí)間的某個(gè)單項(xiàng)數(shù)據(jù)值,比如idate(“Y”)取得年份數(shù)
·strtotime:將一個(gè)字符串“轉(zhuǎn)換”為時(shí)間值;
·date_default_timezone_set:在代碼中設(shè)置“時(shí)區(qū)”
·date_default_timezone_get:在代碼中獲取“時(shí)區(qū)”
image.png

image.png

<u>案例:</u>
課堂電腦性能大比拼:
計(jì)算從1加到1000萬,看花了多少時(shí)間?
做法:先獲得一個(gè)時(shí)間,然后計(jì)算,然后再獲得一個(gè)時(shí)間,后一個(gè)時(shí)間,減前一個(gè)時(shí)間,就是耗時(shí)。
補(bǔ)充:
調(diào)試技巧:
1、第一步,找出出現(xiàn)錯(cuò)誤的文件,然后找到對(duì)應(yīng)的行號(hào)。
image.png

2、分析錯(cuò)誤原因,閱讀錯(cuò)誤信息(可以百度,也可以根據(jù)關(guān)鍵單詞,進(jìn)行猜)
image.png

1、如果沒有致命錯(cuò)誤,但是結(jié)果不是我們預(yù)期,或者我們想提前了解下這個(gè)步驟可能產(chǎn)生的結(jié)果,怎么辦?只能進(jìn)行單步調(diào)試。
控制:
exit
die
return
exit()
die()

8. 函數(shù)相關(guān)

8.1. 變量的作用域問題(重點(diǎn))

簡(jiǎn)單來說,有3種作用域:局部作用域,全局作用域,超全局作用域;
相對(duì)應(yīng)的,有3種變量: 局部變量, 全局變量, 超全局變量;


image.png

8.1.1. 局部作用域與局部變量:

就是函數(shù)內(nèi)部范圍的作用域,其中定義的變量就是局部變量(包括形參也是局部變量)。
局部變量只能在其所在的局部作用域中使用(訪問)。
局部變量在函數(shù)調(diào)用結(jié)束時(shí),會(huì)被自動(dòng)銷毀(可以理解為函數(shù)執(zhí)行結(jié)束,該執(zhí)行空間也被銷毀了)。


image.png

8.1.2. 全局作用域與全局變量:

就是函數(shù)外部范圍的作用域,其中定義的變量就是全局變量。
全局變量只能在其所在的全局作用域中可以直接使用(訪問)。


image.png

8.1.3. 超全局作用域與超全局變量:

包括局部作用域和全局作用域的的整個(gè)作用域范圍。
超全局變量可以在所有范圍中使用(訪問)。
實(shí)際上,只有有限的10來個(gè)系統(tǒng)預(yù)定義變量是超全局變量,包括:$_GET, $_POST, $_REQUEST等。
所以,系統(tǒng)預(yù)定義變量,也被統(tǒng)稱為超全局變量。
PHP中的不同作用域的圖示:

image.png

image.png

一個(gè)特別的超全局變量:$GLOBALS
它也是一個(gè)數(shù)組,其中存儲(chǔ)了我們自己定義的所有全局變量。
每個(gè)全局變量的變量名,就是$GLOBALS數(shù)組的一個(gè)單元。
比如:
在全局作用域中定義如下變量:

$v1 = 1;  //這一行執(zhí)行,就有了一個(gè)這個(gè):$GLOBALS[‘v1’], 其值為1
$v2 = ‘a(chǎn)bc’;  //這一行執(zhí)行,就有了一個(gè)這個(gè):$GLOBALS[‘v2’], 其值為’abc’
$v3 = true;  //這一行執(zhí)行,就有了一個(gè)這個(gè):$GLOBALS[‘v3’], 其值為true

一個(gè)特別的的關(guān)鍵字:global
作用:
用于在局部作用域中,修飾一個(gè)跟全局變量同名的局部變量。
此時(shí)該局部變量也可以使用全局變量的值了——實(shí)際上他們其實(shí)是類似變量引用關(guān)系。
正常來說: 全局變量只能在函數(shù)外部使用,局部變量只能在函數(shù)內(nèi)部使用。
全局變量在局部使用:$GLOBALS

image.png

局部變量在全局使用:global
image.png

8.2. 遞歸函數(shù)(重點(diǎn)/難點(diǎn))

基本含義:
就是一個(gè)函數(shù)內(nèi)部再調(diào)用該函數(shù)本身的一種情形,這是語法形式上的。
具體場(chǎng)景是:
如果要解決的“最終問題”,可以根據(jù)比該問題“小一級(jí)”的問題的答案而得到解決,
并且,該“小一級(jí)”的問題,還可以根據(jù)比其“更小一級(jí)”的問題的答案而得到解決,
以此類推,直到“最小一級(jí)”的問題。如果最小一級(jí)問題已知,則最終的問題也就解決了。
危險(xiǎn):
如果函數(shù)在執(zhí)行的過程中沒有一個(gè)“不再調(diào)用”的終結(jié)機(jī)制,那么就會(huì)出現(xiàn)“停不下來”的現(xiàn)象。
遞歸:
遞歸入口(當(dāng)要執(zhí)行的后面的方法跟前面方法一致時(shí),就可以使用前面的方法)
遞歸點(diǎn)(當(dāng)執(zhí)行完了整個(gè)流程時(shí),需要跳出循環(huán))
原理:

image.png

<u>遞歸調(diào)用過程的代碼演示:</u>
分析一下代碼的輸出結(jié)果:
image.png

<u>案例1:</u>
計(jì)算5的階層;
分析:
數(shù)學(xué)上階乘可以這樣來描述:一個(gè)數(shù)n的階乘,是n-1的階乘,乘以n的結(jié)果!
假設(shè),我們有一個(gè)函數(shù) jieceng(),它可以計(jì)算任意正整數(shù)n的階乘,類似這樣:

$n = 5; //或等于10, 13,等等都無所謂。
$result = jiecheng($n);
image.png

<u>案例2:</u>
計(jì)算斐波那契數(shù)列第10項(xiàng)的值:1, 1, 2, 3, 5, 8, 13, 21, 34,55,89......
假設(shè)有個(gè)函數(shù),可以計(jì)算斐波那契數(shù)列的第n項(xiàng):

image.png

作業(yè): 猴子吃桃,第一天吃總數(shù)的一半多1個(gè),。。。以后的每一天都這樣吃。第10天吃完的時(shí)候還有1個(gè),問一共有多少個(gè)桃子。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容