暑假資讀[2]
struct、object、指標、參考、運算子重載
講師:張秉中
自我介紹
- 227
- OJ上的handle不一(pcc/s10755168/pingchungchang...)
- 不太會資訊
先講萬用標頭檔
#include <bits/stdc++.h>
https://gist.github.com/Einstrasse/ac0fe7d7450621a39364ed3b05cacd11
指標
pointer
功能
- 傳遞資料到函式
- 提高效率
- 動態資料結構(eg:treap,動態開點線段樹)
語法
- 宣告: type* (eg:int* a)
- 取值:*a (eg:*a = 5)
- 取位址:&a (eg: int* a = &b)
範例
#include <iostream>
using namespace std;
int main(){
int *a,*b;
a = new int(5);//new ___ 的回傳值為指標
int c = 8;
b = &c;
cout<<(*a)+(*b)<<endl;
b = a;
*a = 10;
cout<<(*a)<<' '<<(*b)<<endl;
}
範例
#include <iostream>
using namespace std;
int main(){
int *a,*b;
a = new int(5);//new ___ 的回傳值為指標
int c = 8;
b = &c;
cout<<(*a)+(*b)<<endl;
b = a;
*a = 10;
cout<<(*a)<<' '<<(*b)<<endl;
}
13
10 10
參考
reference
功能
- 相當類似指標
- 可以想成是一個變數的別名
- 傳參數到函式
- 不用考慮一堆&,*
語法
- 函數型態:type& (eg:int& a)
- 其他時候當正常變數使用
範例
#include <iostream>
using namespace std;
int main(){
int b = 10;
int &a = b;
a = 13;
cout<<a<<' '<<b<<endl;
b = 48763;
cout<<a<<' '<<b<<endl;
}
13 13
一些小問題
關於&
- 指標&:取址
- 參考&:宣告
- int&int:位元運算
指標的指標
指標的參考
#include <iostream>
using namespace std;
int main(){
int a = 5;
int *b= &a;
int* &c = b;
*c = 7414;
cout<<a<<' '<<*b<<' '<<*c<<endl;
int** d = &c;
int *e= new int(10);
*d = e;
cout<<a<<' '<<*b<<' '<<*c<<' '<<*(*d)<<' '<<*e<<endl;
}
猜猜看結果
#include <iostream>
using namespace std;
int main(){
int a = 5;
int *b= &a;
int* &c = b;
*c = 7414;
cout<<a<<' '<<*b<<' '<<*c<<endl;
int** d = &c;
int *e= new int(10);
*d = e;
cout<<a<<' '<<*b<<' '<<*c<<' '<<*(*d)<<' '<<*e<<endl;
}
猜猜看結果
#include <iostream>
using namespace std;
int main(){
int a = 5;
int *b= &a;
int* &c = b;
*c = 7414;
cout<<a<<' '<<*b<<' '<<*c<<endl;
int** d = &c;
int *e= new int(10);
*d = e;
cout<<a<<' '<<*b<<' '<<*c<<' '<<*(*d)<<' '<<*e<<endl;
}
函式
function
function
- f(x) = 3x+10
- f(x) = 1
- f(x,y,z) = xyz
...
- C++ function 只可以回傳一個變數
- 如果不打算回傳,可以寫void
基本語法
#include <bits/stdc++.h>
using namespace std;
string check(string account,int password){
if(account == "pcc"&&password == 48763)return "correct";
else return "error";
}
int main(){
cout<<check("pcc",48763)<<endl;
cout<<check("pccc",123)<<endl;
}
指標跟參考跟函式
#include <bits/stdc++.h>
using namespace std;
void swap_value(int *a,int *b){
int c = *b;
*b = *a;
*a = c;
return;
}
int main(){
int x = 10,y = 5;
swap_value(&x,&y);
cout<<x<<' '<<y<<endl;
}
#include <bits/stdc++.h>
using namespace std;
void swap_value(int &a,int &b){
int c = b;
b = a;
a = c;
return;
}
int main(){
int x = 10,y = 5;
swap_value(x,y);
cout<<x<<' '<<y<<endl;
}
lambda
- 可以當成在程式內宣告函式的方式
- 順便講一下auto
#include <bits/stdc++.h>
using namespace std;
int x = 5;
auto add = [](int a,int b){
return a+b;
};
int main(){
int arr[] = {1,2,3,4,5};
for(int i = 0;i<5;i++){
cout<<add(arr[i],x)<<',';
}
cout<<endl;
cout<<x<<endl;
auto minus = [&arr,&x](){
for(int i = 0;i<5;i++)arr[i] -=x;
x--;
return;
};
minus();
for(int i = 0;i<5;i++)cout<<arr[i]<<',';
cout<<endl;
cout<<x<<endl;
minus();
for(int i= 0;i<5;i++)cout<<arr[i]<<',';
cout<<endl;
cout<<x<<endl;
}
lambda
- capture也可以是lambda欸
#include <bits/stdc++.h>
using namespace std;
int main(){
int x = 0,y = 0;
auto g = [](int a,int b){
return a+b;
};
auto f = [&g](){
return g(g(1,2),g(1,2));
};
cout<<f(g);
}
分隔線
本頁以下的內容基本上很少用到(或幾乎用不到)
不會也不會怎樣
(但是右邊那幾頁還是要學喔)
函式指標
Function pointer
- 就是把function當成變數來儲存
- 基本上不常用到,除非打模板
#include <bits/stdc++.h>
using namespace std;
string f(int a,int b){
return string(1,'A'+a-1)+(char)('A'+b-1);
}
int main(){
string (*func_ptr)(int,int) = f;
cout<<func_ptr(1,3);
}
函式指標
Function pointer
- 真的就是把function當成變數來儲存
#include <bits/stdc++.h>
using namespace std;
string f(int a,int b){
return string(1,'A'+a-1)+(char)('A'+b-1);
}
string g(int c,int d){
return "hi";
}
int main(){
string (*func_ptr)(int,int) = f;
string (*func_ptr2)(int,int) = g;
vector<string(*)(int,int)> v;
v.push_back(func_ptr);
v.push_back(func_ptr2);
for(int i = 0;i<v.size();i++){
cout<<v[i](1,3)<<endl;
}
}
大雜燴
- capture是空的lambda可以當成function pointer使用
#include <bits/stdc++.h>
using namespace std;
string f(int a,int b){
return string(1,'A'+a-1)+(char)('A'+b-1);
}
string g(int c,int d){
return "hi";
}
int main(){
auto k = [](int a,int b){
return (string)"AcWaTle";
};
string(*func_ptr1)(int,int) = f;
string(*func_ptr2)(int,int) = g;
vector<string(*)(int,int)> v = {f,g,k,[](int a,int b){
return (string)"HIHI";}};
for(auto &i:v){
cout<<i(1,3)<<endl;
}
}
struct
當你想要存一個學生的資料
- 身高(int)
- 體重(double)
- 姓名(string)
How?
- int height[],float weight[],string name[]
- tuple<int,float,string>
- pair<int,pair<float,string>>
- struct student
How?
-
int height[],float weight[],string name[]排序不便 - tuple<int,float,string>
-
pair<int,pair<float,string>>當元素很多你就知道了 - struct student 相對方便,還可以寫函式
語法
Text
struct student{
int height,birthday;
float weight;
char name[30];
};
/*-------------------------------*/
#include <string>
struct student{
string student_id;
float weight;
};
語法
Text
#include <iostream>
#include <string>
using namespace std;
struct student{
int height;
float weight;
float bmi;
string name;
student(){
height = 0;
weight = 0;
bmi = 0;
name = "unknown";
}
student(int h,float w){
height = h;
weight = w;
bmi = weight/(height/100.0)/(height/(100.0));
}
void rename(string s){
name = s;
}
};
int main(){
student rata(172,45.0);
rata.rename("ckpc_rata");
cout<<rata.name<<' '<<rata.bmi;
}
class
- 基本上競程很少用到
- 功能大致上跟struct差不多
語法
#include <iostream>
#include <string>
using namespace std;
struct wheel{
int radius;
wheel(){}
};
class car{
public:
wheel wheels;
string name;
int x,y;
void move(int dx,int dy){
x += dx;
y += dy;
}
car(int px,int py,wheel w,string s){
wheels = w;
x = px;
y = py;
name = s;
}
car(){
x = y = 0;
name = "unknown";
}
private:
string id;
};
int main(){
wheel ww;
ww.radius = 20;
car bmw(0,0,ww,"my car");
cout<<bmw.name<<' '<<bmw.wheels.radius<<endl;
bmw.move(1,2);
cout<<bmw.x<<' '<<bmw.y<<endl;
// cout<<bmw.id<<endl; ??????private???
}
分隔線
- 以下的完全用不到(但我覺得蠻好玩的)
繼承
inheritance
- 當同樣的code不想一直重寫:
#include <bits/stdc++.h>
using namespace std;
#define ll long long
class A{
public:
int x,y,z;
A(){
x = y = z = 0;
}
void getval(){
cout<<x<<y<<z<<endl;
}
};
class B:public A{
public:
B(){
x = y = z = 1;
}
};
int main(){
A* a = new B;
a->getval();
}
header files
自訂標頭檔
編譯指令:g++ -std=c++11 -c ___.o test.h test.cpp others.cpp
g++ -std=c++11 -o test.exe ___.o _____.o _.o(or just *.o)
- test.h
#include<bits/stdc++.h>
using namespace std;
class CK{
public:
CK();
vector<string> students;
string principal;
int get_students();
void change_principal(string s);
};
#include "test.h"
#include <bits/stdc++.h>
using namespace std;
CK::CK(){
for(int i = 1;i<=33;i++){
students.push_back(to_string(i));
}
}
void CK::change_principal(string s){
principal = s;
}
int CK::get_students(){
return students.size();
}
int main(){
int c;
cin>>c;
return 0;
}
- test.cpp
運算子重載
這也很少用到,通常用來除錯或打模版
來看看二維平面
- a+b?
- a-b?
- a*b?
- a/b?
- a += b?
來看看二維平面
- a+b? ->座標相加
- a-b? ->座標相減
- a*b? ->內積
- a/b? ->外積
- a += b? 其實就是a = a+b
How?
#include <bits/stdc++.h>
using namespace std;
struct point{
int x,y;
point(){
x = y = 0;
}
point(int xx,int yy){
x = xx,y = yy;
}
point operator+(point b){
return point(x+b.x,y+b.y);
}
point operator-(point b){
return point(x-b.x,y-b.y);
}
int operator*(point b){
return x*b.x+y*b.y;
}
point operator*(int k){
return point(k*x,k*y);
}
};
point operator+=(point &a,point &b){//也可以寫在struct外
a.x += b.x;
a.y += b.y;
return a;
}
int main(){
point a(1,2);
point b(2,-1);
cout<<a.x<<' '<<a.y<<' '<<(a+b).x<<' '<<a*b<<' '<<(a*3).x<<endl;
}
其他運算子
#include <iostream>
using namespace std;
struct point{
int x,y;
point(){
x = y = 0;
}
point(int xx,int yy){
x = xx,y = yy;
}
bool operator<(const point &b)const{//比大小先比x在比y
if(x != b.x)return x<b.x;
else return y<b.y;
}
};
istream& operator>>(istream& in,point &a){
in>>a.x>>a.y;
return in;
}
ostream& operator<<(ostream& out,point a){
out<<a.x<<' '<<a.y;
return out;
}
int main(){
point a(1,2);
point b(2,-1);
cin>>a;
cout<<a<<endl;
}
統整一下一定要會的內容
- 指標跟參考
- function
- struct
這些之後學排序很好用
可學可不學的
auto
#include <bits/stdc++.h>
運算子重載
最後做些練習吧
設計一個一維線段的struct line
- line a(int,int):初始畫線段
- a.start,a.end:線段的起點跟終點
- a+b:交集線段
- a.size():區間長度
- a.split(int e):由a的起點到e的線段(保證e再線段a內)
- cout<<a:印出a的起點跟終點位置
一些範例
在main裡加入這堆要可以跑才算成功
line a(1,100);
line b(10,11);
a = a+b;
cout<<a<<endl;
line c(0,a.end);
c.split(a.start)
cout<<c.size()
小練習
寫一個計算2*2矩陣的struct
- a*b:矩陣乘法
- det(a):矩陣行列式
- cin>>a:輸入
- cout<<a;輸出
- a+b:元素相加
暑假資讀[2]
By ck1100890張秉中
暑假資讀[2]
- 315