C語言學習筆記(九)—— 函式、遞迴和指標
阿新 • • 發佈:2019-02-18
一、函式
1、一個簡單的函式示例
函式是完成特定任務的獨立程式程式碼單元。
#include <stdio.h> void printStar();//宣告函式原型,函式原型會指明函式的型別和函式接受的引數。前面的void是函式型別,表明函式沒有返回值 #define NUM 20 int main(){//主函式 printStar();//呼叫函式 printf("這裡是文字內容區域!\n"); printStar();//呼叫函式 return 0; } void printStar(){//定義函式 for(int count=0;count<NUM;count++){ printf("*"); } printf("\n"); }
2、帶形式引數和實際引數的函式
形式引數是被調函式中的變數,實際函式是主調函式賦給被調函式的具體值,它可以是常量、變數或者表示式的值。
int main(){//主函式
printRect(3,5);//實際引數,列印三行五列的矩形
return 0;
}
void printRect(int row,int col){//形式引數
for(int i=0;i<row;i++){
for(int j=0;j<col;j++){
printf("*");
}
printf("\n");
}
}
3、帶return的函式
void example3(){ int x,y,z; while(scanf("%d %d",&x,&y)==2){ fflush(stdin);//重新整理輸入流 printf("引數1是:%d,引數2是:%d\n",x,y); z=maxNum(x,y); printf("兩個引數中的最大值是:%d\n",z); } } int maxNum(int x,int y){ int z; if(x>y){ z=x; }else{ z=y; } return z; }
二、遞迴
1、一個簡單的程式演示遞迴
/** * 數值i的值是:1 記憶體地址是:0061FF10 * 數值i的值是:2 記憶體地址是:0061FEF0 * 數值i的值是:3 記憶體地址是:0061FED0 * 數值i的值是:3 記憶體地址是:0061FED0 * 數值i的值是:2 記憶體地址是:0061FEF0 * 數值i的值是:1 記憶體地址是:0061FF10 */ void example4(){ recursion(1); } void recursion(int i){ printf("數值i的值是:%d 記憶體地址是:%p\n",i,&i); if(i<3){ recursion(i+1); } printf("數值i的值是:%d 記憶體地址是:%p\n",i,&i); }
注意:每級遞迴的變數都屬於本級遞迴私有
2、遞迴的基本原理
① 每級函式呼叫都有自己的變數;
② 每次函式呼叫都會返回一次,當函式執行完畢後,控制權將被傳回上一級遞迴,程式必須按順序逐級返回遞迴;
③ 遞迴函式中位於遞迴之前的語句,均按被調函式的順序執行;
④ 遞迴函式中位於遞迴之後的語句,均按被調函式相反的順序執行;
⑤ 遞迴函式必須包含可以讓遞迴停止的語句。
3、尾遞迴
遞迴呼叫在函式的末尾,正好在return之前,這種遞迴被稱為尾遞迴,它其實相當於迴圈。
使用迴圈和尾遞迴來演示階乘,如下:
void example5() {
int num = 5,j=1; //1*2*3*4*5=120
//factorial_while(num);
int result = factorial_recursion(num,j);
printf("%d的階乘是:%d", num, result);
}
//使用迴圈計算階乘
void factorial_while(int num) {
int z = 1;
for (int i = 1; i <= num; i++) {
z = z * i;
}
printf("%d的階乘是:%d", num, z);
}
//使用遞迴計算階乘
int factorial_recursion(int num,int j) {
int z= 1;
if (j<num) {
z = factorial_recursion(num,j+1);
}
return z*j;
}
4、遞迴和倒序計算
void example6(){
recursion_two(10);
}
//用遞迴函式列印正整數的二進位制表示形式
void recursion_two(int num){
int z=num%2;//遞迴函式的第一層級列印最後一位
if(num/2>0){//當除數為0時的餘數是為二進位制位的第一位,遞迴函式的最後層級列印的是二進位制數的第一位
recursion_two(num/2);//把除數當作引數再次傳遞給遞迴函式
}
printf("%d",z);
}
5、遞迴之斐波那契數列
數列定義,第1個和第2個數字都是1,後續的兩個數字都是前兩個數字之和,遞迴計算數列如下:
void example7(){
long count = fiboshulie(24);
printf("%d",count);
}
long fiboshulie(int n){
if(n>2){
return fiboshulie(n-1)+fiboshulie(n-2);
}else{
return 1;
}
}
三、編譯多原始碼檔案的程式
1、標頭檔案(head.h)
標頭檔案中主要是宣告函式原型和常量
//在此檔案中統一定義函式原型和常量
#define NUM1 2
long fiboshulie1(int n);
2、函式支援檔案(second.c)
函式支援檔案主要是編寫獨立的函式程式碼塊,供主函式呼叫
//此檔案主要是編寫獨立的函式程式碼塊,供主函式呼叫
#include<stdio.h>
#include"head.h"
long fiboshulie1(int n){
if(n>NUM1){
return fiboshulie1(n-1)+fiboshulie1(n-2);
}else{
return 1;
}
}
3、主函式所的檔案
#include"head.h" //該指令中的雙引號表明被包含的檔案位於當前目錄中
int main() { //主函式
example8();
return 0;
}
void example8(){
long l = fiboshulie1(24);
printf("%d",l);
}
四、查詢地址:&運算子
指標,是一個值為記憶體地址的變數,指標變數的值是地址,如果要建立指標,要先宣告指標變數的型別
1、示例程式
void example9(){
int x = 1,y=2;
printf("在example9函式中x的記憶體地址是:%p\n",&x);
printf("在example9函式中y的記憶體地址是:%p\n",&y);
cursor(x);
}
void cursor(int x){//需要注意的是雖然這裡使用的x的值一樣,但它們的記憶體地址不一樣
int y = 2;
printf("在cursor函式中x的記憶體地址是:%p\n",&x);
printf("在cursor函式中y的記憶體地址是:%p\n",&y);
}
/*
* 記憶體地址使用十六進位制顯示,一個十六進位制對應4個二進位制位
在example9函式中x的記憶體地址是:0061FF1C
在example9函式中y的記憶體地址是:0061FF18
在cursor函式中x的記憶體地址是:0061FF00
在cursor函式中y的記憶體地址是:0061FEEC
*/
2、宣告指標
宣告指標變數時必須指定指標所指向變數的型別,不同的變數型別佔用不同的儲存空間,一些指標操作要求知道操作物件的大小。示例如下:
void example11(){
char * ch;//ch是指向char型別變數的指標,*表明變數宣告的是一個指標
int a = 10;
int *a2 = &a;//宣告int型別的指標並將指標指向變數a的記憶體地址,*是間接運算子,也稱為解引用運算子,*與變數名之間的空格可有可無
int a3 = *a2;//解引用,相當於a3=a
printf("%d\n",a3);//10
}
3、使用指標交換函式中的變數值
一般交換函式中變數值的方式如下:
void example10(){
int temp,x=2,y=5;
temp = x;
x = y;
y = temp;
printf("x的值是:%d,y的值是:%d",x,y);//x的值是:5,y的值是:2
}
使用指標來交換函式中變數值的方式如下:
void example12() {
int x = 2, y = 5, temp;
temp = *&x;
*&x = *&y;
*&y = temp;
printf("x的值是:%d,y的值是:%d",x,y);//x的值是:5,y的值是:2
}
4、使用指標在函式間進行通訊
void example13() {
int x = 2, y = 5;
printf("在example13函式中x的值是:%d,y的值是:%d\n", x, y);
example14(&x, &y); //在函式通訊時傳遞指標變數
printf("在example13函式中x的值是:%d,y的值是:%d\n", x, y);//通過指標操作改變了呼叫函式中變數的值,如果不使用指標是無法進行這樣操作的
}
void example14(int *x, int *y) { //傳遞過來時已經使用*進行了解引用操作
printf("在example14函式中x的值是:%d,y的值是:%d\n", *x, *y);
int temp;
temp = *x;
*x = *y;
*y = temp;
printf("在example14函式中x的值是:%d,y的值是:%d\n", *x, *y);
}
/*在example13函式中x的值是:2,y的值是:5
在example14函式中x的值是:2,y的值是:5
在example14函式中x的值是:5,y的值是:2
在example13函式中x的值是:5,y的值是:2*/