c++放課

我美感很差,簡報略為簡陋請見諒

講師介紹

賴冠澐

  • 成功店言 膠踅
  • 踅樹立:c++,pisen,惘葉
  • 性趣:打扣,睡覺

@ckcsc35th_laialan

黃博崇

  • 成功電研 教學兼總務
  • 學術力:c++

先來無聊的科普

一個c++程式是如何執行的?

編譯 -> 生成執行檔(machine code) -> 執行

machine code: 電腦硬體看得懂的指令集

why learn c++?

優點:

  • 執行速度快
  • 廣泛使用
  • 能控制部分電腦硬體(ex: 記憶體)

 

缺點:

  • 難學
  • 程式容易爛掉,ex: 記憶體管理不當(與"能控制部分電腦硬體"是相對的)

環境建置

Windows(非ide)

  • 編譯器 - 我用msys2的gcc安裝包
  • 執行 - 在cmd執行g++ [name].cpp -o [name]

或是用wsl

linux/macos

  • 編譯器 - 用package installer裝gcc
  • 執行 - 在terminal執行g++ [name].cpp -o [name]

第一個程式

#include <iostream>

include

引用c++函式庫(工具庫)

iostream為內建輸出入的函式庫

#include <bits/stdc++.h>

bits/stdc++.h為常用函式庫大集成

using namespace (不一定要用)

#include <iostream>

using namespace std;

命名空間  - 確保函式庫裡的名稱不會和其他函式庫撞名

iostream的命名空間是std

宣告主函式main

#include <iostream>

using namespace std;

int main(){
	//do something
}

程式預設執行main以內的指令

回傳給shell的return code->

<-main函式

輸出內容

#include <iostream>

using namespace std;

int main(){
	cout<<"hi i am alanlai";
	return 0; //not necessary
}

cout<<"內容";

如果沒有using namespace std;

#include <iostream>

int main(){
	std::cout<<"hi i am alanlai";
	return 0; //not necessary
}

c++基本語法規則

每個語句都要加分號,代表結束

(可以不用換行,但為了可看性著想還是會換)

語句包括變數宣告,函式呼叫等等

除了#後的語句不加分號

{}大括號表示一整個陳述,會從上到下執行

例如函式,迴圈for/while等

變數

寫程式時時常需要紀錄一些資訊,這時候就要變數

變數有不同形態

  • int: 整數
  • long long:較大的整數
  • float: 浮點數(小數)
  • double: 大浮點數
  • char: 單一字元
  • bool: 布林值,只有0或1
  • string: 字串,需include string.h

宣告

// 型態 名稱;
int value;
double value2;
string value3;

賦值

// 型態 名稱 = 值;
int value = 1;
//or
int value2;
value2 = 3493845;

//字串
string value3 = "hihihi";

如果給不同於其型別的值會報錯

ex: int value = 99.99

同時宣告多個同型別的變數

int value1, value2=999, value3; // use comma

輸出入

輸出換行 \n (跳脫字元)

cout << "hihiihihi\n";

// or

cout<< "hihihihihi" << endl;

endl會std::flush

輸出變數

#include <iostream>

using namespace std;

int main(){
  int number;
  number = 123;
  cout << number << "\n";
}

輸入變數

#include <iostream>

using namespace std;

int main(){
  int number;
  cin >> number;
}

patrickh特別強

另一種陣列 - 動態指標

優點;

  • 能隨意改變陣列大小
  • 以變數指定陣列初始大小

缺點;

  • 難寫
  • 容易爛
  • 危險(記憶體不易管理)

推薦的動態陣列用法 - vector

  • c++內建動態陣列實作

main函式

從命令列傳入參數:

#include <iostream>
int main(int argc, char *argv[]) {
  // argc: number of arguments
  // argv: actual arguments (argument starts at 1)
  ;
}

回傳:

  • return 0: 系統會判定為正確執行
  • return 1: 不正常執行 (有些judge會判定此為RE)

指標

每個變數宣告時都會有一個相對應的記憶體地址

變數前加&即可輸出其記憶體位址(一個16進位數)

int test = 1;
cout << &test;

指標變數

利用指標儲存一個記憶體位址,並間接指向它

指標也是一種變數,可以隨意改變其指向的記憶體位址

語法

int *pointer;
int test1 = 123, test2 = 456;

pointer = &test1;
cout << *pointer << "\n"; //123

pointer = &test2;
cout << *pointer << "\n"; //456

pointer = &test1;
*pointer = 20
cout << test1 << "\n"; //20

pointer = &test2;
*pointer = 89
cout << test2 << "\n"; //89

pointer = test1 // error!!
*pointer = &test2; // error!!
  • 變數前不加*,代表 回傳/改變 指標變數的記憶體地址 
  • 變數前加*,代表 回傳/改變 指標所指向的記憶體位址的值

兩個不能互相指定

陣列

陣列本身是就是指標,其指向陣列第一項的地址

int array[100]

array存array[0]的地址

=*(array+i)         第0項往後i項的值

array[i]
cout<<array;

array[i]的記憶體地址

cout<<array+i;

函數傳入指標

可以利用指標把區域變數丟給其他函數去修改

(否則只是複製到新的記憶體)

*區域變數:宣告在某個大括號(陳述區塊)裡,其有效範圍也只在大括號裡

*全域變數:宣告在最外面,有效範圍為全部


void add(int *a, int *b){
  *a += *b;
}

int main(){
  int aa=1, bb=2;
  add(&aa, &bb); //傳入aa, bb的記憶體地址
  // error: add(1, 2);
  // 1, 2不是一個記憶體地址
  cout << aa;
}

變數

void change(int *a){
  a[2] = 10;
}

int main(){
  int arr[10];
  arr[2] = 9;
  cout << arr[2] << "\n";
  change(arr);
  cout << arr[2] << "\n";
}

陣列

實作:交換函式

void swap(int *a, int *b){
    int tmp = *a;
    *a = *b;
    *b = tmp;
}

int main(){
    int aa = 2, bb = 10;
    swap(&aa, &bb);
    cout << aa << " " << bb << "\n";
}

應用

物件導向

struct / class

c++裡的struct可以做到跟class一模一樣的功能

 

但用class看起來比較厲害

用途:把多種型態的變數(和函式)包裝成一個自定義的型態

語法

struct 結構名稱{
  變數1型態 變數1名稱;
  變數2型態 變數2名稱;
  ...
  ...
  ...
  結構名稱(參數){
  	// do something
  }
  函式1型態 函式1名稱(參數){
  	// do something
  }
  ...
  ...
};

// 宣告
結構名稱 名稱;
// if 有預設呼叫函式
// 結構名稱 名稱(參數);

cout << 名稱.變數1名稱;

名稱.變數2名稱 = 值;

名稱.函式1型態(參數);

<- 宣告時會呼叫這個(不必要)

struct mystruct{
  int a;
  int b;
  string str;
  
  // caution don't use the same name in arguments and variables
  int add(int c){
  	return a+b+c;
  }
  
}

mystruct var;

cout << var.str;

var.a = 3;
var.b = 2;

cout << var.add(123);

example:

如果用指標指向struct,所有.要改成->

實作linked list

用指標串起多個變數,形成類似陣列的東西

每一項會有一個值,和一個指標指向下一個項目

#include <bits/stdc++.h>

using namespace std;

struct linked{
	int val;
	linked *next = nullptr;
};

int main(){
	linked *head = new linked;
	linked *cur = head;
    	// input n values to linked list and output these n values
	int n;
	cin >> n;
	for(int i = 0;i < n;++i){
		int a;
		cin >> a;
		cur->val = a;
		cur->next = new linked;
		cur = cur->next;
	}
	for(int i = 0;i < n;++i){
		cout << head->val << " ";
		head = head->next;
	}
}

c++放課

By alan lai

c++放課

  • 382