陳仲肯
* 取值:指標變成值
& 取址:值變成指標
宣告:在變數名字前加一個*
指標可以加減喔
int *pointer;
int* a,b;//a是指標,b是值
int *a,*b;//ab都是指標
int a;
int *pa=&a;
cout<<&a<<'\n';
cout<<pa<<'\n';
0x7ffdbddd9e3c
0x7ffdbddd9e3c
int a[10]={1,2,3,4,5,6,7,8,9,10};
int *p=a;//=&a[0]
cout<<a[5]<<'\n';
cout<<*(p+5)<<'\n';
6
6
int a[10]={1,2,3,4,5,6,7,8,9,10};
for(int i=0;i<10;++i){
cout<<a[i]<<'\n';
}
for(int *p=a;p!=a+10;++p){
cout<<*p<<'\n';
}
int a[10]={1,2,3,4,5,6,7,8,9,10};
int *p=a;
cout<<a[1000]<<'\n';
cout<<*(p+1000)<<'\n';
cout<<*(p+7122)<<'\n';
cout<<*(p+8787)<<'\n';
Segmentation fault
或讀到沒用的值
變數的綽號
int a=5;
int &b=a;
a=3;
cout<<a<<' '<<b<<'\n';
b=7122;
cout<<a<<' '<<b<<'\n';
3 3
7122 7122
用指標時的&:取址
用參考時的&:宣告時要用
int a=5;
int *p=&a;
int *&b=p;
int c,d;
p=&c;
cout<<p<<' '<<b<<'\n';
b=&d;
cout<<p<<' '<<b<<'\n';
int a=5;
int *p=&a;//指標
int *&b=p;//指標的參考
int c=7,d=8;
p=&c;
cout<<*p<<' '<<*b<<'\n';
b=&d;
cout<<*p<<' '<<*b<<'\n';
7 7
8 8
函數?函式?
都可以
int a[10]={1,2,3,4,5,6,7,8,9,10};
int b;
b=a[0]*a[5];
b=a[6]*a[3];
b=a[7]*a[1];
b=a[2]*a[2];
b=a[8]*a[7];
b=a[9]*a[5];
當你一直做重複的事你就會覺得很煩
(有可能伴隨著值)
回傳值型態 函數名字(參數型態 參數名字,參數型態 參數名字...){
做事情
}
return;
return 變數;
void hello(){
cout<<"Hello\n";
}
int one(){
cout<<"1\n";
return 1;
}
void hello(){
cout<<"Hello\n";
}
int main(){
hello();
}
void num(int n){
cout<<n<<'\n';
}
int main(){
int a=3;
num(5);
num(a);
}
int one(){
return 1;
}
int main(){
int a;
a=one();
cout<<a<<'\n';
cout<<one()<<'\n';
}
int a[10]={1,2,3,4,5,6,7,8,9,10};
int multiply(int first,int second){
return a[first]*a[second];
}
int main(){
int b;
b=multiply(0,5);
b=multiply(6,3);
b=multiply(7,1);
b=multiply(2,2);
b=multiply(8,7);
b=multiply(9,5);
}
就可以把原本的程式寫成這樣
雖然現在沒有比較短
但是當函數裡的程式有十幾行就會短很多了
#include <iostream>
using namespace std;
int hi;
int main(){
}
#include <iostream>
using namespace std;
int main(){
int sum=0;
for(int i=0;i<5;++i){
sum+=i;
cout<<sum<<'\n';
}
}
#include <iostream>
using namespace std;
void printsum(){
cout<<sum<<'\n';
}
int main(){
int sum=0;
for(int i=0;i<5;++i){
sum+=i;
printsum();
}
}
#include <iostream>
using namespace std;
int sum=0;
void printsum(){
cout<<sum<<'\n';
}
int main(){
for(int i=0;i<5;++i){
sum+=i;
printsum();
}
}
#include <iostream>
using namespace std;
int sum=0;
void printsum(){
cout<<sum<<'\n';
}
int main(){
for(int i=0;i<5;++i){
char a='a';
sum+=i;
printsum();
}
cout<<"i="<<i<<'\n';
cout<<"a="<<a<<'\n';
}
#include <iostream>
using namespace std;
int sum=0;
void printsum(){
cout<<sum<<'\n';
}
int main(){
int i;char a;
for(i=0;i<5;++i){
a='a';
sum+=i;
printsum();
}
cout<<"i="<<i<<'\n';
cout<<"a="<<a<<'\n';
}
以int為例
int f(int a) //pass by value //傳值
int f(int* a) //pass by pointer //傳指標
int f(int& a) //pass by reference //傳參考
傳值 | 傳指標 | 傳參考 | |
---|---|---|---|
作法 | 呼叫時複製一份 | 直接丟指標 | 直接丟參考 |
在函數中修改 會不會影響 原本的值 |
不會 | 會 | 會 |
f(b);
void f(int* a){
*a=5;
}
int main(){
int a=87;
cout<<a<<'\n';
f(&a);
cout<<a<<'\n';
}
87
5
void f(int& a){
a=5;
}
int main(){
int a=87;
cout<<a<<'\n';
f(a);
cout<<a<<'\n';
}
87
5
int j(){
return 3;
}
int j(int a){
return a+5;
}
int j(char c){
return c-'0';
}
int main(){
cout<<j()<<'\n';
cout<<j(8)<<'\n';
cout<<j('3')<<'\n';
}
int sum(int list[],int len){
int ans=0;
for(int i=0;i<len;++i)ans+=list[i];
return ans;
}
int main(){
int a[10]={1,2,3,4,5,6,7,8,9,10};
cout<<sum(a,10);
}
int sum(int* list,int len){
int ans=0;
for(int i=0;i<len;++i)ans+=list[i];
return ans;
}
int main(){
int a[10]={1,2,3,4,5,6,7,8,9,10};
cout<<sum(a,10);
}
其實相當於傳入第一格的指標,不是複製一份陣列
但是通常陣列都會宣告為全域變數,所以很少用
recursion
自己呼叫自己
int pow(int a,int b){
//return a^b
//b>=0
if(b==0)return 1;
return a*pow(a,b-1);
}
b=0
回傳a^0=1
pow(a,b)
比如暴力枚舉下棋的所有可能:
黑棋函數:枚舉黑棋所有可能
白棋函數:枚舉白棋所有可能
結構、類別
struct a{
...
};
a b;
struct 結構名字{
變數型態 變數名字;//(屬性)
變數型態 變數名字,變數名字;
函數
}實體名字;//兩種宣告都可以,沒有要宣告就直接分號
結構名字 實體名字;
dot *a;
cout<<a->x;
struct dot{
int x,y;
dot(){
x=y=0;
}
void move(int dx,int dy){
x+=dx;
y+=dy;
cout<<"In dot.move:"<<x<<' '<<y<<'\n';
}
};
int main(){
dot a;
a.move(1,1);
cout<<"In main:"<<a.x<<' '<<a.y<<'\n';
}
In dot.move:1 1
In main:1 1
struct dot{
int x,y;
dot():x(0),y(0){}
dot(int a,int b):x(a),y(b){}
}
+ - * / %
+= -=...
輸入輸出(>> <<)
a+b
a.operator+(b)
a+=b
a.operator+=(b)
a+b
a+=b
a+=3
a++
(a的型態)的operator+(b的型態)
(a的型態)的operator+=(b的型態)
(a的型態)的operator++()
(a的型態)的operator+=(int)
//在struct定義的裡面
struct dot{
dot operator+(dot other){
//處理自己+other
}
};
//在struct定義的外面
dot operator+(dot a,dot b){
//處理a+b
}
型態 | 可不可以 |
int+int | X |
int+dot | X |
dot+int | O |
dot+dot | O |
先了解cin cout如何輸入輸出:
ostream的實體<<a的回傳值是一個ostream的參考
cout<<a<<b => (cout<<a)<<b
如何做到一長串輸入輸出?
這跟a=b=3一樣:
a=(b=3)
其實指定運算子都會回傳東西,所以可以
a= b+=5 之類的
( )
int a=1,b=2;
a=b++;
//a=2,b=3
int a=1,b=2;
a=++b;
//a=3,b=3
int a=1,b=2;
(a=b)+=5;
cout<<a<<' '<<b<<'\n';
7 2
ostream& operator<<(ostream& s,dot a){
s<<a.x<<' '<<a.y;
return s;
}
istream& operator>>(istream& s,dot& a){
s>>a.x>>a.y;
return s;
}
dot a;
cin>>a;
cout<<a<<'\n';
不常用,底爸(debug)時才會自訂輸出,輸入也不必多此一舉
寫一個鏈結串列
1
13
8
5
3
2
1
a[7]={
}
普通的陣列要刪掉一個元素時:
1
13
8
5
2
1
a[6]={
}
普通的陣列要刪掉一個元素時:
O(N)!!!!
1
1
鏈結串列要刪掉一個元素時:
3
2
5
8
13
1
1
2
5
8
13
鏈結串列要刪掉一個元素時:
1
1
2
5
8
13
鏈結串列要刪掉一個元素時:
1
1
2
5
8
13
鏈結串列要刪掉一個元素時:
1
1
鏈結串列要加一個元素時:
2
8
13
5
1
1
2
8
13
5
3
鏈結串列要加一個元素時:
struct node{
int val;
node *next=NULL;
};
struct node{
int val;
node *next=NULL;
int& operator[](int step){
if(step==0){
return val;
}
if(next==NULL){
cout<<"ERROR\n";
return val;
}
return (*next)[step-1];
}
};
node a,b,c;
a.next=&b;
b.next=&c;
a.val=1;
b.val=2;
c.val=3;
cout<<a[0]<<' '<<a[2]<<'\n';
struct node{
int val;
node *next=NULL;
node(int a):val(a){}
int& operator[](int step){
if(step==0){
return val;
}
if(next==NULL){
cout<<"ERROR\n";
return val;
}
return (*next)[step-1];
}
node& operator+=(node& n){
next=&n;
return *this;
}
};
node a(1),b(2),c(3);
a+=b+=c;
cout<<a[0]<<' '<<a[1]<<' '<<b[1]<<'\n';
#include <iostream>
using namespace std;
struct node{
int val;
bool dead=0;
node *next=NULL;
node& operator+=(node& n){
next=&n;
return *this;
}
};
int const N=1e6+10;
int n,m;
node d[N];
int main(){
cin>>n>>m;
for(int i=1;i<=n-1;++i){
d[i].val=i;
d[i]+=d[i+1];
}
d[n].val=n;
int killer;
for(int i=0;i<m;++i){
cin>>killer;
if(d[killer].dead||d[killer].next==NULL){
cout<<"0u0 ...... ?\n";
continue;
}
cout<<d[killer].next->val<<'\n';
d[killer].next->dead=1;
d[killer]+=*(d[killer].next->next);
}
}