十八、函數(一) 1、函數概述 1)函數帶來的好處 ①代碼模塊化,便於閱讀維護 ②代碼模塊化以後,能夠實現分工合作 ③減少重覆代碼,降低工作流 2)函數的語法 //函數的語法 返回類型 函數名稱(參數,參數,參數,參數) //參數的語法包括:參數類型 參數名稱 { 函數的功能區; return 返回 ...
十八、函數(一)
1、函數概述
1)函數帶來的好處
①代碼模塊化,便於閱讀維護
②代碼模塊化以後,能夠實現分工合作
③減少重覆代碼,降低工作流
2)函數的語法
//函數的語法
返回類型 函數名稱(參數,參數,參數,參數) //參數的語法包括:參數類型 參數名稱
{
函數的功能區;
return 返回值;
}
//函數的聲明示範一
int Add(int a,int b)
{
return a+b;
}
使用:
int a=Add(100,200); //a=300
//函數的聲明示範二
void PrintLog(char *str)
{
std::cout<<"日誌:"<<str;
}
使用:
Printlog("你好世界!");
//函數的聲明示例
// 函數一.cpp : 此文件包含 "main" 函數。程式執行將在此處開始並結束。
//
#include <iostream>
int Add(int a, int b) //函數的聲明
{
return a + b; ////返回的是什麼類型的值,就用什麼類型接受
}
//不需要返回值的函數,使用的返回類型為void
void PrintEnding(const char* str,int x)
{
std::cout << str << x << std::endl;
}
int main()
{
int x{ Add(100, 100) }; //函數的使用
PrintEnding("生命值:",x);
x =Add(200,300);
PrintEnding("內力值:",x);
}
註:每個函數都必須有return函數返回值,main()函數編譯器會自動在函數結尾預設加一個return
//用函數實現游戲麟江湖排行榜設計修
//GetDataCount函數統計有幾個角色的信息
int GetDataCount(string str)
{
int icount{};
for (int i = 0; i < str.length(); i++)
{
if (str[i] == ';')
{
icount++;
i += 3;
}
}
return icount/2;
}
//獲取字元串中的數據
string GetDataStr(string str, int istart)
{
string strReturn{};
int iend{};
istart = str.find("id=", istart);
if (istart == std::string::npos) return strReturn;
iend = str.find(";", istart + 3);
strReturn = str.substr(istart + 3, iend - istart - 3);
return strReturn;
}
2、函數參數之指針參數
函數分為三部分:包括函數的頭部、函數體、函數的尾部(一個函數有可能有很多尾部)、
函數頭中的變數只申請了記憶體空間、但是沒有賦值,沒有初始化
函數尾是為了返回值
//直接將實參傳遞給形參
#include <iostream>
int Add(int x, int y) //形參
{
x *= 100;
y *= 100;
return x + y;
}
int main()
{
int x = 2, y = 1;
int c = Add(x,y); //實參
std::cout << "c=" << c << " x=" << x << " y=" << y << std::endl;
}
//通過此種方式無法得到x和y變化後的結果
//向函數中傳入指針參數(將函數中的值讀取去出來,獲得回傳值)
#include <iostream>
int Add(int* x, int* y) //形參
{
(*x) *= 100; //x和y次數是一個指針
(*y) *= 100;
return (*x) + (*y);
}
int main()
{
int x = 2, y = 1;
int c = Add(&x, &y); //實參傳入x和y的記憶體地址
std::cout << "c=" << c << " x=" << x << " y=" << y << std::endl;
}
//通過結果發現c的值沒有發生變化,但是x和y的值發生了變化。成為函數中最終計算的x和y的結果
2)指針參數的常見應用
函數頭部中的形參在定義時,會分配整個結構體內部成員變數總和的記憶體空間,會存在記憶體空間開銷過剩的問題;但是如果函數頭部中傳入的參數為指針參數,那麼只需要分配指針大小的函數空間,即4位元組.
//不使用指針參數,給函數傳值
#include <iostream>
struct Role
{
int Hp;
int Mp;
};
int Exp(Role role)
{
return role.Hp + role.Mp;
}
int main()
{
Role role{ 500,1000 };
int totle =Exp(role); //看起來函數在調用時傳入了一個參數,但是實際上傳入了兩個參數
std::cout << "角色戰鬥力為:" << totle << std::endl;
}
//通過指針參數,給函數傳值
#include <iostream>
struct Role
{
int Hp;
int Mp;
};
int Exp(Role* role)
{
return role->Hp + role->Mp; //不再使用.取實體,而是通過->偏移符號通過地址傳值
}
int main()
{
Role role{ 500,1000 };
int totle = Exp(&role); //取地址
std::cout << "角色戰鬥力為:" << totle << std::endl;
}
//通過此方式可大大提升效率
3)指針參數之常量指針用法
回顧:常量指針,表示指針指向的內容是一個常量,指針指向的內容不可以發生變化,即值可以讀,但不可以寫,防止修改數據
//初始化一個玩家和怪物,定義一個函數,返回一個bool值,當值為true的時候,說明角色死亡
#include <iostream>
struct Role
{
int Hp;
int Mp;
int damage;
};
bool Exp(const Role* Acter, Role* beActer) //攻擊者者和被攻擊者,攻擊者的屬性不能夠修改
{
beActer->Hp -= Acter->damage; //被攻擊者血量=被攻擊者血量-攻擊者傷害值
return beActer->Hp <= 0;
}
int main()
{
Role user{ 500,1000,1200 };
Role monster{ 1500,1000,1000 };
if (Exp(&monster, &user))
std::cout << "角色死亡!" << std::endl;
else
if (Exp(&user ,&monster))
std::cout << "怪物死亡" << std::endl;
}
3、函數參數之數組參數
1)數組本質上就是一個指針,傳入數組參數時,要傳入數組的長度。提高如下兩種數組參數的定義方法
//傳入數組參數時,必須要傳入數組的長度
//數組參數方法一
Void Sort(int ary[],unsigned count) //推薦
{
for(int i=1;i<count;i++)
}
int main()
{
int a[5]{ 2302,5212,3653,9480,5200 };
Sort(a, 5);
}
//數組參數方法一
Void Sort(int* ary,unsigned count) //推薦
{
for(int i=1;i<count;i++)
}
int main()
{
int a[5]{ 2302,5212,3653,9480,5200 };
Sort(a, 5);
}
//將數組進行排序案例
#include <iostream>
void Sort(int ary[],unsigned count)
{
for (int i = 1; i < count; i++)
{
if (ary[i] > ary[i - 1])
{
int tmp = ary[i];
ary[i] = ary[i - 1];
ary[i - 1] = tmp;
}
}
}
int main()
{
int a[5]{ 2302,5212,3653,9480,5200 };
Sort(a, 5);
for (auto x : a)std::cout << x << std::endl;
}
2)多維數組的傳參
//多維數組的傳參,無法寫成指針的形式
Void Sort(int ary[][2],unsigned count) //推薦
{
f
}
int main()
{
int a[3][2]{{1,2},{3,4},{5,6}};
Sort(a, 3); //傳入數組的長度
}
4、函數參數之引用參數
//引用回顧
int a=5;
int &b = a; //引用就相當於被閹割了的指針
則b++就相當於a++
1)引用也可以使用const進行限定只能讀,不能寫
#include <iostream>
struct Role
{
int Hp;
int Mp;
int damage;
};
bool Exp(const Role& Acter, Role& beActer) //引用,相當於Role& Acter = user;Role& beActer=monster
{
beActer.Hp -= Acter.damage;
return beActer.Hp <= 0;
}
int main()
{
Role user{ 5000,1000,12000 };
Role monster{ 1500,1000,1000 };
if (Exp(user, monster))std::cout << "怪物死亡,獲得經驗值XXX" << std::endl;
}
2)引用和指針的區別
引用要想使用,必須先得初始化;而指針可以先傳入一個空指針,先不進行初始化
//此種方式錯誤,引用必須初始化
bool Act(Role& Acter,Role& beAct)
{
return true;
}
Act(nullptr,nullptr);
//指針可以不進行初始化
bool Act(Role* Acter,Role* beAct)
{
return true;
}
Act(nullptr,nullptr);
3)指針類型的引用
//指針類型的引用
#include <iostream>
struct Role
{
char name[0x20];
int Hp;
int Mp;
int damage;
};
bool Exp(const Role& Acter, Role*& beActer) //Role*指針類型的引用
{
beActer->Hp -= Acter.damage;
bool End = beActer->Hp < 0;
beActer = (Role*)&Acter; //通過指針類型的引用,可以修改參數的指向,此處將被攻擊者修改為攻擊者
return End;
}
int main()
{
Role user{ "奧特曼",5000,1000,12000 };
Role monster{ "小怪獸",1500,1000,1000 };
Role* pRole = &monster;
if (Exp(user, pRole))std::cout << pRole->name<<" 怪物死亡,獲得經驗值XXX" << std::endl;
}
可以使用如下寫法
//指針類型的引用的其他寫法
#include <iostream>
typedef struct Role
{
char name[0x20];
int Hp;
int Mp;
int damage;
}*PROLE; //Role類型的指針PROLE
bool Exp(const Role& Acter, PROLE& beActer) //Role類型指針PROLE的引用
{
beActer->Hp -= Acter.damage;
bool End = beActer->Hp < 0;
beActer = (Role*)&Acter; //通過指針類型的引用,可以修改參數的指向,此處將被攻擊者修改為攻擊者
return End;
}
int main()
{
Role user{ "奧特曼",5000,1000,12000 };
Role monster{ "小怪獸",1500,1000,1000 };
PROLE pRole = &monster; ////Role類型指針PROLE
if (Exp(user, pRole))std::cout << pRole->name<<" 怪物死亡,獲得經驗值XXX" << std::endl;
}
5、函數參數之預設實參
1)預設參數引入
//傳入一組數,對其進行排序
#include <iostream>
void Swap(int &a,int &b) //定義函數專門用來交換兩個數
{
int tmp = a;
a = b;
b = tmp;
}
void Sort(int ary[], unsigned count,bool BigSort) //定義函數用來排序
{
for(int i=1;i<count;i++)
{
bool bcase = BigSort ? ary[i] > ary[i - 1]:ary[i - 1] > ary[i];
if (bcase)Swap(ary[i], ary[i - 1]);
}
}
int main()
{
int a[5]{ 2302,5212,3653,9480,5200 };
Sort(a, 5,false); //true表示從大到小排序,false表示從小到大排序
for (auto x : a)std::cout << x << std::endl;
}
2)預設參數使用
在函數調用時,若不傳遞值,則使用函數聲明時設置的預設參數。預設參數只可以放置在最後,不可以放置在最前面或中間;若有多個預設參數,需要依次寫在最後面
//預設參數使用
#include <iostream>
void Swap(int &a,int &b)
{
int tmp = a;
a = b;
b = tmp;
}
void Sort(int ary[], unsigned count,bool BigSort=true) //定義函數預設值參數
{
for(int i=1;i<count;i++)
{
bool bcase = BigSort ? ary[i] > ary[i - 1]:ary[i - 1] > ary[i];
if (bcase)Swap(ary[i], ary[i - 1]);
}
}
int main()
{
int a[5]{ 2302,5212,3653,9480,5200 };
Sort(a, 5); //函數調用時,若不傳入參數,預設使用函數聲明時形參的預設值
for (auto x : a)std::cout << x << std::endl;
}