01 -- C++基礎入門
1、C++初識
1.1 第一個C++程序
創建一個HelloWorld程序
-
01 項目創建
-
02 創建文件
-
03 編寫代碼
示例:
#include <iostream> using namespace std; int main() { cout << "hello, C++" << endl; system("pause"); return 0; }
-
04 運行程序
點擊上方的綠色運行按鈕,運行項目:
1.2 注釋
作用:在代碼塊中方便程序員閱讀代碼,起解釋、說明的功能。
兩種格式:
-
單行注釋:
// 注釋信息
通常在代碼行的上方或者一條語句的末尾,對慈航代碼進行說明
-
多行注釋:
/*注釋信息*/
通常放在一段代碼的上方,對此段代碼做整體說明。
編譯器在編譯時會忽略注釋內容!
1.3 變量
注意一個項目只能有一個main函數,這里先注釋之前的main函數,再創建 02 變量輸出.cpp
作用:給一段指定的內存空間起名,方便操作這段內存。
語法: 數據類型 變量名 = 初始值;
示例:
#include <iostream>
using namespace std;
int main()
{
// 測試變量
int a = 5;
cout << "a = " << a << endl;
system("pause");
return 0;
}

1.4 常量
作用:用於記錄程序中不可更改的數據。
C++定義常量的兩種方式:
-
#define 宏變量:
#define 常量名 常數值
通常在文件上方定義,表示一個常量。
-
const修飾的變量:
const 數據類型 常量名 = 常數值
通常在變量定義前加關鍵字const,修飾該變量為常量,不可修改!
示例:
#include <iostream>
using namespace std;
// 常量的定義方式
// 1、#define 宏常量
// 2、const修飾的變量
// 1、定義宏常量
#define Day 7
int main()
{
// 定義const修飾的常量
const int month = 12;
cout << "一年有 " << month << "月;每周有" << Day << "天" << endl;
system("pause");
return 0;
}

1.5 關鍵字
關鍵字不能作為變量名!
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 |
1.6 標識符命名規則
作用:C++規定給標識符(變量、常量)命名時。需遵守如下規則:
- 標識符不能是關鍵字
- 標識符只能由字母、數字、下划線組成
- 第一個字符必須是字母或者下划線
- 標識符區分大小寫
2、數據類型
C++規定在創建一個變量或者常量時,必須指出相應的數據類型,否則無法給變量分配內存!
2.1 整型
作用:整型變量表示的是整數類型的數據!
數據類型 | 占用空間 | 取值范圍 |
---|---|---|
short(短整型) | 2字節 | (-2^15, 2^15 - 1) |
int(整型) | 4字節 | (-2^31, 2^31 - 1) |
long(長整型) | Windows為4字節,Linux32位為4字節,64為8字節 | (-2^31, 2^31 - 1) |
long long(長長整型) | 8字節 | (-2^63, 2^63 - 1) |
示例:
#include <iostream>
using namespace std;
// 常量的定義方式
// 1、#define 宏常量
// 2、const修飾的變量
// 1、定義宏常量
#define Day 7
int main()
{
// 定義const修飾的常量
const int month = 12;
long long elfin = 10;
cout << "一年有 " << month << "月;每周有" << Day << "天" << endl;
cout << "elfin今年" << elfin<< "歲" << endl;
system("pause");
return 0;
}
2.2 sizeof關鍵字
作用:利用sizeof關鍵字可以統計數據類型所占的內存大小
語法:sizeof(數據類型或變量)
示例:
#include <iostream>
using namespace std;
int main()
{
// 定義const修飾的常量
short a1 = 10;
long a2 = 10;
long long a3 = 10;
cout << "short的內存大小:" << sizeof(a1) << endl;
cout << "int的內存大小:" << sizeof(int) << endl;
cout << "long的內存大小:" << sizeof(a2) << endl;
cout << "long long的內存大小:" << sizeof(a3) << endl;
system("pause");
return 0;
}

2.3 實型
作用:用於表示小數
浮點型變量浮點型變量分為兩種:
- 01 單精度float
- 02 雙精度double
兩者的去吧在於表示的有效數字范圍不同。
數據類型 | 占用空間 | 有效數字范圍 |
---|---|---|
float | 4字節 | 7位有效數字(含整數部分) |
double | 8字節 | 15~16為有效數字 |
示例:
#include <iostream>
using namespace std;
int main()
{
// 定義float、double類型的常量
float f1 = 12.036f;
double d1 = 100.56;
cout << "sizeof(f1): " << sizeof(f1) << endl;
cout << "sizeof(d1): " << sizeof(d1) << endl;
system("pause");
return 0;
}

默認輸出六位有效數字!
2.4 字符型
作用:字符型變量用於顯示單個字符
語法: char ch = 'a'
注意1:在顯示字符型變量時,用單引號將字符括起來,不要用雙引號
注意2:單引號內只能有一個字符,不可以是字符串
- C和C++中字符型變量只占用1個字符
- 字符型變量並不是把字符本身放到內存中存儲,而是將相應的ASCII編碼放入到存儲單元
示例:
#include <iostream>
#include <typeinfo>
using namespace std;
int main()
{
// 字符型創建方式
char ch = 'd';
// 字符型變量所占的內存大小
cout << "字符型變量所占的內存大小sizeof(ch): " << sizeof(ch) << endl;
// 字符型變量常見錯誤
// char ch2 = "b"; // 創建字符型變量,必須使用單引號
char ch3 = 'dc'; // 語法沒有報錯,但是鼠標移動到dc上顯示 int 25699
cout << "ch3: " << ch3 << endl;
cout << "ch3: " << typeid(ch3).name() << endl;
// 字符變量對應的ASCII編碼
char ch4 = 'a';
cout << "ch4: " << (int)ch4 << endl;
system("pause");
return 0;
}

注意這里ch3輸出的並不是‘dc’
2.5 轉義字符
作用:用於一些不能表達出來的ASCII字符
先階段常用的轉義字符有: \n \\ \t
示例:
轉義字符 | 意義 | ASCII碼值(十進制) |
---|---|---|
\a | 響鈴(BEL) | 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 | 空字符(NUL) | 000 |
\ddd | 1到3位八進制數所代表的任意字符 | 三位八進制 |
\xhh | 十六進制所代表的任意字符 | 十六進制 |
2.6 字符串類型
作用:用於表示一串字符
語法:
- C風格字符串:
char 變量名[] = "字符串值"
- C++風格字符串:
string 變量名 = "字符串值"
注意C風格的字符串要用雙引號!
示例:
#include <iostream>
#include <string> // 使用C++類型的字符串
using namespace std;
int main()
{
// C風格字符串
char ch[] = "dc";
cout << "ch: " << ch << endl;
// C++風格字符串
string ch2 = "hello world";
cout << "ch2: " << ch2 << endl;
system("pause");
return 0;
}

2.7 布爾數值類型
作用:表示真、假
語法:bool 變量名 = true/false
布爾類型只占一個字節的內存空間!
2.8 數據的輸入
作用:用於從鍵盤獲取數據
關鍵字:cin
語法: cin >> 變量
示例:
#include <iostream>
#include <string> // 使用C++類型的字符串
using namespace std;
int main()
{
// 整型輸入
int a = 0;
cout << "請輸入整型變量:" << endl;
cin >> a;
cout << "a:" << a << endl;
// 浮點型輸入
double d = 0;
cout << "請輸入浮點型變量:" << endl;
cin >> d;
cout << "d:" << d << endl;
// 字符型輸入
char ch = 'a';
cout << "請輸入字符型變量:" << endl;
cin >> ch;
cout << "ch:" << ch << endl;
// 字符串型輸入
string ch2 = "world";
cout << "請輸入字符串型變量:" << endl;
cin >> ch2;
cout << "ch2:" << ch2 << endl;
// 布爾型輸入
bool b = 0;
cout << "請輸入布爾型變量:" << endl;
cin >> b;
cout << "b:" << b << endl;
system("pause");
return 0;
}

3、運算符
作用:用於執行代碼的運算
運算符類型 | 作用 |
---|---|
算術運算符 | 處理四則運算 |
賦值運算符 | 用於將表達式的值賦給變量 |
比較運算符 | 用於表達式的比較,並返回一個真值或假值 |
邏輯運算符 | 用於根據表達式的值返回真值或假值 |
3.1 算術運算符
運算符 | 描述 | 實例 |
---|---|---|
+ | 把兩個操作數相加 | A + B 將得到 30 |
- | 從第一個操作數中減去第二個操作數 | A - B 將得到 -10 |
* | 把兩個操作數相乘 | A * B 將得到 200 |
/ | 分子除以分母; 這里如果分子分母都是整數,則結果也是整數 |
B / A 將得到 2 |
% | 取模(取余)運算符,整除后的余數 | B % A 將得到 0 |
++ | 自增運算符,整數值增加 1 | A++ 將得到 11 |
-- | 自減運算符,整數值減少 1 | A-- 將得到 9 |
- 前置遞增:如
b = ++a
是先對變量a遞增再賦值; - 后置遞增:如
b = a++
是先對變量b賦值在遞增; - 遞減與遞增一樣!
示例:
#include <iostream>
using namespace std;
int main()
{
int a = 21;
int c;
// a 的值在賦值之前不會自增
c = a++;
cout << "Line 1 - Value of a++ is :" << c << endl;
// 表達式計算之后,a 的值增加 1
cout << "Line 2 - Value of a is :" << a << endl;
// a 的值在賦值之前自增
c = ++a;
cout << "Line 3 - Value of ++a is :" << 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*=3; | a=6; |
/= | 除等於 | a=6; a/=2; | a=3; |
%= | 模等於 | a=3; a%=2; | a=1; |
3.3 比較運算符
作用:用於表達式的比較,並返回一個真值或假值
比較運算符有以下符號:
示例:
運算符 | 術語 | 示例 | 結果 |
---|---|---|---|
== | 相等於 | 4==2; | 0 |
!= | 不等於 | 4!=3; | 1 |
< | 小於 | 4<3; | 0 |
> | 大於 | 3>2; | 1 |
<= | 小於等於 | 2<=3; | 1 |
>= | 大於等於 | 3>=1; | 1 |
3.4 邏輯運算符
作用:用於根據表達式的值返回真值或假值
邏輯運算符有以下符號:
示例:
運算符 | 術語 | 示例 | 結果 |
---|---|---|---|
! | 非 | !a | 如果a為真,!a為假,即取反 |
&& | 與 | a && b | 當且僅當a、b都為真a && b 才是真 |
|| | 或 | a||b | a、b中有一個為真,a || b 就為真 |
4、程序流程控制
C/C++支持最基本的程序運行結構:順序結構、選擇結構、循環結構
- 順序結構:程序按順序執行,不發生跳轉
- 選擇結構:依據條件是否滿足,有選擇的執行相應功能
- 循環結構:依據條件是否滿足,循環多次執行某段代碼
4.1 選擇結構
4.1.1 if語句
作用:執行滿足一傲嬌的語句
if語句的三種形式:
- 單行格式if語句
- 多行格式if語句
- 多條件的if語句
-
單行格式if語句:
if(條件){條件滿足執行的語句}
st=>start: 開始框 op=>operation: 執行語句 cond=>condition: 判斷條件框(是或否?) e=>end: 結束框 st->cond cond(yes)->op->e cond(no)->e
-
多行格式if語句:
if(條件){滿足條件時執行的語句}else{不滿足條件時執行的語句}
st=>start: 開始框 op1=>operation: 執行語句1 op2=>operation: 執行語句2 cond=>condition: 判斷條件框 e=>end: 結束框 st->cond cond(yes)->op1->e cond(no)->op2->e
if(a>=1){ cout << "a大於等於1" << endl; } else{ cout << "a不大於1" << endl; }
-
多條件的if語句
st=>start: 開始框 op1=>operation: 執行語句1 op2=>operation: 執行語句2 op3=>operation: …… op4=>operation: 執行語句n op5=>operation: 執行語句n+1 cond=>condition: 判斷條件1 cond1=>condition: 判斷條件2 cond2=>condition: …… cond3=>condition: 判斷條件n e=>end: 結束框 st->cond cond(yes)->op1->e cond(no)->cond1(yes)->op2->e cond(no)->cond1(no)->cond2(yes)->op3->e cond(no)->cond1(no)->cond2(no)->cond3(yes)->op4->e cond(no)->cond1(no)->cond2(no)->cond3(no)->op5->e
if(a>5) { cout >> "a > 5" >> endl; } else if(a >= 3) { cout >> "3 <= a <=5" >> endl; } else { cout >> "a不滿足要求" >> endl; }
-
嵌套if語句:在if語句中,可以嵌套使用if語句,達到更精確的條件判斷!
案例需求:
- 提示用戶輸入一個高考考試分數,根據分數做如下判斷
- 分數如果大於600分視為考生一本,大於500分考上二本,大於400考上三本,其余視為未考上本科
- 在一本分數中,大於700分考上北大,大於650分考上清華,大於600分考上人大
#include <iostream> using namespace std; int main() { int score = 0; cout << "請輸入你的高考成績:" << endl; cin >> score; if (score > 600) { cout << "恭喜你考上一本:" << endl; if (score > 700) { cout << "恭喜你考上北大……" << endl; } else if (score > 650) { cout << "恭喜你考上清華……" << endl; } else{ cout << "恭喜你考上人大……" << endl; } } else if (score > 500) { cout << "恭喜你考上二本……" << endl; } else if (score > 400) { cout << "恭喜你考上三本……" << endl; } else { cout << "抱歉,你未考上本科……" << endl; } system("pause"); return 0; }
4.1.2 三目運算符
c = (a>b?a:b);
如果a大於b,則返回a,否則返回b。
在C++中,三目運算符返回的是變量可以賦值:
int a = 10
int b = 20
(a > b ? a : b) = 100
此時b=100
python中一般使用:條件為真的結果 if 條件 else 為假時的返回
4.1.3 switch語句
作用:執行多條件的分支語句
語法:
switch{
case 結果1: 執行語句;break;
case 結果1: 執行語句;break;
……
default:執行語句;break;
}
示例:
#include <iostream>
using namespace std;
int main()
{
char a = 'a';
cout << "請輸入字符:s或者c" << endl;
cin >> a;
switch (a)
{
case 's':
cout << "case:s input>>" << a << endl;
case 'c':
cout << "case:c input>>" << a << endl;
default:
break;
}
}

4.2 循環結構
讓代碼重復地去執行
4.2.1 while循環
作用:滿足循環條件,執行循環語句
語法:while(循環條件){循環語句}
示例:
#include <iostream>
using namespace std;
int main()
{
int num = 0;
while (num < 10)
{
cout << "輸出num=" << num << endl;
num++;
}
system("pause");
return 0;
}
注意不要寫死循環!
4.2.2 do-while循環語句
作用:滿足循環條件,執行循環語句
語法:do{循環語句}while(循環條件)
示例:
#include <iostream>
using namespace std;
int main()
{
int num = 0;
do
{
cout << "輸出num=" << num << endl;
num++;
}
while (num < 10)
system("pause");
return 0;
}
do-while不滿足條件也會先執行一次!,即后判斷條件!
4.2.3 for循環結構
作用:滿足循環條件,執行循環語句
語法:for(循環條件){循環語句}
示例:
using namespace std;
int main()
{
for (int i = 0; i < 10; i++)
{
cout << "輸出i=" << i << endl;
}
system("pause");
return 0;
}
注意for后面的三個語句不是必須寫在括號里的,但是i++必須放在判斷條件后!
4.2.4 嵌套循環
嵌套循環與嵌套選擇結構類似
4.2.5 跳轉結構 break、continue、goto
break
:跳出當前循環;
continue
:跳出本次循環執行下一次;
goto
:無條件跳轉到標記的位置;
#include <iostream>
using namespace std;
int main()
{
cout << "輸出 1" << endl;
goto FLAG;
cout << "輸出 2" << endl;
flag:
cout << "輸出 3" << endl;
FLAG:
cout << "輸出 4" << endl;
goto flag;
cout << "輸出 5" << endl;
system("pause");
return 0;
}
注意上面的代碼是死循環,需要說明的是一般不要使用goto,使用的時候也不要將goto放置在標記后面,不然會容易成為死循環!
5、數組
5.1 概述
所謂數組,就是一個集合,里面存放了相同類型的數據元素
特點1:數組中的每個數據元素都是相同的數據類型
特點2:數組是由連續的內存位置組成的
5.2 一維數組
5.2.1 一維數組定義方式
一維數組定義的三種方式:
數據類型 數組名[數組長度];
數據類型 數組名[數組長度] = {值1, 值2, ……};
數據類型 數組名[ ] = {值1, 值2, ……};
示例:
#include <iostream>
using namespace std;
int main()
{
// 數據類型 數組名[數組長度];
int arr[5];
arr[0] = 20;
arr[1] = 50;
arr[2] = 45;
arr[3] = 7;
arr[4] = 0;
cout << "輸出 arr[3] = " << arr[3] << endl;
// 數據類型 數組名[數組長度] = {值1, 值2, ……};
// 初始化如果沒有全部賦值,會使用0填充
int arr2[5] = {25, 32, 1, 36, 5};
cout << "輸出 arr2[2] = " << arr2[3] << endl;
// 數據類型 數組名[數組長度] = {值1, 值2, ……};
int arr3[] = { 25, 32, 1, 36, 5, 36};
cout << "輸出 arr3[2] = " << arr3[3] << endl;
system("pause");
return 0;
}
5.2.2 數組名的用途
- 統計數組在內存中的長度 sizeof(arr)
- 可以獲取數組在內存中的首地址
示例:
#include <iostream>
using namespace std;
int main()
{
// 數組名用途
// 1、可以通過數組名統計整個數組占用內存大小
int arr2[5] = { 25, 32, 1, 36, 5 };
cout << "整個數組占用的內存空間為: " << sizeof(arr2) << endl;
cout << "每個元素占用的內存空間為: " << sizeof(arr2[0]) << endl;
cout << "數組中元素個數為: " << sizeof(arr2) / sizeof(arr2[0]) << endl;
// 2、可以通過數組名查看數組首地址
cout << "數組的首地址為: " << (int)arr2 << endl;
cout << "數組第一個元素的地址為: " << (int)arr2[0] << endl;
cout << "數組第二個元素的地址為: " << (int)arr2[1] << endl;
// 數組名不可修改
system("pause");
return 0;
}

元素逆置:
#include <iostream>
using namespace std;
int main()
{
// 數組逆置
// 1、創建數組
int arr2[5] = { 1, 2, 3, 4, 5 };
cout << "數組逆置前: " << endl;
for (int i = 0; i < 5; i++)
{
cout << arr2[i] << endl;
}
// 2、實現逆置:記錄起始、結束的下標位置;互換起始結束下標的位置;
// 起始位置,結束位置分別++、--;循環執行,直到起始位置大於等於結束位置
int start = 0; //起始下標
int end = sizeof(arr2) / sizeof(arr2[0]) -1; //結束下標
while (start < end)
{
//實現元素互換
int temp = arr2[start];
arr2[start] = arr2[end];
arr2[end] = temp;
//下標更新
start++;
end--;
}
//輸出逆置后的元素
cout << "數組逆置后: " << endl;
for (int i = 0; i < 5; i++)
{
cout << arr2[i] << endl;
}
system("pause");
return 0;
}
5.2.3 冒泡排序
作用:最常用的排序算法,對數組內元素進行排序
- 比較相鄰的元素,如果第一個比第二個大,就交換他們兩個。
- 對每一對相鄰元素做同樣的工作,執行完畢后,找到第一個最大值。
- 重復以上的步驟,每次比較次數-1,直到不需要比較。
示例:將數組{4,2,8,0,5,7,1,3,9}進行升序排列
裝逼版:后面有純凈版的代碼
#include <iostream>
#include <Windows.h>
using namespace std;
void COLOR_PRINT(const char* s, int color)
{
HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);
SetConsoleTextAttribute(handle, FOREGROUND_INTENSITY | color);
printf(s);
SetConsoleTextAttribute(handle, FOREGROUND_INTENSITY | 7);
}
int main()
{
// 創建需要排序的數組
int arr[9] = {4,2,8,0,5,7,1,3,9};
// 輸出排序前的數組元素
printf("排序前的數組:%-4d %-4d %-4d %-4d %-4d %-4d %-4d %-4d %-4d",
arr[0], arr[1], arr[2], arr[3], arr[4], arr[5], arr[6], arr[7], arr[8]);
printf("\n正在排序中……\n");
for (int i = 0; i < 9 - 1; i++)
{
for (int j = 0; j < 8 - i; j++)
{
printf("排序中的數組:");
if (arr[j] > arr[j + 1])
{
int temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
for (int k = 0; k < 9; k++)
{
if (k == j || k == j + 1)
{
printf("\033[33m%-4d\033[0m", arr[k]);
}
else
{
printf("%-4d", arr[k]);
}
}
printf("\r");
Sleep(1000);
}
else
{
for (int k = 0; k < 9; k++)
{
if (k == j || k == j + 1)
{
printf("\033[33m%-4d\033[0m", arr[k]);
}
else
{
printf("%-4d", arr[k]);
}
}
printf("\r");
Sleep(1000);
}
}
}
printf("\n排序結束……\n");
printf("排序后的數組:%-4d %-4d %-4d %-4d %-4d %-4d %-4d %-4d %-4d",
arr[0], arr[1], arr[2], arr[3], arr[4], arr[5], arr[6], arr[7], arr[8]);
system("pause");
return 0;
}

純凈版:
#include <iostream>
#include <Windows.h>
using namespace std;
int main()
{
// 創建需要排序的數組
int arr[9] = {4,2,8,0,5,7,1,3,9};
// 輸出排序前的數組元素
printf("排序前的數組:%-4d %-4d %-4d %-4d %-4d %-4d %-4d %-4d %-4d",
arr[0], arr[1], arr[2], arr[3], arr[4], arr[5], arr[6], arr[7], arr[8]);
printf("\n正在排序中……\n");
for (int i = 0; i < 9 - 1; i++)
{
for (int j = 0; j < 8 - i; j++)
{
printf("排序中的數組:");
if (arr[j] > arr[j + 1])
{
int temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
printf("排序后的數組:%-4d %-4d %-4d %-4d %-4d %-4d %-4d %-4d %-4d",
arr[0], arr[1], arr[2], arr[3], arr[4], arr[5], arr[6], arr[7], arr[8]);
printf("\r");
Sleep(1000);
}
}
}
printf("\n排序結束……\n");
printf("排序后的數組:%-4d %-4d %-4d %-4d %-4d %-4d %-4d %-4d %-4d",
arr[0], arr[1], arr[2], arr[3], arr[4], arr[5], arr[6], arr[7], arr[8]);
system("pause");
return 0;
}
這里相鄰元素判斷時,else實際上沒有什么用,裝逼版的代碼僅僅是為了,動態顯示排序的過程!
5.3 二維數組
二維數組就是在一維數組上,多加一個維度。
5.3.1 二維數組定義方式
二維數組定義的四種方式:
數據類型 數組名[行數][列數];
數據類型 數組名[行數][列數] = {{數據1, 數據2}, {數據3, 數據4}};
數據類型 數組名[行數][列數] = {數據1, 數據2, 數據3, 數據4};
數據類型 數組名[][列數] = {數據1, 數據2, 數據3, 數據4};
建議:以上4種定義方式,利用第二種更加直觀,提高代碼的可讀性
#include <iostream>
using namespace std;
int main()
{
// 創建需要的數組
// int arr[2][2];
int arr1[2][2] = {1,2,3,4};
// int arr2[2][2] = { {4,2},{8,0}};
// int arr3[][2] = { {4,2},{8,0}};
// 外層循環打印行數,內層循環打印列數
for (int i = 0; i < 2; i++)
{
for (int j = 0; j < 2; j++)
{
cout << arr1[i][j]<< endl;
}
}
system("pause");
return 0;
}
5.3.2 二維數組數組名
- 查看二維數組所占內存空間
- 獲取二維數組首地址
#include <iostream>
#include <Windows.h>
using namespace std;
int main()
{
// 創建需要的數組
// int arr[2][2];
int arr1[2][2] = { 1,2,3,4 };
// 可以查看占用內存空間大小
cout << "二維數組大小:" << sizeof(arr1) << endl;
cout << "二維數組一行大小:" << sizeof(arr1[0]) << endl;
cout << "二維數組元素大小:" << sizeof(arr1[0][0]) << endl;
cout << "二維數組的行數:" << sizeof(arr1) / sizeof(arr1[0]) << endl;
cout << "二維數組的列數:" << sizeof(arr1[0]) / sizeof(arr1[0][0]) << endl;
// 可以查看二維數組的首地址
cout << "二維數組首地址為:" << int(arr1) << endl;
cout << "二維數組第一行首地址為:" << int(arr1[0]) << endl;
cout << "二維數組第二行首地址為:" << int(arr1[1]) << endl;
// 這里可以發現二維數組的內存也是連續的!
system("pause");
return 0;
}
6、函數
6.1 函數的定義
函數的定義一般有5個步驟:
- 1、返回值類型
- 2、函數名
- 3、參數列表
- 4、函數體語句
- 5、return表達式
語法:
返回值類型 函數名(參數列表)
{
函數體語句;
return 表達式;
}
示例:
#include <iostream>
#include <Windows.h>
using namespace std;
// num1、num2是形參,實際傳入的時候是實參
int add(int num1, int num2)
{
int num = num1 + num2;
return num;
}
int main()
{
// 函數調用
int num = add(2, 6);
cout << "num=" << num << endl;
system("pause");
return 0;
}
6.2 函數的值傳遞
作用:所謂值傳遞就是函數調用時實參將值傳入給形參
值傳遞時,如果形參發生變化,並不會影響實參
示例:
#include <iostream>
using namespace std;
// 值傳遞
// 定義函數,實現兩個數字進行交換函數
//如果函數不需要返回值,聲明的時候可以寫void
void swap(int num1, int num2)
{
cout << "交換前:" << endl;
cout << "num1 = " << num1 << endl;
cout << "num2 = " << num2 << endl;
int temp = num1;
num1 = num2;
num2 = temp;
cout << "交換后:" << endl;
cout << "num1 = " << num1 << endl;
cout << "num2 = " << num2 << endl;
// return; 返回值不需要的時候,可以不寫return
}
int main()
{
int a = 10;
int b = 20;
cout << "a=" << a << endl;
cout << "b=" << b << endl;
// 函數調用,當我們值傳遞時,函數的形參發生改變並不會影響實參
swap(2, 6);
cout << "a=" << a << endl;
cout << "b=" << b << endl;
system("pause");
return 0;
}

6.3函數的聲明
作用:告訴編譯器函數名稱及如何調用函數。函數的實際主體可以單獨定義。
- 函數的聲明可以多次,但是函數的定義只能有一次
示例:
main函數放在被調用的函數之前,被調用的函數必須提前聲明!
#include <iostream>
using namespace std;
// 函數的聲明
// 比較函數,實現兩個整數的比較,返回較大的值
// 提前告訴編譯器函數的存在,可以利用函數的聲明
// 函數的聲明,聲明可以有多次,但是定義只能有一次
int my_max(int num1, int num2);
int main()
{
int a = 10;
int b = 20;
cout << my_max(a,b) << endl;
system("pause");
return 0;
}
// 定義
int my_max(int num1, int num2)
{
return num1 > num2 ? num1 : num2;
}
6.4 函數的分文件編寫
作用:將部分對象單獨寫一個文件,讓代碼結構更加清晰
函數分文件編寫一般4個步驟:
- 1、創建后綴為
.h
的頭文件 - 2、創建后綴名為
.cpp
的源文件 - 3、在頭文件中寫函數的聲明
- 4、在源文件中寫函數的定義
示例1 – 創建頭文件:
#include <iostream>
using namespace std;
void swap(int num1, int num2);

示例2 – 創建源文件:
#include "swap.h"
void swap(int num1, int num2)
{
cout << "交換前:" << endl;
cout << "num1 = " << num1 << endl;
cout << "num2 = " << num2 << endl;
int temp = num1;
num1 = num2;
num2 = temp;
cout << "交換后:" << endl;
cout << "num1 = " << num1 << endl;
cout << "num2 = " << num2 << endl;
// return; 返回值不需要的時候,可以不寫return
}

示例3 – 其他源文件調用:
#include <iostream>
using namespace std;
#include "swap.h"
int main()
{
int a = 10;
int b = 20;
cout << "a=" << a << endl;
cout << "b=" << b << endl;
// 函數調用,當我們值傳遞時,函數的形參發生改變並不會影響實參
swap(2, 6);
cout << "a=" << a << endl;
cout << "b=" << b << endl;
system("pause");
return 0;
}

7、指針
7.1 指針的基本概念
作用:可以通過指針間接訪問內存
- 內存編號是從零開始記錄的,一般采用十六進制數字表示
- 可以利用指針變量保存內存地址
7.2 指針變量的定義和使用
指針變量的語法:數據類型 * 變量名;
示例:
#include <iostream>
using namespace std;
int main()
{
// 1、定義一個指針
int a = 10;
cout << "a=" << a << endl;
// 指針定義的語法:數據類型 * 指針變量名
int* p;
// 讓指針記錄變量a的地址
p = &a;
cout << "a的地址為:" << &a << endl;
cout << "指針p為:" << p << endl;
// 2、使用指針
// 可以通過“解引用”的方式來找到指針指向的內存
// 指針前加 * 代表解引用,找到指針指向的內存中的數據
*p = 1000;
cout << "a=" << a << endl;
cout << "*p=" << *p << endl;
system("pause");
return 0;
}

7.3 指針所占的內存空間
指針表示了一個內存地址,內存地址編號的存儲:
- 32位操作系統,占用四個字節
- 64位占用8個字節
cout << "sizeof (int *) = " << sizeof(int *) << endl;
cout << "sizeof (int *) = " << sizeof(p) << endl;
7.4 空指針和野指針
空指針
空指針:指針變量指向內存中編號為0的空間
用途:初始化指針變量
注意:空指針指向的內存是不可以訪問的
示例1:空指針:
#include <iostream>
using namespace std;
int main()
{
// 空指針
// 1、空指針用於給指針變量初始化
// 指針變量p指向內存地址編號為0的空間
int* p = NULL;
//2、空指針是不能進行訪問的
// 內存編號為0~255的內存編號是系統占用的,因此不能訪問、更改
// *p = 100; // 訪問空指針會報錯
system("pause");
return 0;
}
野指針
作用:指針變量指向非法的內存空間
示例2:野指針:
#include <iostream>
using namespace std;
int main()
{
// 野指針
// 1、指向了0x1100內存,但是我們沒有申請這塊空間,所以野指針不能進行操作
int * p = (int *)0x1100; // 語法能夠通過,但是不能進行操作!
//2、野指針是不能進行訪問的
// cout << *p << endl; 運行會報錯
system("pause");
return 0;
}
總結:空指針與野指針都不是我們申請的空間,所以不要訪問!
7.5 const修飾指針
const修飾指針有三種情況;
- 1、const修飾指針 ---> 常量指針
- 2、const修飾常量 ---> 指針常量
- 3、const既修飾指針又修飾常量
示例:
#include <iostream>
using namespace std;
int main()
{
// 1、常量指針
// 指針的指向可以修改,指向的值不能修改
int a = 10;
const int * p1 = &a; // 常量指針
//2、指針常量
// const修飾常量時,是指針常量,不能修改指針的指向,可以修改指向的值
int b = 20;
int * const p2 = &b; // 指針常量
// 3、既修飾指針又修正常量
// 指針的指向與指針指向的值都不能修改
int c = 2;
const int * const p3 = &c;
cout << *p3 << endl;
system("pause");
return 0;
}
總結:
- 按照const、*出現的順序命名;
const + *
標識常量指針;* + const
標識指針常量;
7.6 指針和數組
作用:利用指針訪問數組中的元素
指針的類型決定了使用p++
時的自增字節數,如int、float在Windows下都是自增4,而double類型是自增8,這樣恰好和我們的數據類型對應上。
示例:
#include <iostream>
using namespace std;
int main()
{
//指針和數組
//利用指針訪問數組中的元素
// 創建數組
int arr[] = {1, 2, 3, 4, 5, 6, 7, 8, 9};
const int * p = arr; // 指向數組的指針
cout << "第一個元素:" << arr[0] << endl;
cout << "指針訪問第一個元素:" << *p << endl;
for (int i = 0; i < 9; i++)
{
// 利用指針遍歷數組
cout << *p << endl;
p++; // ++會向后偏移4個字節,因為本來就是int類型的指針
cout << "指針的指向內存地址:" << (int)&*p << endl;
}
// 其他類型的指針++也是增加4個字節嗎?
double arr2[] = { 2.36, 2.14, 3.56 };
double* p1 = arr2;
for (int i = 0; i < 3; i++)
{
// 利用指針遍歷數組
cout << *p1 << endl;
p1++; // ++會向后偏移8個字節,因為指針是double類型
cout << "double指針的指向內存地址:" << (int)&*p1 << endl;
}
system("pause");
return 0;
}

7.7 指針和函數
作用:地址傳遞可以改變實參的值
注:如果不想修改實參就用值傳遞,如果想修改實參就使用地址傳遞!
示例:
#include <iostream>
using namespace std;
void swap01(int num1, int num2);
void swap02(int * num1, int * num2);
int main()
{
//指針和函數
//之前我們使用形參、實參實現函數內外的值傳遞;
//如果在函數里面修改形參的值,函數體外的實參也想對應發生變化怎么辦?
//1、值傳遞
int a = 12;
int b = 24;
cout << "值傳遞前的a=" << a << endl;
cout << "值傳遞前的b=" << b << endl;
swap01(a, b);
cout << "值傳遞后的a=" << a << endl;
cout << "值傳遞后的b=" << b << endl;
//2、地址傳遞
cout << "地址傳遞前的a=" << a << endl;
cout << "地址傳遞前的b=" << b << endl;
swap02(&a, &b);
cout << "地址傳遞后的a=" << a << endl;
cout << "地址傳遞后的b=" << b << endl;
system("pause");
return 0;
}
void swap01(int num1, int num2)
{
int temp = num1;
num1 = num2;
num2 = temp;
cout << "swap01的a=" << num1 << endl;
cout << "swap01的b=" << num2 << endl;
}
void swap02(int * num1, int * num2)
{
int temp = *num1;
*num1 = *num2;
*num2 = temp;
cout << "swap02的a=" << * num1 << endl;
cout << "swap02的b=" << * num2 << endl;
}

7.8 指針使用案列
案列描述:封裝一個函數,利用冒泡排序,實現對整型數組的升序排序
例如數組:int arr[6] = { 10, 2, 65, 22, 41, 9 };
示例:
#include <iostream>
using namespace std;
void bubbleSort(int * arr, int len)
{
for (int i = 0; i < len - 1; i++)
{
for (int j = 0; j < len - 1 - i; j++)
{
if (arr[j] > arr[j + 1])
{
int temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}
}
}
}
void printArray(int* arr, int len)
{
for (int i = 0; i < len; i++)
{
cout << arr[i] << endl;
}
}
int main()
{
// 1、先創建數組
int arr[6] = { 10, 2, 65, 22, 41, 9 };
// 數組長度
int len = sizeof(arr) / sizeof(arr[0]);
// 2、創建函數,實現冒泡排序
bubbleSort(arr, len);
// 3、打印排序后的數組
printArray(arr, len);
system("pause");
return 0;
}

8、 結構體
8.1 結構體的基本概念
結構體屬於用戶自定義的數據類型,允許用戶存儲不同的數據類型
8.2 結構體定義和使用
語法:struct 結構體名{結構體成員列表};
通過結構體創建變量的方式有三種:
- struct 結構體名 變量名
- struct 結構體名 變量名 = {成員值1, 成員值2…}
- 定義結構體時順便創建變量
示例:創建學生類型的結構體:
#include <iostream>
#include <string>
using namespace std;
// 定義結構體
struct student
{
// 配置名字
string name;
// 配置年齡
int age;
// 配置得分
float score;
}s3;
int main()
{
// 通過學生數據類型,創建學生
// 1、struct 結構體名 變量名
struct student s1; // 創建變量時,struct關鍵字可以省略
s1.name = "elfin";
s1.age = 23;
s1.score = 98.5;
cout << " 姓名:\t" << s1.name
<< "\t年齡:\t" << s1.age
<< "\t分數:\t" << s1.score << endl;
// 2、struct 結構體名 變量名 = {成員值1, 成員值2…}
struct student s2 = { "嬴政", 12, 60 };
cout << " 姓名:\t" << s2.name
<< "\t年齡:\t" << s2.age
<< "\t分數:\t" << s2.score << endl;
// 3、定義結構體時順便創建變量(不建議使用)
// 即在創建結構體時,在結構體的"}"后書寫變量名
s3.name = "吳正天";
s3.age = 28;
s3.score = 100;
cout << " 姓名:\t" << s3.name
<< "\t年齡:\t" << s3.age
<< "\t分數:\t" << s3.score << endl;
system("pause");
return 0;
}
運行結果:

總結:創建結構體時關鍵字struct是必須要寫的,在創建結構體變量時這個關鍵字可以省略!
8.3 結構體數組
作用:將自定義的結構體放入到數組中方便維護(實際和數組里面放int類型數據一樣)
語法:struct 結構體名 數組名[元素個數] = { {}, {}, … ,{}}
這里的創建方式是和數組創建方式是一樣的!
示例:
#include <iostream>
#include <string>
using namespace std;
// 定義結構體
struct student
{
string name;
int age;
float score;
}s3;
int main()
{
// 創建結構體數組
// 創建結構體數組時,struct可以省略
struct student arr[3] = {
{"elfin", 23, 89.5},
{"嬴政", 12, 90},
{"吳正天", 28, 100},
};
arr[2].name = "武則天";
// 遍歷結構體數組
for (int i = 0; i < 3; i++)
{
cout << "姓名:" << arr[i].name
<< "\t年齡:" << arr[i].age
<< "\t分數:" << arr[i].score << endl;
}
system("pause");
return 0;
}
運行結果:

總結:結構體數組變量和普通的數組變量是一樣的,只是結構體數組變量的元素是一個自定義數據類型,元素會包含一些自定義的屬性變量!(成員)
8.4 結構體指針
作用:通過指針訪問結構體中的成員
語法:p->name
指針p使用“->”后面接結構體屬性就可以訪問該屬性了!
示例:
#include <iostream>
#include <string>
using namespace std;
// 定義結構體
struct student
{
string name;
int age;
float score;
};
int main()
{
// 創建結構體數組
// 創建結構體數組時,struct可以省略
struct student arr[3] = {
{"elfin", 23, 89.5},
{"嬴政", 12, 90},
{"吳正天", 28, 100},
};
arr[2].name = "武則天";
// 通過指針指向結構體變量
student* p = &arr[2];
// 通過指針訪問結構體的屬性
cout << "姓名:" << p->name
<< "\t年齡:" << p->age
<< "\t分數:" << p->score << endl;
// 通過結構體數組的指針訪問結構體元素的屬性
struct student* p1 = arr;
for (int i = 0; i < 3; i++)
{
cout << "姓名:" << p1->name
<< "\t年齡:" << p1->age
<< "\t分數:" << p1->score << endl;
p1++;
}
system("pause");
return 0;
}
運行結果:

8.5 結構體嵌套結構體
作用:結構體的成員可以是另一個結構體
例如:每個老師單獨輔導一個學生,一個老師的結構體中,記錄一個學生的結構體
示例:
#include <iostream>
#include <string>
using namespace std;
// 定義結構體
struct student
{
string name;
int age;
float score;
};
struct teacher
{
string name;
int age;
student s1;
};
int main()
{
// 創建嵌套結構體變量
struct teacher t1;
t1.name = "elfin";
t1.age = 45;
t1.s1 = { "白天", 12, 60 };
cout << "姓名:" << t1.name
<< "\t年齡:" << t1.age
<< "\t學生姓名:" << t1.s1.name
<< "\t學生年齡:" << t1.s1.age
<< "\t學生得分:" << t1.s1.score
<< endl;
system("pause");
return 0;
}
8.6 結構體做函數參數
作用:將結構體作為參數想函數中傳遞
傳遞方式有兩種:
- 值傳遞 (形參改變不改變實參)
- 地址傳遞 (形參改變會改變實參)
示例:
#include <iostream>
#include <string>
using namespace std;
// 定義結構體
struct student
{
string name;
int age;
float score;
};
// 打印學生信息的函數
// 值傳遞
void printStudent1(struct student s)
{
s.age = 24;
cout << "\n值傳遞的 姓名:" << s.name
<< "\t年齡:" << s.age
<< "\t得分:" << s.score
<< endl;
}
// 地址傳遞
void printStudent2(struct student * s)
{
s->age = 12;
cout << "\n地址傳遞的 姓名:" << s->name
<< "\t年齡:" << s->age
<< "\t得分:" << s->score
<< endl;
}
int main()
{
// 結構體做函數參數
// 將學生傳入到一個參數中,打印學生的所有信息
struct student t1 = {"elfin", 18, 100};
cout << "main函數中 姓名:" << t1.name
<< "\t年齡:" << t1.age
<< "\t得分:" << t1.score
<< endl;
printStudent1(t1);
cout << "\nmain函數中 姓名:" << t1.name
<< "\t年齡:" << t1.age
<< "\t得分:" << t1.score
<< endl;
printStudent2(&t1);
cout << "\nmain函數中 姓名:" << t1.name
<< "\t年齡:" << t1.age
<< "\t得分:" << t1.score
<< endl;
system("pause");
return 0;
}

8.7 結構體中const的使用場景
作用:用const防止誤操作
語法:哪里不想修改就給哪個加const,如在地址傳遞時,形參的變化會引起實參的變化,而我們不想實參發生變化,那么就給形參加const!
示例:
#include <iostream>
#include <string>
using namespace std;
// 定義結構體
struct student
{
string name;
int age;
float score;
};
void printStudent1(struct student s)
{
cout << "\n值傳遞的 姓名:" << s.name
<< "\t年齡:" << s.age
<< "\t得分:" << s.score
<< endl;
}
// 將函數中的形參改為指針,可以減少內存開銷而且不會復制新的副本出來
// 地址傳遞有隱患,如果內部修改屬性了外側也會修改,防止被修改,可以給形參加const,防止誤操作
void printStudent2(const struct student* s)
{
cout << "\n地址傳遞的 姓名:" << s->name
<< "\t年齡:" << s->age
<< "\t得分:" << s->score
<< endl;
}
int main()
{
// 創建結構體變量
struct student s = { "張三", 15, 80 };
// 通過函數打印結構體的信息
printStudent1(s); // 值傳遞
printStudent2(&s);
system("pause");
return 0;
}
8.8 結構體案例
案例描述:
-
設計一個英雄的結構體,包括成員姓名、年齡、性別;
-
創建結構體數組,數組中存放5名英雄;
-
通過冒泡排序的算法,將數組中的英雄按照年齡進行降序排列,最終打印排序后的結果。
-
英雄信息如下:
{"貂蟬", 19, "女"}, {"張飛", 20, "男"}, {"關羽", 22, "男"}, {"趙雲", 21, "男"}, {"劉備", 23, "男"}
示例:
#include <iostream>
#include <string>
using namespace std;
// 定義結構體
struct hero
{
string name;
int age;
string sex;
};
void printHero(struct hero s[], int len)
{
for (int i = 0; i < len; i++)
{
cout << "\t姓名:" << s[i].name
<< "\t年齡:" << s[i].age
<< "\t性別:" << s[i].sex
<< endl;
}
}
void bubbleSort(struct hero s[], int len, string order)
{
for (int i = 0; i < len - 1; i++)
{
// 降序排列
if (order == "descending")
{
for (int j = len - 1; j > i; j--)
{
if (s[j].age > s[j - 1].age)
{
hero temp = s[j];
s[j] = s[j - 1];
s[j - 1] = temp;
}
}
}
// 升序排列
else
{
for (int j = 0; j < len - i - 1; j++)
{
if (s[j].age > s[j + 1].age)
{
hero temp = s[j];
s[j] = s[j + 1];
s[j + 1] = temp;
}
}
}
}
// 打印排序后的結構體數組
if (order == "descending")
{
cout << "結構體數組降序排列:" << endl;
}
else
{
cout << "結構體數組升序排列:" << endl;
}
printHero(s, len);
}
int main()
{
// 創建結構體數組變量
struct hero arr[5] = {
{"貂蟬", 19, "女"},
{"張飛", 20, "男"},
{"關羽", 22, "男"},
{"趙雲", 21, "男"},
{"劉備", 23, "男"}
};
// 通過函數打印結構體的信息
int len = sizeof(arr) / sizeof(arr[0]);
cout << "打印原始的結構體數組信息:" << endl;
printHero(arr, len);
// 將結構體數組降序輸出
bubbleSort(arr, len, "descending");
// 將結構體數組升序輸出
bubbleSort(arr, len, "scending");
system("pause");
return 0;
}

完!