C++基礎語法

Kun發表於2022-01-13

C++初識

第一個C++程式

編寫一個C++程式總共分為4個步驟

  • 建立專案
  • 建立檔案
  • 編寫程式碼
  • 執行程式

建立專案

Visual Studio是我們用來編寫C++程式的工具

C++基礎語法

建立檔案

C++基礎語法 C++基礎語法 C++基礎語法

編寫程式碼

#include <iostream>
using namespace std;

int main() 
{
	cout << "hello world" << endl;

	/*
	main函式是一個程式的入口
	每個程式都必須有這麼一個函式
	有且僅有一個
	*/

	system("pause");

	return 0;
}

執行程式

C++基礎語法

註釋

作用:在程式碼中加一些說明和解釋,方便自己或其他程式設計師閱讀程式碼

兩種格式

  1. 單行註釋://說明資訊

    • 通常放在一行程式碼上方,或者一條語句的末尾,對該程式碼說明
  2. 多行註釋:/*說明資訊*/

    • 通常放在一段程式碼的上方,對該段程式碼做整體說明

    編譯器在執行程式碼時,會忽略註釋的內容

變數

作用:給一段指定的記憶體空間起名,方便操作這段記憶體

語法:資料型別 變數名 = 初始值;

示例

#include <iostream>
using namespace std;

int main() 
{
	//變數的建立語法:資料型別 變數名 = 變數初始值
	int a = 10;

	system("pause");

	return 0;
}

常量

作用:用於記錄程式中不可更改的資料

C++定義常量兩種方式

  1. #define巨集常量:#define 常量名 常量值
    • 通常在檔案上方定義,表示一個常量
  2. cons修飾的變數:const 資料型別 變數名 常量值
    • 通常在變數定義前加關鍵字const,修飾改變數為常量,不可更改

示例

#include <iostream>
using namespace std;
// 巨集常量
#define day 7

int main() {

	cout << "一週總共有:" << day << "天" << endl;
    
	// const修飾變數
    
	const int year = 100;
    
	return 0;

}

關鍵字

作用:關鍵字是C++中預先保留的單詞(識別符號)

  • 在定義變數或者常量的時候,不要使用關鍵字

識別符號命名規則

作用:C++規定給識別符號(變數、常量)命名時,有一套自己的規則

  • 識別符號不能是關鍵字

  • 識別符號只能由字母、數字、下劃線組成

  • 第一個字元必須為字母或者下劃線

  • 識別符號中字母區分大小寫

    建議:給識別符號命名時,爭取見名知意的效果

資料型別

C++規定在建立一個變數或者常量時,必須要指定出相應的資料型別,否則無法給變數分配記憶體

整型

作用:整型變數能夠表示的是整數型別的資料

C++中能夠表示整型的型別有以下幾種方式,區別在於所佔記憶體不同

資料型別 佔用空間 取值範圍
short(短整型) 2位元組 -215~215-1
int(整型) 4位元組 -231~231-1
long(長整型) win為4位元組、Linux32位為4位元組/64位為8位元組 -231~231-1
long long(長長整型) 8位元組 -263~263-1

sizeof關鍵字

作用:利用sizeof關鍵字可以統計資料型別所佔記憶體大小

語法:sizeof(資料型別/變數)

示例

#include <iostream>
using namespace std;

int main() {

	int a = 5;

	cout << sizeof(a) << endl;

	cout << sizeof(int) << endl;
	
	const int year = 100;

	cout << sizeof(year) << endl;

	return 0;

}

實型(浮點型)

作用:用於表示小數

浮點型分為兩種:

  1. 單精度float
  2. 雙精度double

兩者的區分在於表示的有效數字範圍不同

資料型別 佔用空間 有效數字範圍
float 4bit 7為有效數字
double 8bit 15~16位有效數字
#include <iostream>
using namespace std;

int main() {

	// float
	float a = 5.6;

	cout << a << endl;

	// double
	double b = 5.6;

	cout << b << endl;

	//科學計數法表示
	float d = 3e2;   //代表 3 * 10 ^ 2

	cout << d << endl;
	

	return 0;

}

字元型

作用:字元型變數用於顯示單個字元

語法:char c = "a";

在顯示字元型變數時,用單引號鍵字元括起來,不要用雙引號

單引號內只能有一個字元,不可以是字串

  • C++和C中字元型變數只佔用1個位元組
  • 字元型變數並不是把字元本身放到記憶體中儲存,而是將對應的ASCII編碼放到儲存單元
#include <iostream>
using namespace std;

int main() {

	// 字元型
	char d = 'D';
	cout << d << endl;
	cout << (int)d << endl;  // 字元型對應ASCII編碼

	/*
	char d = "D";  建立字元型變數時候,要用單引號
	char d = 'hello';  建立字元型變數時候,單引號內只能有一個數值
	*/
	system("pause");
	

	return 0;

}

轉義字元

作用:用於表示一些不能顯示出來的ASCII字元

常用的轉義字元有://、/t、/n

#include <iostream>
using namespace std;

int main() {

	// 換行符  \n
	cout << "Hello World \n";
	cout <<"Hello World" << endl;

	// 反斜杆 \\

	cout << "\\" << endl;

	// 水平製表符 \t  可以整齊輸出資料
	cout << "Hello \t World";

	system("pause");
	return 0;

}

字串型

作用:用於表示一串字元

兩種風格

  1. C風格字串:char 變數名[] = "字串值"

    #include <iostream>
    using namespace std;
    
    int main() {
    
    	char a[] = "hello world";  // 雙引號
    	cout << a <<endl;
    	cout << sizeof(a) << endl;  // 12
    
    	system("pause");
    	return 0;
    
    }
    
  2. C++風格字串:string 變數名 = "字串值"

    #include <iostream>
    #include <string>  // 用C++風格字串的時候,要包含這個標頭檔案
    using namespace std;
    
    int main() {
    	
        // 包含一個標頭檔案
    	string a = "hello world";
    	cout << a <<endl;
    	cout << sizeof(a) << endl;  // 40
    
    	system("pause");
    	return 0;
    
    }
    

布林資料型別 bool

作用:布林資料型別代表真或假的值

bool型別只有兩個值

  • true:真(本質是1)
  • false:假(本質是0)

bool型別佔一個位元組大小

#include <iostream>
#include <string>  // 用C++風格字串的時候,要包含這個標頭檔案
using namespace std;

int main() {

	// 建立bool資料型別
	bool flag = true;  // true代表真
	cout << flag << endl;  // 本質上,1代表真的值,0代表假的值

	// 檢視bool型別佔用的記憶體空間
	cout << flag << endl;

	system("pause");
	return 0;

}

資料的輸入

作用:用於從鍵盤獲取資料

語法:cin >> 變數

#include <iostream>
#include <string>  // 用C++風格字串的時候,要包含這個標頭檔案
using namespace std;

int main() {

	// 整型
	int a = 0;
	cout << "請輸入一個整數:";
	cin >> a;
	cout << "整型變數a = " << a << endl;

	// 字串型
	string a = "hello";
	cout << "請輸入一個字串數:";
	cin >> a;
	cout << "字串型變數a = " << a << endl;

	// bool型
	bool a = false;  // 非空即為真
	cout << "請輸入一個bool數:";
	cin >> a;
	cout << "bool型變數a = " << a << endl;

	// 字元型
	char a = '0';
	cout << "請輸入一個字元:";
	cin >> a;
	cout << "字元型變數a = " << a << endl;

	// 浮點型
	float a = 3.14f;
	cout << "請輸入一個浮點數:";
	cin >> a;
	cout << "浮點型變數a = " << a << endl;

	system("pause");
	return 0;

}

運算子

作用:用於執行程式碼的運算

算術運算子

作用:用於處理四則運算

"+" 加, "-" 減, "/" 除, "*" 乘, "%" 取餘, "++" 遞增, "--"遞減

#include <iostream>
#include <string>  // 用C++風格字串的時候,要包含這個標頭檔案
using namespace std;

int main() {

	int a = 10;
	int b = 3;

	// +
	cout << a+b << endl;
	
	//-
	cout << a - b << endl;

	// / 兩個整數相除 結果為整數,將小數去除
	cout << a / b << endl;

	// *
	cout << a * b << endl;

	// % 兩個小數不可進行取餘運算
	cout << a % b << endl;

	system("pause");
	return 0;

}

++ 和 --

#include <iostream>
#include <string>  // 用C++風格字串的時候,要包含這個標頭檔案
using namespace std;

int main() {

	// ++ 遞增
	int a = 10;
	++a;  // 讓變數進行加一的結果,前置遞增
	a++;  // 後置遞增

	// 前置遞增 先進行變數+1,後進行表示式的運算
	int b = 10;
	int c = ++b * 10;
	cout << "前置b=" << b << endl;
	cout << "前置c=" << c << endl;
	// 後置遞增 先進行表示式的運算,後讓變數+1
	int b1 = 10;
	int c1 = b1++ * 10;
	cout << "後置b=" << b1 << endl;
	cout << "後置c=" << c1 << endl;

	system("pause");
	return 0;

}

賦值運算子

作用:用於將表示式的值賦給變數

"=" 等於, "+=" 加等於 , "-=" 減等於 , "/=" 除等於 , "%=" 餘等於 , "*=" 乘等於

#include <iostream>
#include <string>  // 用C++風格字串的時候,要包含這個標頭檔案
using namespace std;

int main() {

	int a = 10;
	int b = 20;

	// +=
	a += b;  // 相當於:a = a + b
	cout << a << endl;

	// -=
	a -= b;  // 相當於:a = a - b
	cout << a << endl;

	// /=
	a /= b;  // 相當於:a = a / b 
	cout << a << endl;

	// *= 
	a *= b;  // 相當於a = a * b
	cout << a << endl;

	// =
	a = b - a;
	cout << a << endl;

}

比較運算子

"=="等於 , "<=" 小於等於, ">=" 大於等於 , "!=" 不等於 , "<" 小於 , ">" 大於

返回bool型別

#include <iostream>
#include <string>  // 用C++風格字串的時候,要包含這個標頭檔案
using namespace std;

int main() {

	int a = 10;
	int b = 20;

	// >=
	cout << (a >= b) << endl;

	// <=
	cout << (a <= b) << endl;

	// ==
	cout << (a == b) << endl;

	// != 
	cout << (a != b) << endl;

	// <
	cout << (a < b) << endl;

	// >
	cout << (a > b) << endl;

}

由於運算的優先順序,要用括號隔開

邏輯運算子

作用:用於根據表示式的值返回真值或假值

"!" 非 , "&&" 與 , "||" 或

#include <iostream>
#include <string>  // 用C++風格字串的時候,要包含這個標頭檔案
using namespace std;

int main() {

	// 邏輯運算子

	// ! 真變假、假變真
	bool a = true;
	cout << !a<< endl;

	// && 兩個都為真,則為真;同真則真,其餘為假
	int a1 = 10;
	int b = 0;
	cout << (a1 && b) << endl;

	// || 只要有一個為真,則為真;同假則假,其餘為真
	cout << (a1 || b) << endl;
    
    // 綜合應用
   	cout << (a1 || !( a1 && ! a ) );

}

程式流程結構

C/C++支援最基本的三種程式執行結構:順序結構、選擇結構、迴圈結構

  • 順序結構:程式按順序執行,不發生跳轉
  • 選擇結構:依據條件是否滿足,有選擇的執行相應功能
  • 迴圈結構:依據條件是否滿足,迴圈多次執行某段程式碼

選擇結構

if語句

作用:執行滿足條件的語句

if語句的三種形式

  • 單行格式if語句
  • 多行格式if語句
  • 多條件的if語句

單行格式

#include <iostream>
using namespace std;

int main() {
	// 選擇結構 單行if語句
    
	// 使用者輸入一個數字
	int num = 1;
	cout << "請輸入一個數字:";
	cin >> num;

	// 判斷數字是否大於100,是則輸出原數
	if (num >= 100){  // 注意if語句後面不要加分號,否則,if將不會進行判斷
		cout << num; 
	}
}

多行if語句

#include <iostream>
using namespace std;

int main() {
	// 選擇結構 單行if語句
    
	// 使用者輸入一個數字
	int num = 1;
	cout << "請輸入一個數字:";
	cin >> num;

	// 判斷數字是否大於100,是則輸出原數;否則,輸出0
	if (num >= 100) {  // 注意if語句後面不要加分號,否則,if將不會進行判斷
		cout << num << endl; 
	} 
    else {
        cout << "0" << endl;
    }
}

多條件if語句

#include <iostream>
using namespace std;

int main() {
	// 選擇結構 單行if語句
    
	// 使用者輸入一個數字
	int num = 1;
	cout << "請輸入一個數字:";
	cin >> num;

	// 判斷數字是否大於600,是則輸出原數;數字是否小於600,大於0,是則輸出100;否則,輸出0
	if (num >= 600) {  // 注意if語句後面不要加分號,否則,if將不會進行判斷
		cout << num << endl; 
	} 
    else if (num >= 100) {
        cout << "100" << endl;
    }
    else {
        cout << "0" << endl;
    }
}

if ( 條件1 ) { 條件1滿足執行語句} else if ( 條件2 ) { 條件2滿足,同時條件1不滿足,執行的語句 }··· else { 都不滿足執行的語句 }

巢狀if語句

在if語句中,可以巢狀使用if語句,達到更加精確的條件判斷

案例:輸入3個數字,判斷出最大的數字

#include <iostream>
using namespace std;

int main() {
	int num = 1;
	int num1 = 1;
	int num2 = 1;
	cout << "請輸入三個數字:";
	cin >> num;
	cin >> num1;
	cin >> num2;

	if ( num > num1 ) {  // 判斷 num 和 num1
		if ( num > num2 ) {  // 判斷 num 和 num2
			cout << num << "最大" << endl;
		}
		else {
			cout << num2 << "最大" << endl;
		}
	}
	else {
		if (num1 > num2) {
			cout << num1 << "最大" << endl;
		}
		else {
			cout << num2 << "最大" << endl;
		}
		cout << "判斷完畢" << endl;
	}
}

三目運算子

作用:通過三目運算實現簡單的判斷

語法:表示式1 ? 表示式2 : 表示式3

#include <iostream>
using namespace std;

int main() {
	
	// 三目運算
	
	// 將 a 和 b 做比較,將大的值賦值給c
	int a = 10;
	int b = 20;
	int c = 0;

	c = a > b ? a : b;  // 如果 a 比 b 大,則將a賦值給c
    
    /*
    if ( a > b ) {
    	c = a;
    }
    else {
    	c = b
    }
    */

}

在C++中,三目運算子返回的是變數,可以繼續賦值

switch語句

作用:執行多條件分支語句

語法:

switch ( 表示式 ) {
    case 結果1: 執行語句; break;  // switch裡面不一定每個case都要對應break,break的作用的向外跳出一層
    ······
    default: 執行語句; break;  // 不一定需要default判斷
} 

示例

#include <iostream>
using namespace std;

int main() {
	
	// switch 語句

	// 電影打分
	int score = 0;
	cout << "請輸入分數:";
	cin >> score;
	cout << "您打的分數為:" << score << endl;

	switch (score) {
	case 10:
			cout << "是經典電影" << endl;
			break;  // 退出當前分支,如果沒有break,則會繼續向下執行
	default:  // 當所有條件不滿足時,執行該語句
			cout << "普通" << endl;

	}

}

缺點:判斷的時候,只能是整型或者字元型,不可以是一個區間

優點:結構清晰,執行效率高

注意

  • switch語句中表示式型別只能是整型或者字元型
  • case裡如果沒有break,那麼程式會一直向下執行

迴圈結構

while迴圈語句

作用:滿足迴圈條件,執行迴圈語句

語法:while ( 迴圈條件 ) { 迴圈語句 }

解釋:只要迴圈條件的結果為真,就執行迴圈語句

#include <iostream>
using namespace std;

int main() {

	int nu = 0;
		// 在螢幕中列印0到9的數字
	while ( nu < 10 )
	{
		cout << nu << endl;
		nu++;
	}
}
猜數字遊戲
#include <iostream>
using namespace std;
// time系統時間標頭檔案包含
#include <ctime>

int main() {

	// 新增隨機數的種子,利用當前系統時間生成隨機數,防止每次隨機數一樣
	srand((unsigned int)time(NULL));

	// 系統生成隨機數
	int rand_nu = rand() % 100 + 1; // rand()%100生成0到99的隨機數

	// 猜測數字
	int guess_nu = 0;
	while (guess_nu != rand_nu) {
		cout << "請輸入一個數字:";
		cin >> guess_nu;
		// 判斷
		if (guess_nu > rand_nu) {
			cout << "輸大了,請重新猜測!!!" << endl;
		}
		else if (guess_nu < rand_nu){
			cout << "輸小了,請重新猜測!!!" << endl;
		}
		else {
			cout << "恭喜你,猜對了!!!" << endl;
			break;
		}
	}
}

do···while迴圈語句

作用:滿足迴圈條件,執行迴圈語句

語法:do {迴圈語句} while (迴圈條件);

注意:與while的區別在於do...while會先執行一次迴圈時間,在判斷迴圈條件

#include <iostream>
using namespace std;

int main() {

	// do...while語句
	// 在螢幕中輸出 0 到 9 這10個數字
	int num = 0;

	do {
		cout << num << endl;
		num++;
	} 
	while (num <= 9);
}

水仙花數

水仙花數是指一個三位數,它的每個位上的數字的3次冪之和等於它本身

如:1 ^ 3 + 5 ^ 3 + 3 ^ 3 = 153

#include <iostream>
using namespace std;


int main() {

	int nu = 100;
	// 水仙花數
	do {
		int ge = 0;  // 定義個位的數字
		int shi = 0;  // 定義十位的數字 
		int bai = 0;  // 定義百位的數字
		
		ge = nu % 10;
		shi = nu / 10 % 10;
		bai = nu / 100;

			if (ge*ge*ge + shi*shi*shi + bai*bai*bai == nu){
				cout << "水仙花數:" << nu << endl;
			}
			nu++;

	} while ( nu <= 999 );
}

for迴圈語句

作用:滿足迴圈條件,執行迴圈語句

語法:for (起始表示式;條件表示式;末尾迴圈體) { 迴圈語句; }

#include <iostream>
using namespace std;


int main() {

	// for迴圈
	// 從數字0列印到9

	for (int i = 0; i < 10; i++ ) {
		cout << i << endl;
	}

	// 也可以
	int i = 0;
	for (;;) {
		if (i >= 10) {
			break;
		}
		cout << i << endl;
		i++;
	}
}

案例:敲桌子

從1開始數到數字100,如果數字個位含有7,或者數字十位含有7,或者該數字是7的倍數,我們列印敲桌子,其餘的列印輸出

#include <iostream>
using namespace std;


int main() {
	// 從1開始數到數字100,如果數字個位含有7,或者數字十位含有7,或者該數字是7的倍數,我們列印敲桌子,其餘的列印輸出

	for (int i = 1; i < 100; i++) {
		if (i % 10 == 7 || i % 100 / 10 == 7 || i % 7 == 0) {
			cout << "敲桌子" << endl;
		}
		else {
			cout << i << endl;
		}
	}
}

巢狀迴圈

作用:在迴圈中在巢狀一層迴圈,解決一些實際問題

#include <iostream>
using namespace std;


int main() {

	// 巢狀迴圈
	for (int i = 0; i < 5; i++) {
		for (int j = 0; j < 5; j++) {
			cout << "*";
		}
		cout << "" << endl;
	}

}

列印九九乘法口訣表

#include <iostream>
using namespace std;


int main() {

	// 巢狀迴圈
	for (int i = 1; i < 10; i++) {
		for (int j = 1; j < i+1; j++) {
			cout << i << "*" << j << "=" << i * j << "\t";
		}
		cout << "" << endl;
	}
}

跳轉語句

break語句

作用:用於跳出選擇結構或者迴圈結構

break使用的時機:

  • 出現在switch語句中,作用是終止case並跳出switch
  • 出現在迴圈語句中,作用是跳出當前的迴圈語句
  • 出現在巢狀迴圈中,跳出最近的內層迴圈語句

continue語句

作用:在迴圈語句中,跳過本次迴圈中餘下尚未執行的語句,繼續執行下一次迴圈

#include <iostream>
using namespace std;


int main() {
	
	for (int i = 0; i <= 10; i++) {
		if (i % 2 == 0) {
			continue;
		}
		else {
			cout << i << "\t";
		}
	}

}

goto語句

作用:可以無條件跳轉語句

語法:goto 標記;

解釋:如果標記的名稱存在,執行到goto語句時,會跳轉到標記的位置

#include <iostream>
using namespace std;


int main() {
	
	// goto
	cout << "hello" << endl;
	cout << "hello" << endl;
	cout << "hello" << endl;
	goto flag;
	cout << "hello" << endl;
	cout << "hello" << endl;
flag:
	cout << "world";
}

陣列

概述

陣列:就是一個集合,裡面存放了相同型別的資料元素

特點

  • 陣列中的每個資料元素都是相同的資料型別
  • 陣列是由連續的記憶體位置組成的

一維陣列

定義方式

  1. 資料型別 陣列名[ 陣列長度 ];
  2. 陣列型別 陣列名[ 陣列長度 ] = {值1, 值2...};
  3. 陣列型別 陣列名[ ] = {值1, 值2...}
#include <iostream>
using namespace std;


int main() {
	
	// 1. 資料型別 陣列名[ 陣列長度 ];
	int arr[4];
	arr[0] = 10;  // 賦值操作

	// 2. 陣列型別 陣列名[ 陣列長度 ] = {值1, 值2...};
	int arr1[5] = { 2, 2, 10, 20 };  // 如果在初始化資料的時候,沒有全部填完,會用0來填補剩餘資料
	cout << arr1[0] << endl;  // 通過下標索引取值

	// 利用迴圈取值
	for (int i = 0; i < 5; i++) {
		cout << arr1[i] << endl;  
	}
}

定義陣列的時候必須有一個初始的長度

陣列名的命名規範與變數名命名規範一致,不要和變數重名

陣列中下標是從0開始索引

陣列名

一維陣列名稱的用途:

  1. 可以統計整陣列在記憶體中的長度
  2. 可以獲取陣列在記憶體中的首地址
#include <iostream>
using namespace std;


int main() {

	int arr[5] = { 2, 2, 10, 20 };
	cout << "陣列所佔空間為" << sizeof(arr) << "\n" << "裡面有" << (sizeof(arr) / sizeof(arr[0])) << "個元素" << endl;
	cout << "陣列的首地址為" << (int)arr << "\n每個元素所佔空間為" << sizeof(arr[0]) << "\n陣列中第一個元素的地址為" << (int)&arr[0] << endl;
}

陣列名是一個常量,不可以進行賦值的操作

案例

找出陣列中的最大的元素
#include <iostream>
using namespace std;


int main() {
	//找出陣列中最大的數字
	int max_nu = 0;  // max_nu用於儲存最大值
	int arr[5] = { 300, 350, 200, 400, 250 };
	for (int i = 0; i < ((sizeof(arr) / sizeof(arr[0]))-1); i++) {
		max_nu = arr[i] > arr[i + 1] ? arr[i] : arr[i + 1];
	}
	cout << max_nu << endl;
}
組元素逆置

將陣列中的元素首尾進行互換

#include <iostream>
using namespace std;


int main() {
	// 陣列裡面的內容逆轉
	int arr1[5] = { 300, 350, 200, 400, 250 };
	int end = sizeof(arr1) / sizeof(arr1[0]);  // 末尾下標
	int start = 0;  // 起始下標
	while (start < end) {
		int temp = arr1[start];
		arr1[start] = arr1[end];
		arr1[end] = temp;
		start++;
		end--;
	}
	for (int i = 0; i < (sizeof(arr1) / sizeof(arr1[0])); i++) {
	cout << arr1[i] << endl;
	}
}

氣泡排序

作用:最常用的排序演算法,對陣列內的元素進行排序

  1. 比較相鄰的元素。如果第一個比第二個大,就交換他們兩個
  2. 對每一對相鄰元素做同樣的工作,執行完畢後,找到第一個最大值
  3. 重複以上的步驟,每次比較次數-1,直到不需要比較

排序 int arr = { 4, 2, 8, 0, 5, 7, 1, 3, 9};

#include <iostream>
using namespace std;


int main() {
	// 利用氣泡排序,實現升序排序
	int arr[ ] = {4, 2, 8, 0, 5, 7, 1, 3, 9};
	cout << "排序前:";
	for (int i = 0; i < (sizeof(arr) / sizeof(arr[0])); i++) {
		cout << arr[i] << "  ";
	}
	for (int i = 0; i < (sizeof(arr) / sizeof(arr[0]) - 1); i++) {  // 排序次數為元素個數減一
		for (int j = 0; j < (sizeof(arr) / sizeof(arr[0]) - 1 - i); j++) {  // 內層迴圈對比次數元素個數 - 排序次數 - 1
			if (arr[j] > arr[j + 1]) {  // 如果前一個數字比第二個數字大,交換順序
				int temp = arr[j];
				arr[j] = arr[j + 1];
				arr[j + 1] = temp;
			}
		}
	}
	cout << "排序後:";
	for (int i = 0; i < (sizeof(arr) / sizeof(arr[0])); i++) {
		cout << arr[i] << "  ";
	}
}

二維陣列

二維陣列就是在以為陣列上,多加一個維度

定義方式

  1. 資料型別 陣列名 [ 行數 ] [ 列數 ];
  2. 資料型別 陣列名 [ 行數 ] [ 列數 ] = { { 資料1, 資料2 }, {資料3, 資料4}} ;
  3. 資料型別 陣列名 [ 行數 ] [ 列數 ] = {資料1, 資料2, 資料3, 資料4};
  4. 資料型別 陣列名 [ ] [ 列數 ] = {資料1, 資料2, 資料3, 資料4};

以上定義方式,利用第二種更加直觀,提高程式碼的可讀性

#include <iostream>
using namespace std;


int main() {
	// 1. `資料型別 陣列名 [ 行數 ] [ 列數 ];` 
	int arr1[2][3];
	// 2. `資料型別 陣列名[行數][列數] = { { 資料1, 資料2 }, {資料3, 資料4} }; `
	int arr2[2][3] = {
		{1, 2 ,3},
		{4, 5, 6}
	};
	// 二次迴圈,外層迴圈列印行數,內層迴圈列印列數
	for (int i = 0; i < 2; i++) {
		for (int j = 0; j < 3; j++) {
			cout << arr2[i][j] << " ";
		};
		cout << endl;
	};
	// 3. `資料型別 陣列名[行數][列數] = { 資料1, 資料2, 資料3, 資料4 }; `
	int arr3[2][3] = { 1, 2, 3, 4, 5, 6 };
	for (int i = 0; i < 2; i++) {
		for (int j = 0; j < 3; j++) {
			cout << arr2[i][j] << " ";
		};
		cout << endl;
	};
	// 4. `資料型別 陣列名[][列數] = { 資料1, 資料2, 資料3, 資料4 }; `
	int arr3[2][3] = { 1, 2, 3, 4, 5, 6 };
	for (int i = 0; i < 2; i++) {
		for (int j = 0; j < 3; j++) {
			cout << arr2[i][j] << " ";
		};
		cout << endl;
	};
}

陣列名

  • 檢視二維陣列所佔記憶體空間
  • 獲取二維陣列首地址
#include <iostream>
using namespace std;


int main() {
	int arr2[2][3] = {
	{1, 2 ,3},
	{4, 5, 6}
	};
	// 檢視佔用記憶體
	cout << "二維陣列佔用記憶體空間為:" << sizeof(arr2) << endl;
	cout << "二維陣列第一行佔用記憶體為:" << sizeof(arr2[0]) << endl;
	cout << "二維陣列第一個元素佔用的記憶體為:" << sizeof(arr2[0][0]) << endl;
	
	cout << "二位陣列的一行的元素數量為:" << sizeof(arr2[0]) / sizeof(arr2[0][0]) << endl << "二維陣列的行數為:" << sizeof(arr2) / sizeof(arr2[0]) << endl;

	// 檢視二維陣列的首地址
	cout << "二維陣列首地址為:" << (int)arr2 << endl;
	cout << "二維陣列第一行的首地址為:" << (int)arr2[0] << endl;
	cout << "二維陣列第一個元素的首地址為:" << (int)&arr2[0][0];
}

案例

有一個陣列 int arr[3][3] = {{100, 100, 100}, {90, 50, 100}, {60, 70, 80}}

計算該陣列每一行的總和

#include <iostream>
using namespace std;


int main() {
	// 求陣列中每一行內數字的總和
	int arr[3][3] = {
		{100, 100, 100},
		{90, 50, 100},
		{60, 70, 80}
	};

	// 二次迴圈,得到陣列中的每一個值
	for (int i = 0; i < (sizeof(arr) / sizeof(arr[0])); i++) {
		int sum = 0;
		for (int j = 0; j < (sizeof(arr[0]) / sizeof(arr[0][0])); j++) {
			sum += arr[i][j];
		};
		cout << "第" << (i + 1) << "行的和為:" << sum <<endl;
	};

}

函式

概述

作用:將一段經常使用的程式碼進行封裝起來,減少重複程式碼;一個較大的程式,一般分為若干個程式塊,每個模組實現特定的功能

函式的定義

函式的定義一般主要有5個步驟

  1. 返回值型別
  2. 函式名
  3. 引數系列
  4. 函式體語句
  5. return表示式

語法

返回值型別 函式名 (引數列表) 
{
    
    函式體語句
        
    return 表示式
}

實現一個加法的函式,傳入兩個整型數值,計算資料相加的結果,並且返回

#include <iostream>
using namespace std;


// 函式體
int add(int num1, int num2) {
	return num1 + num2;
}

函式的呼叫

功能:使用定義好的函式

語法:函式名(引數)

#include <iostream>
using namespace std;


// 函式體
int add(int num1, int num2) {  // 函式定義裡面的引數沒有實際值,稱為形參(形式引數)
	return num1 + num2;
}

int main() {
	cout << add(1, 2) << endl;  // 在main函式中呼叫add函式,其中,1和2為實參(實際引數),位置要一一對應
}

值傳遞

  • 所謂值傳遞,就是函式呼叫時實參將數值傳入給形參
  • 值傳遞時,如果形參發生改變,不會影響實參
#include <iostream>
using namespace std;


/* 
值傳遞
定義函式,實現兩個數字進行交換函式
如果函式不需要返回值宣告的時候可以寫void
*/
void swap(int num1, int num2) {
	cout << "交換前的數字" << endl << "num1:" << num1 << "\tnum2:" << num2;
	int temp = num1;
	num1 = num2;
	num2 = temp;
	cout << "\n交換後的數字" << endl << "num1:" << num1 << "\tnum2:" << num2;
}

int main() {
	int num1 = 10;
	int num2 = 20;
	cout << "未呼叫前的數字" << endl << "num1:" << num1 << "\tnum2:" << num2 << endl;  // 當我們做值傳遞的時候,函式的形參發生改變,並不會影響形參
	swap(num2, num1);
}

函式的常見樣式

常見的函式樣式有4種

  1. 有參無返
  2. 無參無返
  3. 無參有返
  4. 有參有返
#include <iostream>
#include <string>
using namespace std;


// 1. 有參無返
void test01(string str) {
	cout << str << endl;
}
// 2. 無參無返
void test02() {
	cout << "this is test02" << endl;
}
// 3. 無參有返
int test03() {
	return 100;
}
// 4. 有參有返
int test04(int num1, int num2) {
	return num1 * num2;
}

int main() {
	// 1. 有參無返呼叫
	test01("hello world");
	// 2. 無參無返呼叫
	test02();
	// 3. 有參無返呼叫
	cout << test03() << endl;
	// 4. 有參有返呼叫
	cout << test04(2, 3) << endl;
}

函式的宣告

作用:告訴編譯器函式名稱及如何呼叫函式.函式的實際主體可以單獨定義

  • 函式宣告可以多次,但是函式的定義只能有一次
#include <iostream>
#include <string>
using namespace std;


// 函式宣告:提前告訴編譯器函式的存在
// 函式宣告-->如果沒有該宣告那麼函式將不會呼叫
int max(int num1, int num2);

int main() {
	int a = 10;
	int b = 20;
	cout << max(a, b) << endl;
}

// 比較函式,實現兩個整型數字進行比較,返回較大的數字
int max(int num1, int num2) {
	return num1 > num2 ? num1 : num2;
}

函式的分檔案編寫

作用:讓程式碼結構更加清晰

函式分檔案編寫一般有4個步驟

  1. 建立字尾名為.h的標頭檔案
  2. 建立字尾名為.cpp的原始檔
  3. 在標頭檔案中寫函式的宣告
  4. 在新的原始檔中寫函式的定義
/* 新建的原始檔中 */

#include "標頭.h"
 

// 比較函式,實現兩個整型數字進行比較,返回較大的數字,函式定義
int max(int num1, int num2) {
	return num1 > num2 ? num1 : num2;
}


/* 新建的標頭檔案中(名稱為標頭.h) */

#include <iostream>
using namespace std;

int max(int num1, int num2);


/* 執行檔案中 */

#include "標頭.h"


int main() {
	int a = 10;
	int b = 20;
	cout << max(a, b) << endl;
}

指標

基本概念

作用:可以通過指標間接訪問記憶體

  • 記憶體編號是從0開始記錄的,一般用十六進位制數字表示
  • 可以利用指標變數儲存地址

定義和使用

指標變數定義語法:資料型別 * 變數名

#include <iostream>
using namespace std;


int main() {
	// 定義一個指標
	int a = 10;
	// 指標定義語法:資料型別 * 變數名
	int * p;
	// 讓指標記錄變數a的地址
	p = &a;  // & 取址符號
	cout << "a的地址為:" << &a << endl;
	cout << "指標p的值為:" << p << endl;
	// 使用指標
	// 可以通過解引用的方式來找到指標指向的記憶體
	// 指標前加 * 代表解引用,找到指標指向的記憶體中的資料
	*p = 100;
	cout << "a等於:" << a << "\n*p等於" << *p << endl;
}

指標所佔的記憶體空間

#include <iostream>
using namespace std;


// 在32位作業系統下,指標佔4bit,不管是什麼資料型別
// 在64位作業系統下,指標佔8bit
int main() {
	int a = 10;
	int * p = &a;
	cout << "int *:" << sizeof(int*) << endl;
    cout << "char *:" << sizeof(char*) << endl;
	cout << "p:" << sizeof(p) << endl;
}

空指標和隱指標

空指標:指標變數指向記憶體中編號為0的空間

用途:初始化指標變數

注意:空指標指向的記憶體是不可以被訪問的

野指標:指標變數指向非法的記憶體空間

#include <iostream>
using namespace std;


int main() {
	// 空指標
	// 空指標用於給指標物件初始化
	int* p1 = NULL;
	// 空指標不能被訪問,其被系統佔用

	// 野指標
	// 在程式中一定要避免野指標
	int * p = (int *)0x1100;
}

const修飾指標

const修飾指標有三種情況

  1. const修飾指標 --常量指標const int * p = &a
    • 指標的指向可以修改,但是指向的值不可以修改
  2. const修飾常量 --指標常量int * const p = &a
    • 指標的指向不可以改,指標的值可以改
  3. const即修飾指標 ,又修飾常量
#include <iostream>
using namespace std;


int main() {
	int a = 10;
	int b = 10;

	// 常量指標
	const int* p = &a;
	// 指標指向的值不可以改,指向的位置可以修改
	// * p = 20; 錯誤
	p = &b; // 正確

	// 指標常量
	int* const p1 = &a;
	// 指標指向的值可以修改,指向的位置不可以修改
	*p1 = 20;  // 正確
	// p = &b;  錯誤
}

記憶方法:看const右側緊跟的是指標還是常量,是指標就是常量指標,是常量就是指標常量

指標和陣列

作用:利用指標訪問陣列中的元素

#include <iostream>
using namespace std;


int main() {
	// 指標和陣列
	// 利用指標訪問陣列中的元素

	int arr[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
	cout << "第一個元素為:" << arr[0] << endl;

	int* p = arr;  // arr就是陣列的首地址

	cout << "利用指標來訪問第一個元素:" << *p << endl;

	p++;  // 讓指標偏移4bit
	 
	cout << "利用指標訪問第二個元素:" << *p << endl;

	// 利用指標來訪問陣列,也可以通過p1[索引值來訪問]
	int* p1 = arr;
	for (int i = 0; i < (sizeof(arr) / sizeof(arr[0])); i++) {
		cout << *p1++ << "  ";
	}
    for (int i = 0; i < (sizeof(arr) / sizeof(arr[0])); i++) {
		cout << p1[i] << "  ";
	}

}

指標和函式

作用:利用指標做函式的引數,可以修改實參的值

#include <iostream>
using namespace std;


void swap(int* p1, int* p2) {
	int temp = *p1;
	*p1 = *p2;
	*p2 = temp;
}

int main() {
	// 函式和指標
	// 地址傳遞
	int a = 10;
	int b = 30;
	cout << "a:" << a << " b:" << b << endl;
	swap(&a, &b);
	cout << "after a:" << a << " b:" << b << endl;  // 地址中的記憶體發生改變
}

指標、陣列、函式

封裝一個函式,利用氣泡排序,實現對整型陣列的升序排序

例如,陣列:int arr[] = { 4, 3, 6, 9, 1, 2, 10, 8, 7, 5 };

#include <iostream>
using namespace std;


// 氣泡排序函式
void sort(int * arr, int length) {  // 引數為陣列的記憶體地址
	for (int i = 0; i < length - 1; i++) {
		for (int j = 0; j < length - i - 1; j++) {
			if (arr[j] > arr[j + 1]) {
				int temp = arr[j];
				arr[j] = arr[j+1];
				arr[j+1] = temp;
			}
		}
	}
}
// 列印陣列
void print(int* arr, int length) {
	for (int i = 0; i < length; i++) {
		cout << arr[i] << " ";
	}
}

int main() {
	int arr[] = { 4, 3, 6, 9, 1, 2, 10, 8, 7, 5 };
	int length = sizeof(arr) / sizeof(arr[0]);
	sort(arr, length);
	print(arr, length);
}

結構體

基本概念

結構體屬於使用者自定義的資料型別,允許使用者儲存不同的資料型別

定義和使用

語法:struct 結構體名 { 結構體成員列表 }

通過結構體建立變數的方式有三種

  • struct 結構體名 變數名
  • struct 結構體名 變數名 = { 成員值1, 成員值2, ... }
  • 定義結構體是順便建立變數
#include <iostream>
#include <string>
using namespace std;


// 建立學生的資料型別:包括(姓名、年齡、分數)
// 自定義資料型別,一些型別集合組成的一個資料型別
struct Student  
{
	// 成員列表
	string name;  // name
	int age;  // age
	int score;  // score
}s3;  // 順便建立結構體變數

int main() {
	// 通過學生型別建立具體學生
	// struct Student s1
	struct Student s1;  // struct關鍵字可以省略,但是定義的時候不能省略
	// 給s1屬性賦值,通過.訪問結構變數中的屬性
	s1.name = "張三";
	s1.age = 18;
	s1.score = 90;
	cout << "name:" << s1.name << " age:" << s1.age << " score:" << s1.score << endl;

	// struct Stufent s2 = { ... }
	struct Student s2 = { "李四", 18, 80 };
	cout << "name:" << s2.name << " age:" << s2.age << " score:" << s2.score << endl;

	// 在定義接哦古體是順便建立結構體變數
	s3.name = "王五";
	s3.age = 18;
	s3.score = 85;
	cout << "name:" << s3.name << " age:" << s3.age << " score:" << s3.score << endl;
}

結構體陣列

作用:將自定義的結構體放入到陣列中方便維護

語法:struct 結構體名 陣列名 [ 元素個數 ] = { {}, {}, ...{} }

#include <iostream>
#include <string>
using namespace std;


// 結構體陣列
// 定義結構體陣列
struct Student
{
	string name;
	int age;
	int score;
};

int main() {

	// 建立結構體陣列
	struct Student stuArray[3] = {	// 給結構體陣列賦值
		{"zhangsan", 18, 100},
		{"lisi", 19, 99},
		{"wangwu", 20, 85}
	};

	// 修改值
	stuArray[2].name = "lihua";
	stuArray[2].age = 19;
	stuArray[2].score = 89;

	// 遍歷陣列
	for (int i = 0; i < 3; i++) {
		cout << "name:" << stuArray[i].name << "  age:" << stuArray[i].age << "  score:" << stuArray[i].score << endl;
	};
}

結構體指標

作用:通過指標訪問結構體中的成員

  • 利用操作符 ->可以通過結構體指標訪問結構體屬性
#include <iostream>
#include <string>
using namespace std;


// 結構體指標

// 定義學生的結構體
struct Student
{
	string name;
	int age;
	int score;
};

int main() {

	// 建立學生結構體變數

	struct Student s = { "zhangsan", 18, 99 };

	// 通過指標指向結構體變數
	struct Student* p = &s;

	// 通過指標指向訪問結構體變數中的資料
	cout << "name:" << p->name << "  age:" << p->age << "  score:" << p->score << endl;
}

結構體巢狀結構體

作用:結構體中的成員可以是另一個結構體

例如:每個老師輔導一個學生,一個老師的結構體,記錄一個學生的結構體

#include <iostream>
#include <string>
using namespace std;


// 結構體指標

// 定義學生的結構體
struct Student
{
	string name;
	int age;
	int score;
};

// 定義老師結構體
struct Treacher
{
	int id;
	string name;
	int age;
	struct Student stu;  // 輔導學生
};

int main() {

	// 結構巢狀結構體
	// 建立老師物件
	struct Treacher t;
	t.id = 100000;
	t.name = "老王";
	t.age = 58;
	t.stu.name = "小王";
	t.stu.age = 16;
	t.stu.score = 60;

	cout << "tea_name:" << t.name << "  tea_id:" << t.id << "  tea_age:" << t.age << "\nstu_name:" << t.stu.name << "  stu_age:" << t.stu.age << "  stu_score:" << t.stu.score << endl;
}

結構體做函式引數

作用:將結構體作為引數向函式中傳遞

傳遞的方式有兩種

  • 值傳遞
  • 地址傳遞
#include <iostream>
#include <string>
using namespace std;



// 定義學生的結構體
struct Student
{
	string name;
	int age;
	int score;
};

// 列印學生資訊的函式,值傳遞
void printStuInfo(Student stu) {
	stu.age = 100;
	cout << "name:" << stu.name << "  age:" << stu.age << "  score:" << stu.score << endl;
};

// 地址傳遞:形參修改會引起實參的改變
void printStudentInfo2(Student* p) {
	cout << "name:" << p->name << "  age:" << p->age << "  score:" << p->score << endl;
};


int main() {

	// 結構體做函式的引數
	// 將學生傳入到一個引數中,列印學生身上的所有資訊

	// 建立結構體變數
	struct Student stu;
	stu.name = "zhangsan";
	stu.age = 20;
	stu.score = 85;
	cout << "值傳遞" << endl;
	printStuInfo(stu);
	cout << "地址傳遞" << endl;
	printStudentInfo2(&stu);
}

結構體中const使用場景

作用:用const來防止五操作

#include <iostream>
#include <string>
using namespace std;



// 定義學生的結構體
struct Student
{
	string name;
	int age;
	int score;
};

// 地址傳遞,節省空間
void printStudentInfo2(const Student* p) {  // 加入const之後,一旦有修改的操作就會報錯,可以防止我們的誤操作
	cout << "name:" << p->name << "  age:" << p->age << "  score:" << p->score << endl;
};


int main() {

	// const使用場景

	// 建立結構體變數
	struct Student stu;
	stu.name = "zhangsan";
	stu.age = 20;
	stu.score = 85;
	printStudentInfo2(&stu);
}

結構體案例

案例一

#include <iostream>
#include <string>
#include <ctime>
using namespace std;



// 定義學生的結構體
struct Student
{
	string name;
	int score;
};

// 老師結構定義
struct Teacher
{
	string name;
	Student stuArray[5];
};

// 給老師和學生賦值的函式
void allocateSpace(Teacher tArray[], int len) {
	// 給老師賦值
	string name = "abcde";
	for (int i = 0; i < len; i++) {
		tArray[i].name = "Teacher_";
		tArray[i].name += name[i];  // 字串的取值
		
		// 給每名學生賦值
		for (int j = 0; j < 5; j++) {
			tArray[i].stuArray[j].name = "Student_";
			tArray[i].stuArray[j].name += name[j];

			int random = rand() % 61 + 40;  // 40-99
			tArray[i].stuArray[j].score = random;
		}
	};
};

// 列印學生和老師的資訊
void printInfo(Teacher* tArray, int len) {
	for (int i = 0; i < len; i++) {
		cout << "teacher_name:" << tArray[i].name << endl;
		for (int j = 0; j < 5; j++) {
			cout << "stu_name:" << tArray[i].stuArray[j].name << "  stu_score:" << tArray[i].stuArray[j].score << endl;
		};
		cout << "--------------------------------------------------------------------------------" << endl;
	};
}

int main() {
	// 隨機數種子
	srand((unsigned int)time(NULL));

	// 三名老師陣列
	Teacher tArray[3]; 
	
	// 通過函式給老師的資訊賦值,並給老師帶的學生資訊賦值
	int len = sizeof(tArray) / sizeof(tArray[0]);
	allocateSpace(tArray, len);
	printInfo(tArray, len);
}

案例二

有五個學生,通過氣泡排序的方法,將陣列中的學生按照年齡進行升序排序,最終列印排序後的結果

{ {"stu1", 23}, {"stu2", 22}, {"stu3", 20}, {"stu4", 21}, {"stu5", 19} }

#include <iostream>
#include <string>
using namespace std;



// 定義學生的結構體
struct Student
{
	string name;
	int age;
};

// 排序
void sort(Student* stuArray, int len) {
	for (int i = 0; i < len - 1; i++) {
		for (int j = 0; j < len - i - 1; j++) {
			if (stuArray[j].age > stuArray[j + 1].age) {
				struct Student temp = stuArray[j];
				stuArray[j] = stuArray[j + 1];
				stuArray[j + 1] = temp;
			};
		};
	};
};

// 輸出
void printInfo(const Student * stuArray, int len) {
	for (int i = 0; i < len; i++) {
		cout << "name:" << stuArray[i].name << "  age:" << stuArray[i].age << endl;
	};
};


int main() {
	// 建立陣列存放五名學生
	Student stuArray[] = {
		{"stu1", 23},
		{"stu2", 22},
		{"stu3", 20},
		{"stu4", 21},
		{"stu5", 19}
	};
	int len = sizeof(stuArray) / sizeof(stuArray[0]);
	sort(stuArray, len);
	printInfo(stuArray, len);
};