C++語法衝刺(3)
最後一堂語法衝刺ㄌ
目錄
- function & recursion
- struct
- 亂七八糟的東西
函式
function
#include <iostream>
using namespace std;
int main() {
int x1, y1, x2, y2;
int a, b, c, d;
cin >> x1 >> y1 >> x2 >> y2;
cin >> a >> b >> c >> d;
int cnt = 0;
if(a<=x1 && x1<=c && b<=y1 && y1<=d) cnt++;
if(a<=x1 && x1<=c && b<=y2 && y2<=d) cnt++;
if(a<=x2 && x2<=c && b<=y1 && y1<=d) cnt++;
if(a<=x2 && x2<=c && b<=y2 && y2<=d) cnt++;
if(cnt<2) cout << (x2-x1)*(y2-y1);
else if(cnt == 4) cout << 0;
else{
int xl, xr, yl, yr;
if(x1 > a) xl = x1;
else xl = a;
if(x2 < c) xr = x2;
else xr = c;
if(y1 > b) yl = y1;
else yl = b;
if(y2 < d) yr = y2;
else yr = d;
cout << (x2-x1)*(y2-y1) - (xr-xl)*(yr-yl);
}
return 0;
}
我到底在寫什麼啊好醜
怎麼連我自己都看不懂RRRRRR
我怎麼一直打重複ㄉ東西
一直複製貼上再改煩死了啊啊啊
而且code這麼亂的話debug好難QAQ
好想像python一樣好多方便的函式……
Function saves the day!
#include <iostream>
using namespace std;
bool cover_corner(int x, int y, int x1, int y1, int x2, int y2){
return x1<=x && x<=x2 && y1<=y && y<=y2;
}
int main() {
int x1, y1, x2, y2;
int a, b, c, d;
cin >> x1 >> y1 >> x2 >> y2;
cin >> a >> b >> c >> d;
int cnt = 0;
if(cover_corner(x1, y1, a, b, c, d)) cnt++;
if(cover_corner(x1, y2, a, b, c, d)) cnt++;
if(cover_corner(x2, y1, a, b, c, d)) cnt++;
if(cover_corner(x2, y2, a, b, c, d)) cnt++;
if(cnt<2) cout << (x2-x1)*(y2-y1);
else if(cnt == 4) cout << 0;
else{
int xl = max(x1, a);
int xr = min(x2, c);
int yl = max(y1, b);
int yr = min(y2, d);
cout << (x2-x1)*(y2-y1) - (xr-xl)*(yr-yl);
}
return 0;
}
整齊、美觀、可讀性++、易於debug
減少複製貼上改到頭很痛編寫重複ㄉcode
btw C++也有有很多內建函式可以用喔喔喔
(希望你們還記得++是什麼意思
C++內建函式庫
__gcd(a,b) 回傳a和b的最大公因數
lcm(a,b) 回傳a和b的最小公倍數
swap(a,b) 交換a和b
max(a,b) 回傳a或b較大的那個
min(a,b) 回傳a或b較小的那個
abs(n) 回傳絕對值n
sqrt(n) 回傳根號n
這些都是比較常用的 可以先記一下
除此之外還有很多內建函式可以用,遇到再去查就可以ㄌ
btw後面這兩個要先include <cmath>
自訂義函式怎麼寫
/*回傳型別*/ /*函式名稱*/ (/*傳入參數*/){
/*做事情*/
return /*變數*/;
}
int plus_one(int n){
return n + 1;
}
傳入參數的地方記得打上參數的型別
return代表回傳東西並且碰到return後函式會停止執行
例子
#include <iostream>
using namespace std;
bool passed(int n){ //傳入參數的名字可以跟傳進來的時候不一樣
if(n < 60) return false;
//如果小於60就回傳false並結束 不會跑到後面的東西
return true;
}
int main(){
int score;
cin >> score;
if(!passed(score)) cout << "FAILURE\n";
else cout << "I'm so dian\n";
}
如果我沒有要回傳東西ㄋ
如果我沒有要回傳東西ㄋ
在回傳型別寫void!!!
void greeting(){
cout << "hello\n";
return;
}
例子:
也可以省略return
那就是會跑到函式的最後一行才會結束
傳入一維陣列!
#include <iostream>
using namespace std;
int max_of_array(int arr[], int n) {
int maxx = 0;
for (int i = 0; i < n; i++){
if(arr[i] > maxx) maxx = arr[i];
}
return maxx;
}
int main(){
int arr[100] = {1, 2, 3};
int maxx = max_of_array(arr, 100);
cout << maxx;
}
// output : 3
傳入二維陣列!
#include <iostream>
using namespace std;
int max_of_array(int arr[][100], int n, int m) {
int maxx = 0;
for (int i = 0; i < n; ++i){
for(int j=0; j < m; ++j)
if(arr[i][j] > maxx) maxx = arr[i][j];
}
return maxx;
}
int main(){
int arr[100][100] = {{1, 2, 3}, {4, 5, 6}};
int maxx = max_of_array(arr, 100, 100);
cout << maxx;
}
// output : 6
除了第一維以外要記得寫大小喔喔喔
pass by value
#include <iostream>
using namespace std;
void swap_num(int m, int n){
int tmp;
tmp = m;
m = n;
n = tmp;
}
int main(){
int a = 1, b = 2;
swap_num(a, b);
cout << a << ' ' << b << '\n';
}
// output : 1 2
whyyyyyyyyyyyyyyyyyyyyyyyyyyy
pass by value
一般傳入參數的時候,參數是被複製進去的
所以m跟a是不一樣的東西,n跟b也是不一樣的東西
#include <iostream>
using namespace std;
void swap_num(int m, int n){
int tmp;
tmp = m;
m = n;
n = tmp;
}
int main(){
int a = 1, b = 2;
swap_num(a, b);
cout << a << ' ' << b << '\n';
}
// output : 1 2
怎麼解決這個問題ㄋ
指標或pass by reference !
但我們之後才會教指標la
pass by reference
#include <iostream>
using namespace std;
void swap_num(int &m, int &n){
int tmp;
tmp = m;
m = n;
n = tmp;
}
int main(){
int a = 1, b = 2;
swap_num(a, b);
cout << a << ' ' << b << '\n';
}
// output : 2 1
aka. 傳參考 一個給變數取暱稱的概念
用法基本上就是在變數前面加 '&'
總結一下
在函式裡面改變變數的值不會影響到這個函式以外的地方
但陣列是例外,在函式裡面改變陣列的值整個程式都會被影響到,原因教指標的時候應該會講......吧
遞迴
Recursion
遞迴是什麼
遞迴的定義:參見遞迴
蛤?
遞迴是什麼
遞迴函式就是指在函式中再呼叫一次函式本身,而用這種做法可以省下許多麻煩的coding,譬如若要算出\(x\)的階乘,其實\(x! = x \times (x-1)!\),再以此往下類推到\(1!\)為止,此時用遞迴去寫就很方便。
階乘
#include <iostream>
using namespace std;
int rec(int n){
if(n == 1) return 1;
return n * rec(n-1);
}
int main(){
int n;
n = 5;
cout << rec(n);
}
// output : 120
費式數列
在數學上,費波那契數是以遞迴的方法來定義:
\(F_{0}=0\)
\(F_{1}=1\)
\(F_{n}=F_{n-1}+F_{n-2}\) \((n \geq 2)\)
輸入一個數字\(n (n\leq 40)\) 請輸出費式數列第\(n\)項
費式數列
#include <iostream>
using namespace std;
int f(int n){
if(n <= 1) return n;
return f(n-1) + f(n-2);
}
int main(){
int n;
cin >> n;
cout << f(n) << '\n';
}
河內塔
河內塔是根據一個傳說形成的一個問題:有三根桿子A, B, C。A桿上有\(n\)個\((n \geq 1)\)穿孔圓盤,盤子的尺寸由下到上依次變小。
現在,想要把桿子A上的盤子移動到桿子C,而且盤子的移動規則是:每次只能移動一個圓盤; 大盤子不能疊在小盤子上面。當然,任何盤子皆可以臨時置於B桿,也可將從A桿移出的圓盤重新移回A桿,但都必須遵循上述兩條規則。
現在,請你寫一個能夠描述盤子搬動過程的程式。
河內塔
把整個問題拆解成每次把最底下的盤子搬到目的地
所以會是先把第\(n\)個盤子以外的所有盤子搬到工具桿(?),再把第\(n\)個盤子搬到目的地,再把第\(n\)個盤子以外的所有盤子從工具桿(?)搬到目的地
#include <iostream>
using namespace std;
int cnt = 0;
void rec(int n, char from, char to, char buffer){
if(n == 0) return;
rec(n-1, from, buffer, to);
printf("Move disk %d from %c to %c\n", n, from, to);
cnt++;
rec(n-1, buffer, to, from);
}
int main(){
int n;
cin >> n;
rec(n, 'a', 'c', 'b');
cout << cnt;
}
河內塔
快速冪
求\(n^{m}\)
for迴圈?
如果\(m=0\) \(n^{m}=1\)
如果\(m\)是奇數 \(n^{m}=n \times n^{m-1}\)
如果\(m\)是偶數
快速冪
求\(n^{m}\)
#include <bits/stdc++.h>
using namespace std;
int rec(int n, int m){
if(m == 0) return 1;
if(m % 2 == 1) return n * rec(n, m-1);
int a = rec(n, m/2);
return a * a;
}
int main(){
int n, m;
cin >> n >> m;
cout << rec(n, m) << endl;
}
寫寫題目
學長學長~
那我殼以在一個函式一次回傳兩個值ㄇ
打咩。
在一個函式回傳多個值 ?
struct !
struct
struct structName{
/*這個struct裡面有的變數*/
}; // 注意這裡要分號
把很多變數綁在一起的東西(變數型態可以不一樣)
創造一個把很多變數綁在一起的變數型態
當要存取那些子資料時,便是使用 變數.子結構名稱 來像一個普通變數一樣存取。
栗子
#include <iostream>
using namespace std;
struct score{
string name;
int math;
};
int main(){
score luo;
luo.name = "luo";
luo.math = 0;
}
搭配陣列使用
#include <iostream>
using namespace std;
struct score{
string name;
int math;
};
int main(){
score students[100];
int n;
cin >> n;
for(int i=0; i<n; ++i)
cin >> students[i].name >> students[i].math;
//輸入n個學生ㄉ名字和數學成績
}
好耶語法衝刺結束ㄌ
C++語法衝刺的啦(3)
By mouyilai
C++語法衝刺的啦(3)
- 183