前言:面向過程編程的定義
面向過程是一種以步驟為中心的編程設計方法。編程的時候把解決問題的步驟拆分出來,並用函數把這些步驟實現出來,或者說包裝起來,便是面向過程的意思了。那麼,如果我們要用C++進行一個未知數的四則運算,那麼該怎麼拆分步驟呢?
- 先界定我們要尋找的range
- 把昨日的Code寫進來
- 分開 + - x ÷四種情況做運算
- 把運算結果返回
你會發現都是順序的結果
函數需要標明型別的!!
如果忘記了C++有什麼類型可以會第4天看最底的小表格
函數
我假設大家都聽過數學的函數,數學的函數裡的表示是這樣的: sin(x)
, f(y)
,你可以看見函數有一個名字,而在括弧裡的就是你要傳入的數值。如果要定義一個函數做什麼,和返回的數值是什麼。那麼就要用以下的方法。
我們假設要做一個 叫 add(x,y)
的函數,當中我們希望他計算出 x + y 的總和,那麼就可以這樣做。
//return 就是把我們希望要的答案輸出到主函數裡
如此類推,我們可以得出以下的函數
//return 就是把我們希望要的答案輸出到主函數裡//return 就是把我們希望要的答案輸出到主函數裡//return 就是把我們希望要的答案輸出到主函數裡
那麼我們下一步就是查詢數式究竟是 + - x ÷ 了
auto calculate(auto x, char operators, auto y){
switch(operators){
case '+': return sumOf(x,y); break;
case '-': return differenceOf(x,y); break;
case '*': return productOf(x,y); break;
case '/': return quotientOf(x,y); break;
}
- 我們現在就已經弄了一個最基本的Parser 了
然後再寫一個四則驗算器。
auto check(int x, char oeprators, int y, int z){
return calculate(x,operators,y) == z;
}
- 這個運算器會在三個數值都正確的時候返回
true
,反之false
下一步便是寫出計算的For Loops了
auto evaluateX(char operators, int y, int z){
for(auto x = 0; x < 1000 ;x++){
if(check(x,operators,y,z)) return static_cast<double>(x);
else if(check(-x,operators,y,z)) return static_cast<double>(x);
else continue;
}
這個程序的範圍從-1000到1000,能應付簡單的計算,static_cast應付小數的
那怎麼使用函數呢?其實上面的函數有不少都有使用其他函數的,而下面就是在Main中使用。
//輸出了 2//輸出了 1.2//輸出了 180
這樣,我們一個並不是很Flexible的 Function就完成啦。回顧一下函數結構
-- evaluateX()
----check()
--------calculate()
------------sumOf()
------------differenceOf()
------------quotientOf()
----check()
--------calculate()
------------sumOf()
------------differenceOf()
------------quotientOf()
Lambda 函數
函數式有三個概念,分別是
- 一等公民和高階函數
- 純函數/類似數學函數
- 宣告式編程
特性與語法
1. 第一公民特性
函數式編程第一個特性就是當函數式是變數一樣傳遞。例如以下的例子
auto sum = [](auto x, auto y){
auto sum = x + y;
return sum;
};
int main(){
auto sums = sumOf(1,2);
}
2. 高階函數特性
可以當函數式是參數傳入到另一個函數式,甚至是Vector/Map等等。改動Day 6的函數式為例子。
#include <unordered_map>#include <functional>using namespace std;
auto difference = [](auto x, auto y){ return x-y; };
auto product = [](auto x, auto y){ return x * y; };
auto quotient = [](auto x, auto y){ return x/y; };
auto sum = [](auto x, auto y){ return x + y; };
unordered_map<char, function<double(double,double)>> calculate = {
{'+',sum},
{'-',difference},
{'*',product},
{'/',quotient}
};
3. 宣告式編程
宣告式編程是較為抽象的程式碼,描述該在哪做什麼以及資料流程,而且很少用到If,While,for loop等等。你可以很容易猜到他在做什麼,例如下面的程序。
int main(){
calculate['*'](3.5,2);
calculate['/'](9.5,2);
}
輸出
7
4.75
4. 高階函數(二)
Lambda也擁有高階函數的第二個特性,就是能自己返回函數了
using namespace std;
auto chooseSign = [](char sign){ return calculate[sign]; };
auto equation = [](auto x, auto y,char sign, auto z){
auto evaluate = chooseSign(sign);
for(auto i = 0;i<2000;i++){
if(evaluate(x,y) == z) return x;
else if(evaluate(x,y) == z) return -x;
}
return -1;
};
5. 純函數
純函數的意思是,將相同的數值放到函數裡會輸出一樣的結果,就像數學函數一樣。在C++裡,大部分基本函數都是純函數,包括Day 6的函數和今日的所有函數。
好了,其實函數式編程已經講完了...