C++基礎知識筆記


一、初識C++

1.0 ---------------

1.1 注釋

  1. 單行注釋// 描述信息
  2. 多行注釋/* 描述信息 */

1.2 變量

作用:給一段指定的內存空間起名,方便操作這段內存

語法:數據類型 變量名 = 初始值;

1.3 常量

作用:用於記錄程序中不可更改的數據

語法:

1. #define 宏常量: `#define 常量名 常量值` -- 通常定義在程序的最上方
2. const修飾的變量 `const 數據類型 常量名 = 常量值` -- 修飾該變量為常量,不可修改

1.4 關鍵字

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

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

C++關鍵字如下:

asm do if return typedef
auto double inline short typeid
bool dynamic_cast int signed typename
break else long sizeof union
case enum mutable static unsigned
catch explicit namespace static_cast using
char export new struct virtual
class extern operator switch void
const false private template volatile
const_cast float protected this wchar_t
continue for public throw while
default friend register true
delete goto reinterpret_cast try

提示:在給變量或者常量起名稱時候,不要用C++得關鍵字,否則會產生歧義。

1.5 標識符命名規則

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

  • 標識符不能是關鍵字
  • 標識符只能由字母、數字、下划線組成
  • 第一個字符必須為字母或下划線
  • 標識符中字母區分大小寫

建議:給標識符命名時,爭取做到見名知意的效果,方便自己和他人的閱讀


二、數據類型

C++規定在創建一個變量或者常量時,必須要指定出相應的數據類型,否則無法給變量分配內存

2.0 ---------------

2.1 sizeof關鍵字

作用: 統計數據類型所占內存大小

語法: sizeof( 數據類型 / 變量)

2.2 整型

作用:整型變量表示的是整數類型的數據

C++中能夠表示整型的類型有以下幾種方式,區別在於所占內存空間不同

數據類型 占用空間 取值范圍
short(短整型) 2字節 (-2^15 ~ 2^15-1)
int(整型) 4字節 (-2^31 ~ 2^31-1)
long(長整形) Windows為4字節,Linux為4字節(32位),8字節(64位) (-2^31 ~ 2^31-1)
long long(長長整形) 8字節 (-2^63 ~ 2^63-1)

平時程序中沒有特殊說明一般用int就夠了

2.3 實型(浮點型)

作用:表示小數

浮點型變量分為兩種:

  1. 單精度float -- 創建時在初始化數字后加上f能減少一次轉換
  2. 雙精度double -- 小數默認是double
  3. 科學計數法 -- 3e-2代表3乘10的-2次方

兩者的區別在於表示的有效數字范圍不同。 正常顯示都是6位有效數字

數據類型 占用空間 有效數字范圍
float 4字節 7位有效數字
double 8字節 15~16位有效數字

2.4 字符型

作用: 字符型變量用於顯示單個字符

語法:char ch = 'a';

注意1:在顯示字符型變量時,用單引號將字符括起來,不要用雙引號

注意2:單引號內只能有一個字符,不可以是字符串

  • C和C++中字符型變量只占用 1個字節 。
  • 字符型變量並不是把字符本身放到內存中存儲,而是將對應的ASCII編碼放入到存儲單元

使用 int(ch) 查看 ch 對應的字符 a 的 ASCII碼

2.5 轉義字符

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

現階段我們常用的轉義字符有: \n \\ \t

\t 水平制表符,占4個位置(包括其前邊的字符,可疊加)

轉義字符 含義 ASCII碼值(十進制)
\a 警報 007
\b 退格(BS) ,將當前位置移到前一列 008
\f 換頁(FF),將當前位置移到下頁開頭 012
\n 換行(LF) ,將當前位置移到下一行開頭 010
\r 回車(CR) ,將當前位置移到本行開頭 013
\t 水平制表(HT) (跳到下一個TAB位置) 009
\v 垂直制表(VT) 011
\\ 代表一個反斜線字符 \ 092
' 代表一個單引號(撇號)字符 039
" 代表一個雙引號字符 034
? 代表一個問號 063
\0 數字0 000
\ddd 8進制轉義字符,d范圍0~7 3位8進制
\xhh 16進制轉義字符,h范圍09,af,A~F 3位16進制

2.6 字符串型

作用:用於表示一串字符

兩種風格

  1. C風格字符串char 變量名[] = "字符串值"

注意:字符串名字后加[]; 字符串要用雙引號括起來

  1. C++風格字符串string 變量名 = "字符串值"

注意:C++風格字符串,需要加入頭文件 #include <string>

2.7 布爾類型 bool

作用: 布爾數據類型代表真或假的值

bool類型只有兩個值:true(本質是1); false(本質是0)

bool類型占1個字節大小

2.8 數據的輸入

作用:用於從鍵盤獲取數據

關鍵字: cin

語法: cin >> 變量

在vscode輸出面板中無法完成輸入操作,需要運行代碼后去終端執行 cmd /c "xxx.exe" 后輸入


三 運算符

3.0 ---------------

3.1 算術運算符

作用:用於處理四則運算

算術運算符包括以下符號:

運算符 術語 示例 結果
+ 正號 +3 3
- 負號 -3 -3
+ 10 + 5 15
- 10 - 5 5
* 10 * 5 50
/ 10 / 5 2
% 取模(取余) 10 % 3 1
++ 前置遞增 a=2; b=++a; a=3; b=3;
++ 后置遞增 a=2; b=a++; a=3; b=2;
-- 前置遞減 a=2; b=--a; a=1; b=1;
-- 后置遞減 a=2; b=a--; a=1; b=2;

兩個整數相除結果依然是整數

兩個小數不可以進行取模運算

前置計算是先對變量進行計算,再計算表達式,后置遞增相反

#include<iostream>
using namespace std;

int main(){
    int a1 = 10;
    // 前置運算符,先對變量計算,再計算公式  110
    int b = ++a1 * 10;
    cout << a1 << endl;
    cout << b << endl;

    // 后置運算符,先計算公式,再對變量計算  100
    int a2 = 10;
    int c = a2++ *10;
    cout << a2 << endl;
    cout << c << endl;

    return 0;
}

3.2 賦值運算符

作用: 用於將表達式的值賦給變量

賦值運算符包括以下幾個符號:

運算符 術語 示例 結果
= 賦值 a=2; b=3; a=2; b=3;
+= 加等於 a=0; a+=2; a=2;
-= 減等於 a=5; a-=3; a=2;
*= 乘等於 a=2; a*=2; a=4;
/= 除等於 a=4; a/=2; a=2;
%= 模等於 a=3; a%2; a=1;

a += 2 可以理解為 a = a+2 的縮寫

3.3 比較運算符

作用: 用於表達式的比較,並返回一個真值或假值

比較運算符有以下符號:

運算符 術語 示例 結果
== 相等於 4 == 3 0
!= 不等於 4 != 3 1
< 小於 4 < 3 0
> 大於 4 > 3 1
<= 小於等於 4 <= 3 0
>= 大於等於 4 >= 1 1

真返回1,假返回0

3.4 邏輯運算符

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

邏輯運算符有以下符號:

運算符 術語 示例 結果
! !a 如果a為假,則!a為真; 如果a為真,則!a為假。
&& a && b 如果a和b都為真,則結果為真,否則為假。
|| a || b 如果a和b有一個為真,則結果為真,二者都為假時,結果為假。

四 程序流程結構

C/C++支持最基本的三種程序運行結構:順序結構、選擇結構、循環結構

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

4.0 ---------------

4.1 選擇結構

4.1.1 if語句

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

if語句的三種形式

  1. 單行格式if語句:if(條件){ 條件滿足執行的語句 }
  2. 多行格式if語句:if(條件){ 條件滿足執行的語句 }else{ 條件不滿足執行的語句 }
  3. 多條件的if語句:if(條件1){ 條件1滿足執行的語句 }else if(條件2){條件2滿足執行的語句}... else{ 都不滿足執行的語句}

4.1.2 三目運算符

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

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

解釋:

如果表達式1的值為真,執行表達式2,並返回表達式2的結果;

如果表達式1的值為假,執行表達式3,並返回表達式3的結果。

示例:

int main() {

	int a = 10;
	int b = 20;
	int c = 0;

	c = a > b ? a : b;
	cout << "c = " << c << endl;

	//C++中三目運算符返回的是變量,可以繼續賦值

	(a > b ? a : b) = 100;

	cout << "a = " << a << endl;
	cout << "b = " << b << endl;
	cout << "c = " << c << endl;

	system("pause");

	return 0;
}

總結:和if語句比較,三目運算符優點是短小整潔,缺點是如果用嵌套,結構不清晰

4.1.3 switch語句

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

語法:

switch(表達式)

{

	case 結果1:執行語句;break;

	case 結果2:執行語句;break;

	...

	default:執行語句;break;

}

注意1:switch語句中表達式類型只能是整型或者字符型

注意2:case里如果沒有break,那么程序會一直向下執行

總結:與if語句比,對於多條件判斷時,switch的結構清晰,執行效率高,缺點是switch不可以判斷區間

4.2 循環結構

4.2.1 while循環語句

作用: 滿足循環條件,執行循環語句

語法: while(循環條件){ 循環語句 }

while循環練習案例:猜數字

案例描述: 系統隨機生成一個1到100之間的數字,玩家進行猜測,如果猜錯,提示玩家數字過大或過小,如果猜對恭喜玩家勝利,並且退出游戲。

// 系統隨機生成1-100的數字,猜測對了輸出,錯了說明大還是小后繼續猜測

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

int main(){

    // 生成種子 記住就行
    srand((unsigned int)time(NULL));
    // 程序不認識time 需要添加頭文件ctime

    // 生成一個1-100之間的隨機數  rand()%100是0-99
    int a = rand()%100 + 1;
    // 如果只是這么生成的是偽隨機數,即第一次生成后之后的結果都一樣,因此要添加種子,利用當前系統時間生成隨機數

    int num = 0;

    cout << "請輸入您猜測的數字" << endl;
    
    while(1){
        cin >> num;
        if(num > a){
            cout << " 您猜測的數字過大,請重新猜測" << endl;
        }
        else if(num < a){
            cout << " 您猜測的數字過小,請重新猜測" << endl;
        }
        else{
            cout << "恭喜您獲得勝利" << endl;
            // 注意break,不然會一直循環下去
            break; 
        }
        cout << "請輸入您猜測的數字" << endl;
        
    }

    return 0;
}

4.2.2 do...while循環語句

作用: 滿足循環條件,執行循環語句

語法: do{ 循環語句 } while(循環條件);

總結:與while循環區別在於,do...while先執行一次循環語句,再判斷循環條件

4.2.3 for 循環語句

作用: 滿足循環條件,執行循環語句

語法: for(起始表達式;條件表達式;末尾循環體) { 循環語句; }

注意:for循環中的表達式,要用分號進行分隔

總結:while , do...while, for都是開發中常用的循環語句,for循環結構比較清晰,比較常用

4.3 跳轉語句

4.3.1 break語句

作用: 用於跳出選擇結構或者循環結構

break使用的時機:

  • 出現在switch條件語句中,作用是終止case並跳出switch
  • 出現在循環語句中,作用是跳出當前的循環語句
  • 出現在嵌套循環中,跳出最近的內層循環語句

4.3.2 continue語句

作用:循環語句中,跳過本次循環中余下尚未執行的語句,繼續執行下一次循環

注意:continue並沒有使整個循環終止,而break會跳出循環

4.3.3 goto語句

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

語法: goto 標記;

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

注意:在程序中不建議使用goto語句,以免造成程序流程混亂


五 數組

5.0 ---------------

5.1 概述

所謂數組,就是一個集合,里面存放了相同類型的數據元素

特點1: 數組中的每個數據元素都是相同的數據類型

特點2: 數組是由 連續的內存 位置組成的

5.2 一維數組

5.2.1 一維數組定義方式

一維數組定義的三種方式:

  1. 數據類型 數組名[ 數組長度 ];
  2. 數據類型 數組名[ 數組長度 ] = { 值1,值2 ...};
  3. 數據類型 數組名[ ] = { 值1,值2 ...};

總結1:數組名的命名規范與變量名命名規范一致,不要和變量重名

總結2:數組中下標是從0開始索引

5.2.2 一維數組數組名

一維數組名稱的用途

  1. 可以統計整個數組在內存中的長度
  2. 可以獲取數組在內存中的首地址

注意:數組名是常量,不可以賦值

總結1:直接打印數組名,可以查看數組所占內存的首地址;查看字符所占內存地址,在字符前加 &

總結2:對數組名進行sizeof,可以獲取整個數組占內存空間的大小

5.3 二維數組

二維數組就是在一維數組上,多加一個維度。

5.3.1 二維數組定義方式

二維數組定義的四種方式:

  1. 數據類型 數組名[ 行數 ][ 列數 ];
  2. 數據類型 數組名[ 行數 ][ 列數 ] = { {數據1,數據2 } ,{數據3,數據4 } };
  3. 數據類型 數組名[ 行數 ][ 列數 ] = { 數據1,數據2,數據3,數據4};
  4. 數據類型 數組名[ ][ 列數 ] = { 數據1,數據2,數據3,數據4};

建議:以上4種定義方式,利用第二種更加直觀,提高代碼的可讀性

總結:在定義二維數組時,如果初始化了數據,可以省略行數

5.3.2 二維數組數組名

  • 查看二維數組所占內存空間
  • 獲取二維數組首地址

總結1:二維數組名就是這個數組的首地址

總結2:對二維數組名進行sizeof時,可以獲取整個二維數組占用的內存空間大小


六 函數

6.0 ---------------

6.1 概述

作用: 將一段經常使用的代碼封裝起來,減少重復代碼

一個較大的程序,一般分為若干個程序塊,每個模塊實現特定的功能。

6.2 函數的定義

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

1、返回值類型

2、函數名

3、參數表列

4、函數體語句

5、return 表達式

語法:

返回值類型 函數名 (參數列表)
{

       函數體語句

       return表達式

}
  • 返回值類型 :一個函數可以返回一個值。如果函數不需要返回值,聲明的時候可以寫 void
  • 函數名:給函數起個名稱
  • 參數列表:使用該函數時,傳入的數據
  • 函數體語句:花括號內的代碼,函數內需要執行的語句
  • return表達式: 和返回值類型掛鈎,函數執行完后,返回相應的數據

示例: 定義一個加法函數,實現兩個數相加

//函數定義
int add(int num1, int num2)
{
	int sum = num1 + num2;
	return sum;
}

6.3 函數的調用

功能: 使用定義好的函數

語法: 函數名(參數)

示例:

//函數定義
int add(int num1, int num2) //定義中的num1,num2稱為形式參數,簡稱形參
{
	int sum = num1 + num2;
	return sum;
}

int main() {

	int a = 10;
	int b = 10;
	//調用add函數
	int sum = add(a, b);//調用時的a,b稱為實際參數,簡稱實參
	cout << "sum = " << sum << endl;

	a = 100;
	b = 100;

	sum = add(a, b);
	cout << "sum = " << sum << endl;

	system("pause");

	return 0;
}

總結:函數定義里小括號內稱為形參,函數調用時傳入的參數稱為實參

在實際調用中,a,b首先傳遞給num1,num2(實參傳遞給形參),再經過計算得到sum,返還的結果賦值給c

6.4 值傳遞

  • 所謂值傳遞,就是函數調用時實參將數值傳入給形參
  • 值傳遞時,如果形參發生,並不會影響實參

總結: 值傳遞時,形參是修飾不了實參的

6.5 函數的常見樣式

常見的函數樣式有4種

  1. 無參無返
  2. 有參無返
  3. 無參有返
  4. 有參有返

示例:

//函數常見樣式
//1、 無參無返
void test01()
{
	//void a = 10; //無類型不可以創建變量,原因無法分配內存
	cout << "this is test01" << endl;
	//test01(); 函數調用
}

//2、 有參無返
void test02(int a)
{
	cout << "this is test02" << endl;
	cout << "a = " << a << endl;
}

//3、無參有返
int test03()
{
	cout << "this is test03 " << endl;
	return 10;
}

//4、有參有返
int test04(int a, int b)
{
	cout << "this is test04 " << endl;
	int sum = a + b;
	return sum;
}

6.6 函數的聲明

作用: 告訴編譯器函數名稱及如何調用函數。函數的實際主體可以單獨定義。

  • 函數的聲明可以多次,但是函數的定義只能有一次
  • 當函數寫在main函數后的時候,一定要事先聲明

七 指針

7.0 ---------------

7.1 指針的基本概念

指針的作用: 可以通過指針間接訪問內存

  • 內存編號是從0開始記錄的,一般用十六進制數字表示

  • 可以利用指針變量保存地址

7.2 指針變量的定義和使用

指針變量定義語法: 數據類型 * 變量名;

示例:

int main() {

	//1、指針的定義
	int a = 10; //定義整型變量a
	
	//指針定義語法: 數據類型 * 變量名 ;
	int * p;

	//指針變量賦值
	p = &a; //指針指向變量a的地址
	cout << &a << endl; //打印數據a的地址
	cout << p << endl;  //打印指針變量p

	//2、指針的使用
	//通過*操作指針變量指向的內存
	cout << "*p = " << *p << endl;

	system("pause");

	return 0;
}

指針變量和普通變量的區別

  • 普通變量存放的是數據,指針變量存放的是地址
  • 指針變量可以通過" * "操作符,操作指針變量指向的內存空間,這個過程稱為解引用

總結1: 我們可以通過 & 符號 獲取變量的地址

總結2:利用指針可以記錄地址

總結3:對指針變量解引用,可以操作指針指向的內存

7.3 指針所占內存空間

總結:所有指針類型在32位操作系統下是4個字節,64位操作系統下8個字節

7.4 空指針和野指針

空指針:指針變量指向內存中編號為0的空間

用途:初始化指針變量

注意:空指針指向的內存是不可以訪問的

示例1:空指針

int main() {

	//指針變量p指向內存地址編號為0的空間
	int * p = NULL;

	//訪問空指針報錯 
	//內存編號0 ~255為系統占用內存,不允許用戶訪問
	cout << *p << endl;

	system("pause");

	return 0;
}

野指針:指針變量指向非法的內存空間

示例2:野指針

int main() {

	//指針變量p指向內存地址編號為0x1100的空間
	int * p = (int *)0x1100;

	//訪問野指針報錯 
	cout << *p << endl;

	system("pause");

	return 0;
}

總結:空指針和野指針都不是我們申請的空間,因此不要訪問。

7.5 const修飾指針

const修飾指針有三種情況

  1. const修飾指針 --- 常量指針
  2. const修飾常量 --- 指針常量
  3. const即修飾指針,又修飾常量

示例:

# include <iostream>
using namespace std;

int main(){

    int a = 10;
    int b = 20;

    // 1.const 修飾指針  常量指針,指針指向可以改,值不可以改  
    // 因為*m代表的是值,int * m  (m)代表的是指針

    const int * m = &a;
    // *m = 30;  會報錯
    m = &b;
    cout << *m << endl;

    cout << "指針所占用的內存是: " << sizeof(int *) << endl;
    

    // 2、const修飾常量  指針常量,指針指向不可以改,值可以改

    int * const n = &a;

    // n = &b; 會報錯
    *n = 100;
    cout << "a的值為: " << a << endl;

    // 3、const即修飾指針,又修飾常量   啥都不能改
    const int * const q = &a;
    // q = &b;  報錯
    // *q = 300; 報錯

    return 0;
}

技巧:看const右側緊跟着的是指針還是常量, 是指針就是常量指針,是常量就是指針常量

7.6 指針和數組

作用: 利用指針訪問數組中元素

示例:

# include <iostream>

using namespace std;

int main(){

    int arr[] = {1,2,3,4,5};

    int * p = arr; // 相當於指向數組的首地址
    // 如果想訪問第二個地址,有兩個方法:1、arr[1]  2、指針偏移P++(因為指針類型也是int)

    for(int i=0; i<5; i++){
        cout << *p << endl;  // *用於解地址,得到對應的變量值
        p++;
    }

    return 0;
}

7.7 指針和函數

作用: 利用指針作函數參數,可以修改實參的值

# include <iostream>
using namespace std;

// 值傳遞 交換函數
void swap01(int a, int b){
    int temp = a;

    a = b;
    b = temp;
}

// 地址傳遞  交換函數
void swap02(int * a, int * b){

    int temp = *a;

    *a = *b;
    *b = temp;
}


int main(){

    int num1 = 10;
    int num2 = 20;

    // 調用值傳遞,num1和num2為實參,實參的值沒變
    swap01(num1, num2);
    cout << "num1的值為: " << num1 << endl;  //10
    cout << "num2的值為: " << num2 << endl;  //20

    // 調用地址傳遞,實參的值變了
    swap02(&num1, &num2);
    cout << "num1的值為: " << num1 << endl;  //20
    cout << "num2的值為: " << num2 << endl;  //10

    return 0;
}

總結:如果不想修改實參,就用值傳遞,如果想修改實參,就用地址傳遞

數組傳入函數中,只能是地址傳遞,不可以是函數傳遞!

八 結構體

8.0 ---------------

8.1 結構體基本概念

結構體屬於用戶自定義的數據類型,允許用戶存儲不同的數據類型

8.2 結構體定義和使用

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

通過結構體創建變量的方式有三種:

  • struct 結構體名 變量名
  • struct 結構體名 變量名 = { 成員1值 , 成員2值...}
  • 定義結構體時順便創建變量

總結1:定義結構體時的關鍵字是struct,不可省略

總結2:創建結構體變量時,關鍵字struct可以省略

總結3:結構體變量利用操作符 ''.'' 訪問成員

8.3 結構體數組

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

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

示例:

//結構體定義
struct student
{
	//成員列表
	string name;  //姓名
	int age;      //年齡
	int score;    //分數
}

int main() {
	
	//結構體數組
	struct student arr[3]=
	{
		{"張三",18,80 },
		{"李四",19,60 },
		{"王五",20,70 }
	};

	for (int i = 0; i < 3; i++)
	{
		cout << "姓名:" << arr[i].name << " 年齡:" << arr[i].age << " 分數:" << arr[i].score << endl;
	}

	system("pause");

	return 0;
}

8.4 結構體指針

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

  • 利用操作符 -> 可以通過結構體指針訪問結構體屬性

示例:

//結構體定義
struct student
{
	//成員列表
	string name;  //姓名
	int age;      //年齡
	int score;    //分數
};


int main() {
	
	struct student stu = { "張三",18,100, };
	
	struct student * p = &stu;
	
	p->score = 80; //指針通過 -> 操作符可以訪問成員

	cout << "姓名:" << p->name << " 年齡:" << p->age << " 分數:" << p->score << endl;
	
	system("pause");

	return 0;
}

總結:結構體指針可以通過 -> 操作符 來訪問結構體中的成員

8.5 結構體嵌套結構體

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

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

示例:

//學生結構體定義
struct student
{
	//成員列表
	string name;  //姓名
	int age;      //年齡
	int score;    //分數
};

//教師結構體定義
struct teacher
{
    //成員列表
	int id; //職工編號
	string name;  //教師姓名
	int age;   //教師年齡
	struct student stu; //子結構體 學生
};

8.6 結構體做函數參數

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

傳遞方式有兩種:

  • 值傳遞
  • 地址傳遞

示例:

//學生結構體定義
struct student
{
	//成員列表
	string name;  //姓名
	int age;      //年齡
	int score;    //分數
};

//值傳遞
void printStudent(student stu )
{
	stu.age = 28;
	cout << "子函數中 姓名:" << stu.name << " 年齡: " << stu.age  << " 分數:" << stu.score << endl;
}

//地址傳遞
void printStudent2(student *stu)
{
	stu->age = 28;
	cout << "子函數中 姓名:" << stu->name << " 年齡: " << stu->age  << " 分數:" << stu->score << endl;
}

總結:如果不想修改主函數中的數據,用值傳遞,反之用地址傳遞

8.7 結構體中 const使用場景

作用: 地址傳遞能大大節約內存,用const來防止地址傳遞誤操作

示例:

//學生結構體定義
struct student
{
	//成員列表
	string name;  //姓名
	int age;      //年齡
	int score;    //分數
};

//const使用場景
void printStudent(const student *stu) //加const防止函數體中的誤操作
{
	//stu->age = 100; //操作失敗,因為加了const修飾
	cout << "姓名:" << stu->name << " 年齡:" << stu->age << " 分數:" << stu->score << endl;

}

int main() {

	student stu = { "張三",18,100 };

	printStudent(&stu);

	system("pause");

	return 0;
}

8.8 結構體案例

8.8.1 案例1

案例描述:

學校正在做畢設項目,每名老師帶領5個學生,總共有3名老師,需求如下

設計學生和老師的結構體,其中在老師的結構體中,有老師姓名和一個存放5名學生的數組作為成員

學生的成員有姓名、考試分數,創建數組存放3名老師,通過函數給每個老師及所帶的學生賦值

最終打印出老師數據以及老師所帶的學生數據。

示例:

// 創建學生、老師結構體

//實例15個學生,放入3個數組中
//實例3個老師,放入一個數組中
//通過函數賦值
//通過函數打印

# include <iostream>
# include<string>
// # include<time.h>  這個和下邊的都可以
# include<ctime>

using namespace std;

struct Stu
{
    string name;
    int score;
};

struct Tea
{
    string name;
    Stu student[5];
};

// 定義函數給老師學生賦值
void Fuzhi(Tea * p, int len)
{
    for (int i=0; i<len; i++)
    {
        string temp = "ABCDE";
        // 給結構體指針賦值 不用* 用->
        p->name = "teacher";
        p->name += temp[i];
        

        // 給學生賦值
        for (int j=0; j<5; j++)
        {
            p->student[j].name = "student";
            p->student[j].name += temp[j];
            // srand((unsigned int)time(NULL));  隨機數種子要在main函數中加
            // int randScore = rand() % 101;  // 隨機生成0-100之間的數,如果是60-100
            int randScore = rand() % 41 + 60;

            p->student[j].score = randScore;
        }

        p++;
    }

}

void Print(Tea tArray[])
{
    for (int i=0; i<3; i++)
    {
        cout << "老師的名字是" << tArray[i].name << "他帶的學生信息如下:" << endl ;
        for (int j=0; j<5; j++)
        {
            cout << "\t" << "姓名:" << tArray[i].student[j].name << "\t" << "成績:" << tArray[i].student[j].score << "\t" << endl;
            
        }

    }    
}

int main(){

    Tea teacher[3];

    srand((unsigned int)time(NULL));

    // 通過函數賦值
    Fuzhi(teacher, 3);

    // 打印
    Print(teacher);



    return 0;
}

8.8.2 案例2

案例描述:

設計一個英雄的結構體,包括成員姓名,年齡,性別;創建結構體數組,數組中存放5名英雄。

通過冒泡排序的算法,將數組中的英雄按照年齡進行升序排序,最終打印排序后的結果。

五名英雄信息如下:

		{"劉備",23,"男"},
		{"關羽",22,"男"},
		{"張飛",20,"男"},
		{"趙雲",21,"男"},
		{"貂蟬",19,"女"},
/*
    1、創建結構體 
    2、寫冒泡排序函數
    3、將年齡作為參數傳遞(放到數組中)
*/

# include<iostream>
# include<string>

using namespace std;

struct hero
{
    string name;
    int age;
    string sex;
};

void Sort(hero ageArr[], int len)
// 也可以是
// void Sort(hero *ageArr, int len)
{
// 注意:數組內的是.,此時不是指針,而是結構體
// 如果寫ageArr[i]->age肯定會出錯!!
    for(int i=0; i<len; i++){
        for(int j=0; j<len-1-i; j++){
            if(ageArr[j].age > ageArr[j+1].age){
                hero temp = ageArr[j];
                ageArr[j] = ageArr[j+1];
                ageArr[j+1] = temp;
            }
        }
    }

    for(int i=0; i<len; i++){
        cout << "{" << ageArr[i].name << ","  << ageArr[i].age << "," << ageArr[i].sex << "}" <<endl;
        
    }

}

int main(){

    hero arrAge[5] = {
        {"劉備",23,"男"},
	{"關羽",22,"男"},
	{"張飛",20,"男"},
	{"趙雲",21,"男"},
	{"貂蟬",19,"女"}
    };
    int len = sizeof(arrAge)/sizeof(arrAge[0]);
    cout << "-----排序前打印:" << endl;
    for(int i=0; i<len; i++){
        cout << "{" << arrAge[i].name << ","  << arrAge[i].age << "," << arrAge[i].sex << "}" <<endl;
        
    }
    cout << "-----排序后打印:" << endl;
    Sort( arrAge,len );

    return 0;
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM