十八、函數(一)

来源:https://www.cnblogs.com/piaolaipiaoqu/archive/2023/11/28/17863473.html
-Advertisement-
Play Games

十八、函數(一) 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;
}

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 簡介 nodemon用來監視node.js應用程式中的任何更改並自動重啟服務,非常適合用在開發環境中。以前,我們開發一個node後端服務時,每次更改文件,均需重啟一下,服務才能生效。這使我們的開發效率降低了很多。nodemon的出現,可以隨時監聽文件的變更,自動重啟服務,我們開發時只需關註代碼即可, ...
  • 最近,相信大家一定被這麼個動效給刷屏了: 以至於,基於這個效果的二次創作層出不窮,眼花繚亂。 基於跨視窗通信的彈彈球: 基於跨視窗通信的 Flippy Bird: 我也嘗試製作了一個跨 Tab 視窗的 CSS 動畫聯動,效果如下: 代碼不多,核心代碼 200 行,感興趣的可以戳這裡:Github - ...
  • 專欄分享:vue2源碼專欄,vue3源碼專欄,vue router源碼專欄,玩具項目專欄,硬核💪推薦🙌 歡迎各位ITer關註點贊收藏🌸🌸🌸 Vue3中響應數據核心是 reactive , reactive 的實現是由 proxy 加 effect 組合,上一章節我們利用 proxy 實現了 ...
  • 自增自減運算符 1、基本使用 內置提供 ++、--運算符 是用於將變數本身進行加1或者減1操作 // 1、基本使用 var i = 10; i++;//等價於語句 i+=1 console.log(i);//11 var m = 10; m--; console.log(m) 2、前置與後置的區別 ...
  • 一、定義 定義一個語言的文法,並且建立一個解釋器來解釋該語言中的句子,這裡的“語言”是指使用規定格式和語法的代碼。解釋器模式是一種行為型模式。 二、描述 解釋器模式是一種使用頻率相對較低但學習難度較大的設計模式,它主要用於描述如何使用面向對象語言構成一個簡單的語言解釋器,包含以下四個角色: 1、Ab ...
  • 推薦一本日本網友Kenji Hiranabe寫的《線性代數的藝術》。這本書是基於MIT大牛Gilbert Strang教授的《每個人的線性代數》製作的。 雖然《線性代數的藝術》這本書僅僅只有12頁的內容,就把線性代數的重點全畫完了,清晰明瞭。 《線性代數的藝術》PDF版本:https://pan.q ...
  • 懶載入是Spring框架中的一個重要特性,它允許我們將bean的實例化推遲到第一次使用時。懶載入的主要用途是提高應用程式的啟動性能,減少不必要的資源消耗。 一、懶載入的用途 在大型的應用程式中,有些bean可能只在特定的條件下才會被使用到。如果在應用程式啟動時就實例化所有的bean,會導致啟動時間變 ...
  • 一、參考 https://ericniebler.com/2020/11/08/structured-concurrency/ 二、總結 1. 結構化併發是什麼-概述 是什麼:一種確保子操作在父操作之前完成的方式,類似函數在調用函數之前完成。 最典型的結構化併發:C++20的協程 意義:它通過使非同步 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...