十、數組 1、數組的概念 1)引出數組 需求:學校為了統計學生的信息,需要設計一個程式,要求如下,一共有十個學員,要求依次輸入各位學員的學號,並將其列印出來。 #include <iostream> int main() { int studentId1, studentId2, studentId ...
十、數組
1、數組的概念
1)引出數組
需求:學校為了統計學生的信息,需要設計一個程式,要求如下,一共有十個學員,要求依次輸入各位學員的學號,並將其列印出來。
#include <iostream>
int main()
{
int studentId1, studentId2, studentId3, studentId4, studentId5;
std::cin >> studentId1;
std::cin >> studentId2;
std::cin >> studentId3;
std::cin >> studentId4;
std::cin >> studentId5;
std::cout << "第一個學生的學號為" << studentId1 << std::endl;
std::cout << "第二個學生的學號為" << studentId2 << std::endl;
std::cout << "第三個學生的學號為" << studentId3 << std::endl;
std::cout << "第四個學生的學號為" << studentId4 << std::endl;
std::cout << "第五個學生的學號為" << studentId5 << std::endl;
}
問題描述:實際生活中,我們經常會需要處理多個具有相同性質的數據,比如100個員工的工資、10個學院的學號,這種情況下,依次申請多個變數變得不太現實或者太過繁雜,這種情況下,我們使用數組來解決這樣的問題。
2)數組的聲明
//數組聲明語法
數據類型 數組變數名稱[數組元素個數]{初始化值,初始化值...}
//示例:申請10個學員的學號
int studentId[10]{1,2,3,4} //後面的沒初始化,預設為0。代表有10個元素
//示例:申請100個員工的工資
int salary[100]{} //不初始化,預設為0
註:同一個數組,其數據類型是一樣的
3)數組的使用及遍歷
//輸入10個學生的學號,並且輸出
#include <iostream>
int main()
{
int studentId[10]{};
for (int i = 0; i < 10; i++)
{
std::cout << "請輸入第" << i << "個學生的學號:";
std::cin >> studentId[i];
}
for (int i = 0; i < 10; i++)
{
std::cout << "第" << i << "個學生的學號為:";
std::cout << studentId[i]<<std::endl;
}
//計算數組中元素個數
std::cout << "studentId數組中有" << sizeof(studentId) / sizeof(int) << "個元素";
}
註:數組不初始化可以編譯,但是有可能使用記憶體中的垃圾數值
2)數組的本質
數組本質:數組的本質是按照所申請的數據類型,向操作系統申請了一段連續的記憶體空間,中間不能插入其他的變數
例:int age[6]在記憶體中是按照如下顯示的,總共占用4*6=26位元組
//計算數組的大小
#include <iostream>
int main()
{
int studentId[10]{};
std::cout<<"數組studentId的大小為"<<sizeof(studentId)<<std::endl; //即4*10=40位元組
}
2、數組的應用
1)項目設計
需求:學校今天開學,要求等級每一位報道的學生,因此我們要設計一個程式,要求輸入學員的編號,並且列印出來。根據報名錶得知,今天來報道的學生有100位,但是不排除有個別學生因為飛機晚點、火山噴發等原因無法即使到達,但是無論如何,我們的報道工作還是要做的
#include <iostream>
int main()
{
int studentId[100]{ 0 };
int indexId{}; //已等級的學生信息
while (indexId < 100)
{
std::cout << "輸入學號(輸入0查看已等級的學生信息):";
std::cin >> studentId[indexId];
if (studentId[indexId] == 0)
{
system("cls");
for (int i = 0; i < indexId; i++)
{
std::cout << i << "號 學生學號" << studentId[i] << std::endl;
}
}
else indexId++; //,不是0,就代表學號。表示變成了下一個元素
}
}
2)數組的另外一種聲明方式
//數組的另外一種聲明方式:不告訴數組的元素個數,但是對值進行賦值
變數類型 數組名[]{初始化,初始化}
//示例
int a[]{1,2,3}; //編譯器會自動將a聲明為只有一個有3個元素的數組
3、基於數組的迴圈
C++11之後的新用法:
1)案例:列印出一個數組的所有元素
//列印出一個數組的所有元素
#include <iostream>
int main()
{
int studentId[]{ 1001,1002,1003,1004,1005,1006 };
for (int i = 0; i < sizeof(studentId) / sizeof(int); i++) //先計算元素個數
{
std::cout << "第"<<i<<"個學生的學號為:" << studentId[i] << std::endl;
}
}
2)基於數組的迴圈
①基於數組的迴圈語法
//基於數組的迴圈語法
for(變數類型 變數名稱:數組名稱)
{
迴圈內容;
}
//例
for(int i:studentId) //給i賦予studentId數組中每個元素的值,
{
迴圈內容;
}
//第一次i=studentId[0],第二次i=studentId[1],第三次i=studentId[3],依次。。。
//變數類型根據實際需求進行定義,例如char、auto都可以
for(auto 變數名稱:數組)
{
迴圈內容;
}
②基於數組的迴圈用法
//基於數組的迴圈用法
#include <iostream>
int main()
{
int studentId[]{ 9991,9992,9993,9994,9995,9996 };
for (int i : studentId)
{
std::cout << i << std::endl; //取元素時,不再使用studentId[i]取數據中的值,而是直接通過i
}
}
③通過auto指定變數類型
//通過auto指定變數類型
#include <iostream>
int main()
{
int studentId[]{ 9991,9992,9993,9994,9995,9996 };
for (auto i : studentId) //系統通過auto自動推斷出變數類型
{
std::cout << i << std::endl;
}
}
④變數類型可以是任意類型
#include <iostream>
int main()
{
int studentId[]{ 65,66,67,68,69,70 };
for (char i:studentId) //次數會進行強制類型轉化
{
std::cout << i<< std::endl;
}
}
4、多維數組
1)引出多維數組:
需求:學校冬季要發大白菜,一共有3個班級,每個班級5個學員,要求統計這三個班所有學員的學號,並且列印出來。
//一維數組實現
#include <iostream>
int main()
{
int studentId[15]{ };
for (int x = 0; x < 15; x++)
{
std::cout << "第" << (x / 5) + 1 << "班,第" << (x % 5)+1 << "個學生" << std::endl;
}
}
2)多維數組的定義
//多維數組聲明語法
類型 變數名稱[元素個數][元素個數]...[元素個數]{};
//示例
int studentId[3][5]{}; //即可表示3個班,5個學員
//多維數組初始化示例
int studentId[3][5]
{
{101,102,103,104,105}, //訪問第一個元素studentId[0][0]
{201,202,203,204,205},
{301,302,303,304,305} //訪問第15個元素studentId[2][4]
}
案例:學校冬季要發大白菜,一共有3個班級,每個班級5個學員,要求統計這三個班所有學員的學號,並且列印出來。
#include <iostream>
//學院冬季發放大白菜,,一共3個班,每個班5個學院,要求統計這三個班所以學員的學號,並且列印出來
int main()
{
int studentId[3][5]
{
{101,102,103,104,105},
{201,202,203,204,205},
{301,302,303,304,305}
};
for (int x = 0; x < 3; x++)
{
for (int y = 0; y < 5; y++)
{
std::cout << x+1 << "班第" << y+1 << "個同學的學號是:" << studentId[x][y] << std::endl;
}
}
}
3)多維數組的遍歷
除上述方式外,還可使用如下方式遍歷多維數組,但是需要單獨引入一個變數進行計數
#include <iostream>
//學院冬季發放大白菜,,一共3個班,每個班5個學院,要求統計這三個班所以學員的學號,並且列印出來
int main()
{
int studentId[3][5]
{
{1,2,3,4,5},
{1,2,3,4,5},
{1,2,3,4,5}
};
for (int x=0;x<3;x++)
{
int count{};
for (int y :studentId[x]) //y就表示student[x]中的值
{
count++; //單獨引入一個變數進行計數
std::cout << x + 1 << "班第" << count << "個同學的學號是:" <<y << std::endl;
}
}
}
4)多維數組的本質
本質:多維數組的本質也是向操作系統申請一塊連續的記憶體,一般來講是按照低緯度優先排序的方式來排序(可能因操作系統和編譯器不同而不同),而索引只是為了方便訪問對應的記憶體區域
示例:int studentId[3][5]在記憶體中的樣子如下
studentId[0][0] | studentId[0][1] | studentId[0][2] | studentId[0][3] | studentId[0][4] |
---|---|---|---|---|
studentId[1][0] | studentId[1][1] | studentId[1][2] | studentId[1][3] | studentId[1][4] |
studentId[3][0] | studentId[3][1] | studentId[3][2] | studentId[3][3] | studentId[3][4] |
4)數組的安全問題
由於數組的本質是向操作系統申請了一塊記憶體,因此越界的數組將會訪問到不該訪問的地址,這種越界將會造成程式奔潰、BUG、錯誤,更可怕的是數組越界漏洞,可能會讓攻擊者拿到操作系統的控制權。
5、安全的數組(std::array容器)
1)std::array概念
由於原生的數組存在著安全問題,使用不當會造成程式的漏洞,因此C++標準庫里提供了容器,後面詳細的進行容器學習,本次只簡單瞭解array這種容器如何實現類似數組的功能。
//array數組的語法
#include <array> //需要先引入頭文件
std::array<變數類型,元素數量>變數名{初始化值}; //array的聲明
//案例
std::array<int,5>studentId; //5個學員的學號
2)array使用
#include <iostream>
#include <array> //引入頭文件
int main()
{
std::array<int, 4>studentId{ 1001,1002,1003,1004 }; //聲明一個int類型的數組,包含4個元素,併進行初始化
for (int x : studentId) //遍曆數組,x表示數組中的每個元素
{
std::cout << x << std::endl;
}
}
2)std::array的幾個常見用法
//std::array的幾個常見用法
std::array<int,5>studentId; //聲明5個學員的學號
studentId.size(); //返回studentId擁有幾個元素
studentId.fill(250); //將studentId數組的每個元素都設置為250
studentId.at(1); //返回studentId[1]的內容
#include <iostream>
#include <array>
int main()
{
std::array<int, 5>studentId; //聲明5個學員的學號
std::cout << "數組studentId擁有" << studentId.size() << "個元素" << std::endl;; //返回studentId擁有幾個元素
studentId.fill(250); //將studentId數組的每個元素都設置為250
for (int i : studentId)
{
std::cout << i << std::endl;
}
std::cout << "數組studentId的第4個值為" << studentId.at(3)<<std::endl; //返回studentId[3]的內容
}
3)std::array的安全性
當使用【數組名.at】時,如果數組越界會直接報錯,便於尋找錯誤,但是原生數組對於越界訪問的數組不報錯。
4)array數組的比較
通過std::array可以比較兩個數組是否相同,但是原生數組無法進行比較
//數組的比較
#include <iostream>
#include <array>
int main()
{
int classA[3]{ 123,456 };
int classB[3]{ 123,456 };
std::array<int, 5>studentIdA{123,456,789};
std::array<int, 5>studentIdB{123,456,789};
std::array<int, 5>studentIdC{121,456,789 };
std::cout << (classA == classB) << std::endl; //返回0,說明原生數組不可以進行比較
std::cout << (studentIdA == studentIdB) << std::endl; //返回1
std::cout << (studentIdA == studentIdC) << std::endl; //返回0
}
6、std::vector容器
1)std::vector語法
//vector數組的語法
#include <vector> //需要先引入頭文件
std::vector<數據類型>變數名{初始化值}; //vector的聲明
//案例
std::vector<int>studentId; //聲明一個int類型的數組studentId,但是沒有元素
std::vector<int>studentId{1,2,3}; //聲明一個int類型的數組studentId,初始化3個元素
std::vector<int>studentId(5); //註意是(),不是{},設置這個vector擁有5個元素
std::vector<int>studentId(5,100); //註意是(),不是{},設置這個vector擁有5個元素,且初始值都為100
2)std::vector簡單使用
#include <iostream>
#include <vector>
int main()
{
std::vector<int> studentId(5); //告訴數組有5個元素,預設有初始值
std::cout << "數組有:" << studentId.size() <<"個元素" << std::endl;
std::cout << studentId.at(2) << std::endl; //查看studentId[2]的值
for (int x : studentId)
{
std::cout << x << std::endl;
}
}
2)std::vector的新用法
註:array具備的有點,vector都具備
//向數組中動態添加值
#include <iostream>
#include <vector>
int main()
{
int userId;
std::vector<int>studentId; //定義vector數組
do
{
std::cout << "請輸入學號:";
std::cin >> userId;
if (!userId) break; //如果學號為0,直接退出
studentId.push_back(userId); //向數組中動態的添加值
} while (true); //因為已經有跳出迴圈機制,不需要再利用while的判斷
for (int x : studentId)
{
std::cout << x << std::endl;
}
}