0.前言
1.上一篇文章中荷腊,我們重點(diǎn)講述了:如何main函數(shù)的各個(gè)模塊轉(zhuǎn)化為函數(shù),使得main函數(shù)簡介合理悄窃,利于閱讀、整理蹂窖。
2.今天轧抗,則主要講解c語言中數(shù)組的知識(shí)及其應(yīng)用(包括進(jìn)制轉(zhuǎn)換以及兩個(gè)有趣的游戲)
1.文章目的:
- 闡述數(shù)組的語法、特點(diǎn)等基礎(chǔ)知識(shí)
- 通過例子來探究c語言中數(shù)組的使用方法瞬测、使用思路横媚、注意事項(xiàng)
2.本文主要提及的技術(shù)
2.1數(shù)組
2.1.1數(shù)組基本概念
數(shù)組能夠開辟多個(gè)連續(xù)的空間,每個(gè)存儲(chǔ)空間都能存放一個(gè)類型相同的元素
?
注意事項(xiàng):
(1)此概念僅針對(duì)c語言月趟,在java等語言中灯蝴,同一個(gè)數(shù)組可以存放不同類型的元素
(2)數(shù)組分配的內(nèi)存空間是連續(xù)的,所以如果數(shù)組分配空間較大孝宗,可能會(huì)失敗
(3)靜態(tài)數(shù)組定義時(shí)必須明確知道數(shù)組的大小
2.1.2數(shù)組的優(yōu)缺點(diǎn)
(1)數(shù)組的語法定義較為簡單
(2)由于有索引值穷躁,因此“查找”操作較為輕松
(3)刪除數(shù)組中央的某個(gè)元素較為困難
2.1.3數(shù)組的定義
數(shù)組的定義方式有三種:
(1)初始化里面確定數(shù)組大小
int score[] = {29,13,23,11};
(2)在定義時(shí),明確指定數(shù)組大小
int temp[5]; //沒有立刻分配空間因妇,int默認(rèn)元素為0
(3)在定義時(shí)明確指定數(shù)組大小问潭,且對(duì)數(shù)組進(jìn)行一定的初始化
int temp2[5] = {1,2};
注意:
- 靜態(tài)數(shù)組定義時(shí),不能使用變量
int a[m] = {};//這是錯(cuò)誤的寫法
2.1.4數(shù)組的其他重要知識(shí)
(1)數(shù)組名婚被,這個(gè)變量所占用的內(nèi)存空間中狡忙,存放著數(shù)組首地址(同時(shí)也是第一個(gè)元素的地址)
printf("%p\n", &score[0]);
printf("%p\n", score);
這兩句話的效果相同,其中%p專門用來打印地址址芯,而“&”則是代表取變量的地址
(2)數(shù)組與循環(huán)的關(guān)系較為密切
①一般情況下灾茁, 對(duì)于將某些元素逐個(gè)裝入數(shù)組中的過程,會(huì)使用數(shù)組+循環(huán)的組合
②另外谷炸,如果是兩個(gè)字符串的對(duì)比北专,實(shí)際上也是將字符串放入數(shù)組中,依靠循環(huán)進(jìn)行比較(比如下文中會(huì)提到的猜數(shù)字游戲淑廊,就是這個(gè)道理)
3.技術(shù)的具體應(yīng)用
接下來主要談一談標(biāo)題所提到的數(shù)組的實(shí)際應(yīng)用的思路逗余,具體實(shí)現(xiàn)會(huì)放在下一部分
3.1 應(yīng)用1——進(jìn)制轉(zhuǎn)換
(1)數(shù)組的主要應(yīng)用:記錄計(jì)算結(jié)果,并輸出
(2)程序思路:
該程序的目的是將任意的十進(jìn)制數(shù)季惩,轉(zhuǎn)換為其他進(jìn)制數(shù)录粱,并輸出
如十進(jìn)制中的數(shù)字20腻格,轉(zhuǎn)換為二進(jìn)制形式,為10100
具體算法根據(jù)如下:
由圖可見啥繁,轉(zhuǎn)換結(jié)果為10100
我們要做的菜职,就是把這個(gè)10100放入數(shù)組中。
但是按照這個(gè)算法得到數(shù)字的順序是00101旗闽,(即數(shù)組的第一個(gè)元素放的是數(shù)字的最后一位)因此輸出的時(shí)候必須倒過來輸出(如何倒過來輸出后面再說)
3.2 應(yīng)用2——游戲1·最后誰留下來
效果如圖:
(1)數(shù)組的主要應(yīng)用部分:記錄每個(gè)人的編號(hào)酬核、是否被淘汰
(2)游戲過程:
先輸入一個(gè)淘汰號(hào)碼,每個(gè)人從1開始按順序依次喊出號(hào)碼适室,喊出淘汰號(hào)碼的人便會(huì)被淘汰嫡意,下一個(gè)人從1開始重新喊
該程序的作用便是能夠通過不斷循環(huán)遍歷數(shù)組,逐次找出被淘汰的編號(hào)捣辆,以得出最后的生還者
(3)代碼思路:
①將每個(gè)人的編號(hào)記錄在一個(gè)數(shù)組中蔬螟,然后設(shè)置兩個(gè)變量,一個(gè)記錄數(shù)組下標(biāo)汽畴,一個(gè)記錄喊出的號(hào)碼
②兩個(gè)數(shù)同時(shí)增加旧巾,當(dāng)喊出的號(hào)碼等于淘汰號(hào)碼時(shí),將對(duì)應(yīng)的編號(hào)設(shè)置為' * '(星號(hào))忍些,然后重置喊出的號(hào)碼(賦值為1)鲁猩,
③重復(fù)上述內(nèi)容,當(dāng)檢測到數(shù)組中內(nèi)容為星號(hào)時(shí)罢坝,跳過該次循環(huán)(因>為星號(hào)代表已經(jīng)被淘汰)
3.3 應(yīng)用3——游戲2·猜數(shù)字
先放效果圖:(1)游戲規(guī)則:
①系統(tǒng)會(huì)隨機(jī)生成四個(gè)不同的數(shù)字廓握,玩家需要猜測分別是什么
②玩家允許對(duì)正確答案進(jìn)行猜測,對(duì)于玩家的猜測炸客,系統(tǒng)會(huì)給予一定的反饋
③反饋格式為:mA疾棵,nB
其中m為A的個(gè)數(shù),n為B的個(gè)數(shù)痹仙,A表示位置和數(shù)字都同時(shí)猜對(duì)的數(shù)字個(gè)數(shù)是尔,B表示數(shù)字猜對(duì)了但是位置不對(duì)的數(shù)字個(gè)數(shù)
④玩家一共有10次機(jī)會(huì),需要不斷根據(jù)反饋調(diào)整自己的答案开仰,以找出正確的序列
(2)數(shù)組的主要應(yīng)用:
數(shù)組在這個(gè)程序中拟枚,主要是用來存放兩個(gè)序列(正確序列與猜測序列),然后比較兩個(gè)序列中的值众弓,并返回A與B的個(gè)數(shù)
4.實(shí)際應(yīng)用(具體實(shí)現(xiàn)步驟)
三個(gè)例子恩溅,我們一個(gè)個(gè)分析
4.1進(jìn)制轉(zhuǎn)換的實(shí)現(xiàn)
(1)代碼細(xì)節(jié):
int result[20] = {};
int i = 0;//從第一個(gè)元素開始,而且最后i可以反映數(shù)組中有多少個(gè)元素
逐步分析代碼:
①首先定義一個(gè)數(shù)組result[20]以及變量“i”,這個(gè)變量i十分重要谓娃,不僅可以在下面展示while循環(huán)中起到記錄下標(biāo)脚乡,其最終結(jié)果,還能展現(xiàn)出進(jìn)制轉(zhuǎn)換后的數(shù)字的位數(shù)(因?yàn)槲覀儾恢擂D(zhuǎn)化后的數(shù)字有多少位滨达,可以靠i來獲饶坛怼)
//開始將轉(zhuǎn)換后的數(shù)字按照逆序放入數(shù)組中
while (num != 0) {
result[i] = num % system;//把余數(shù)依次放在數(shù)組中
num /= system;//被除數(shù)要更新為商
i++;
}
這個(gè)while循環(huán)是由輾轉(zhuǎn)相除法得來的俯艰,system指的是進(jìn)制數(shù),num為待轉(zhuǎn)換的數(shù)
result[i]依次裝入num對(duì)system取余的結(jié)果
//開始輸出
printf("該數(shù)字的%d進(jìn)制為",system);
for (i--; i >= 0; i--) {
if (result[i]>=10) {
printf("%c", result[i]+'A'-10);
}
else {
//0到9的數(shù)字直接輸出即可
printf("%d", result[i]);
}
}
printf("\n");
最后輸出即可锌订,需要注意的是竹握,由于數(shù)組中是按照逆序存儲(chǔ)的最終結(jié)果,因此得倒過來輸出
而最終結(jié)果的長度辆飘,就可以看上文所說的變量i
- for循環(huán)中的第一個(gè)i--是因?yàn)樯厦骖~代碼i多++了一次
- if(result[i]>=10)主要是針對(duì)10以上的進(jìn)制啦辐,如十六進(jìn)制,這些進(jìn)制會(huì)出現(xiàn)10以上的一些數(shù)字蜈项,并用大寫字母代替芹关,而printf("")中的result[i]+'A'-10,則是將數(shù)組中大于等于10的數(shù)字紧卒,轉(zhuǎn)化為對(duì)應(yīng)的英文大寫字符(根據(jù)ASCII碼)
4.2游戲1·最后誰留下來
(1)代碼細(xì)節(jié):
int nowNum = 1;//當(dāng)前喊出來的號(hào)碼
int lastNum = 7;//剩余人數(shù)
int totalNum = 7;
int i = 0;
//1.固定7個(gè)人游戲充边,每個(gè)人編號(hào)分別是1到7
char order[7];
for (int i = 0; i < 7; i++) {
order[i] = i + '1';
//printf("%c ", order[i]);
}
①先定義一些變量,然后定義一個(gè)char類型的長度為7的數(shù)組常侦,并逐個(gè)賦值'1','2'贬媒,‘3‘ .......‘7’
使用char類型的主要原因是后面想要通過*星號(hào)來代表被淘汰的人(當(dāng)然用int類型數(shù)組聋亡,然后用0表示淘汰也行)
②然后就是對(duì)結(jié)果進(jìn)行驗(yàn)算:
//2.對(duì)結(jié)果進(jìn)行驗(yàn)算
while (lastNum > 1) {
//此時(shí)喊出號(hào)碼,并判斷是否為死亡號(hào)碼
if (i == totalNum) {
//如果已經(jīng)到頭了,回到開頭
i = 0;
}
if (order[i] == '*') {
//已經(jīng)死亡了,直接下一個(gè)
i++;
continue;
}
else if (nowNum == dieNum) {
order[i] = '*';
lastNum--;//剩余人數(shù)減1
nowNum = 1;
//淘汰一個(gè)人就輸出一次
for (int j = 0; j < 7; j++) {
printf("%c ", order[j]);
}
printf("\n");
}
else {
//否則繼續(xù)喊出號(hào)碼
nowNum++;
}
i++;
}
③其中l(wèi)astNum表示剩余人數(shù)际乘,totalNum表示總?cè)藬?shù)(這里其實(shí)是數(shù)組的長度坡倔,不會(huì)變化,該變量主要用于下標(biāo)到6之后脖含,能夠通過if語句重新回到0)
④nowNum指的是當(dāng)前喊出的號(hào)碼罪塔,dieNum表示淘汰號(hào)碼,當(dāng)二者相同時(shí)养葵,表明該選手被淘汰征堪,則有:
if (nowNum == dieNum) {
order[i] = '*';
lastNum--;//剩余人數(shù)減1
nowNum = 1;
//淘汰一個(gè)人就輸出一次
for (int j = 0; j < 7; j++) {
printf("%c ", order[j]);
}
printf("\n");
}
被淘汰的人用星號(hào)表示,下一次星號(hào)关拒,則只能下標(biāo)++佃蚜,nowNum(喊出的號(hào)碼)不會(huì)變化,即:
else {
//否則繼續(xù)喊出號(hào)碼
nowNum++;
}
另外着绊,淘汰號(hào)碼可以通過手動(dòng)輸入的方式進(jìn)行更改:
printf("請(qǐng)輸入淘汰號(hào)碼:");
scanf_s("%d", &dieNum);
whoDie(dieNum);//淘汰游戲函數(shù)
4.3游戲2·猜數(shù)字
(1)代碼細(xì)節(jié):
int correctOrder[4];//放正確答案
int guessOrder[4];//放猜測的
srand((unsigned)time(NULL));//用來生成隨機(jī)數(shù)的種子
int num = 0;
int numA = 0;
int numB = 0;
int totalTime = 10;//總共10次機(jī)會(huì)
①先定義變量
②然后下面開始制作正確的序列:
//1.準(zhǔn)備好正確的數(shù)組序列
for (int i = 0; i < 4; i++) {
num = rand() % 10;//0到9隨機(jī)取一個(gè)
for (int j = 0; j < i; ) {//保證四個(gè)數(shù)字不重復(fù)
if (num == correctOrder[j]) {
num = rand() % 10;
j = 0;
}
else {
j++;
}
}
correctOrder[i] = num;
//printf("%d ", num);//測試用谐算,打印看一下
}
其中
for (int j = 0; j < i; ) {//保證四個(gè)數(shù)字不重復(fù)
if (num == correctOrder[j]) {
num = rand() % 10;
j = 0;
}
else {
j++;
}
}
該for循壞主要效果是,將前面已經(jīng)定好的數(shù)字與這次隨機(jī)數(shù)產(chǎn)生的數(shù)字進(jìn)行比較归露,如果有相同的洲脂,則重新去隨機(jī)數(shù)
③獲取猜測序列:
//3.輸入猜測序列
printf("輸入你的猜測序列:\n");
while (site != 4) {
scanf_s("%d", &num);
guessOrder[site] = num;
site++;
}
這里雖然是循環(huán)4次,每次只獲取1個(gè)剧包,但是可以一次性輸入四個(gè)(中間要有一個(gè)空格)
④計(jì)算A和B的數(shù)量:
numA = numB = 0;//重新從零計(jì)算
for (int m = 0, j = 0; m < 4; m++) {
if (correctOrder[m] == guessOrder[m]) {
//看看有沒有A
numA++;
}
else {
//看看有沒有B
j = 0;//重新從頭比較
for (; j < 4; j++) {
if (m == j) {
//沒有A恐锦,所以i和j相同的時(shí)候跳過
continue;
}
else if (correctOrder[m] == guessOrder[j]) {
numB++;
break;//B數(shù)目+1之后就退出循環(huán)
}
}
}
}
printf("%dA往果,%dB\n\n", numA, numB);
計(jì)算思路為:
將兩個(gè)序列(正確的與猜測的)對(duì)齊,然后先看第一個(gè)下標(biāo)的元素踩蔚,將正確的元素與猜測的相比棚放,如果正確,則numA++
如果不正確馅闽,則開始找有沒有B飘蚯,方法就是講正確的第一個(gè)下標(biāo)元素,以此與猜測序列后面的數(shù)字相比較福也,有相同的則numB++并停止循環(huán)
后面的同理局骤,先比較相同位置,看有無A暴凑,沒有的話再看有無B
⑤最后判斷是否達(dá)成結(jié)束游戲的條件
//5.判斷是否結(jié)束游戲
if (numA != 4) {
totalTime--;
if (totalTime == 0) {
printf("機(jī)會(huì)已經(jīng)用光\n");
exit(EXIT_FAILURE);
}
else {
//機(jī)會(huì)還沒有用光峦甩,但是還沒有正確
printf("還有%d次機(jī)會(huì),請(qǐng)繼續(xù)", totalTime);
}
}
先用if判斷numA有沒有4個(gè)(有就證明已經(jīng)猜對(duì)了)
然后在讓totalTime--,并判斷機(jī)會(huì)用光了沒有
⑥
從第③步到第⑤步现喳,是個(gè)循環(huán)(畢竟有多次機(jī)會(huì))凯傲,需要用while套在外面,循環(huán)條件則是numA != 4
while (numA != 4) {
site = 0;//每次重新賦值
//3.輸入猜測序列
printf("輸入你的猜測序列:\n");
while (site != 4) {
scanf_s("%d", &num);
guessOrder[site] = num;
site++;
}
//4.下面開始計(jì)算A和B的個(gè)數(shù)
numA = numB = 0;//重新從零計(jì)算
for (int m = 0, j = 0; m < 4; m++) {
if (correctOrder[m] == guessOrder[m]) {
//看看有沒有A
numA++;
}
else {
//看看有沒有B
j = 0;//重新從頭比較
for (; j < 4; j++) {
if (m == j) {
//沒有A嗦篱,所以i和j相同的時(shí)候跳過
continue;
}
else if (correctOrder[m] == guessOrder[j]) {
numB++;
break;//B數(shù)目+1之后就退出循環(huán)
}
}
}
}
printf("%dA冰单,%dB\n\n", numA, numB);
//5.判斷是否結(jié)束游戲
if (numA != 4) {
totalTime--;
if (totalTime == 0) {
printf("機(jī)會(huì)已經(jīng)用光\n");
exit(EXIT_FAILURE);
}
else {
//機(jī)會(huì)還沒有用光,但是還沒有正確
printf("還有%d次機(jī)會(huì),請(qǐng)繼續(xù)", totalTime);
}
}
}
printf("恭喜你猜對(duì)了灸促!\n");