寫程式偶爾會遇到需要儲存大量資料
而且資料類型又相同的情況
這個時候就輪到陣列登場了!
本課將介紹陣列的基本使用方式
以及解答一些關於陣列的常見問題
教學影片
注意:影片有高畫質 720P 的選項,可以看得更清楚喔!
重點提示
1. 陣列通常用來存放大量類型相同的資料,如 1000 個整數等等
2. 陣列的宣告方法如下,例如要宣告可以存放 40 個整數的陣列,名為 intArray:
int[] intArray = new int[40];
或是如果預先知道要存入的數值,也可以用下面的方式宣告:
(假設要預先存入 92, 83, 100)
int[] intArray = new int[] {92, 83, 100};
3. 如果要存取陣列內的資料,則需要打「陣列名稱 [ 編號 ]」
例如要存取整數陣列 scores 編號 3 的資料:
scores[3] = 100; // 在編號 3 的位置存入 100
4. 陣列的編號是從 0 開始算起,因此如果陣列大小為 40 ,則可以用的編號是 0 ~ 39
5. 陣列一開始會將每個位置的資料填上預設值,預設值則跟每一格存放的資料型別有關。不同型別的預設值請參考「相關資訊連結」的「預設值表」
6. 如果使用了範圍外的編號,只有在程式執行時才會發現錯誤。因此要特別注意
7. 除了 int, double 這些基本型別,也可以建立物件陣列。只需要將型別名稱替換成 class 名稱即可,例如要宣告大小 20 的 Student class 的陣列可以寫:
Student[] students = new Student[20];
8. 陣列的大小是固定的,在宣告的時候就要決定
9. 陣列也是一種物件
補充
Class 的預設值
基本上,所有 Value Type 的變數的預設值都可以在相關連結的「預設值表」中找到。那麼 Reference Type(指向物件的變數) 的預設值又是甚麼?
所有 Reference Type 的預設值都是 null,也就是說,如果你一開始宣告了一個變數 object,然後還沒有用 new 來產生任何物件。那這個 object 裡面存的值就是 null。因此我們在寫程式的時候,常常可以使用下列這個判斷式來比對 Reference Type 的變數是否有指向任何物件。
if (object == null) // 如果 object 沒有指向任何物件,這個判斷式就會成立
另外,string 其實也是一個 class,所以它預設值也是 null。
Value Type 的陣列與 Reference Type 陣列的結構
在看這個條目之前,請先注意是否理解 Value Type 與 Reference Type 這兩種變數的差別。如果不了解的話,可以先去看「小山的 C# 教學-第16課-Value 與 Reference Type」。
在本課的教學中,我們了解到陣列儲存整數的方法是像下面這張圖。
而我們也學過,當我們建立物件的時候,物件的本體是放在一個名為 Heap(堆疊) 的物件海。然後我們物件的變數也只有紀錄物件本體的位置的而已,這些變數就稱為 Reference Type 的變數。
那這些 Reference Type 的陣列實際上的結構是長甚麼樣子呢?實際上,Reference Type 的陣列裡面所存的,只是一群「指向物件本體」的位址而已。如果我們有一個 class Student,然後我們建立了 Student 的陣列。再用下列的程式碼一一地建立物件,並利用陣列來儲存。
Student[] students = new Student[20];
students[0] = new Student(10001, 小山);
students[1] = new Student(10002, 小羊);
students[2] = new Student(10003, 元正);
students[3] = new Student(10004, 高光);
....
那這些東西實際儲存的狀態就會像下面這張圖(箭頭代表我們可以透過位址去找到被指向的物件)
動態陣列
本課教學提到陣列是固定大小的,而且必須要在宣告時就決定大小。事實上,也有不需要事先指定大小,並且可以動態改變大小的陣列。
在 System.Collectioins 這個 namespace 下有一個 class 叫做 ArrayList。它本身的結構與陣列很類似,但是具有自行動態調整大小的特性。當然使用方法上會有些不同。關於這部分的介紹有網友製作了簡單的說明,有興趣的可以點進去參考。
相關資訊連結
微軟官方(MSDN) 對於陣列的簡介
http://msdn.microsoft.com/zh-tw/library/9b9dty7d%28v=vs.80%29.aspx
MSDN 的 Array class 參考資料
http://msdn.microsoft.com/en-us/library/system.array.aspx
C# Value Type 的預設值表
http://msdn.microsoft.com/zh-tw/library/83fhsxwc%28v=vs.80%29.aspx
某位網友對於 ArrayList 使用方法的簡單說明
《[C#.NET][VB.NET] 一般集合 - ArrayList 類別 排序》
http://www.dotblogs.com.tw/yc421206/archive/2009/01/21/6902.aspx
小山您好:
回覆刪除近期跟著您的腳步學習C#
在這裡我有一個比較複雜的程式想請教您 不是請教您他的內容
而是程式架構部份
不知是否願意以讓我已寄信的方式向您詢問
我的信箱 redonizuka@gmail.com
沒問題,請寄信到以下信箱
刪除sam123456777@gmail.com
小山您好:
回覆刪除有一個程式碼不太懂意思想請教您
if ((x[i] & 0x80) == 0x80) 上面有個FOR迴圈就沒寫出來了
這句話的意思是我要進入if的話 我x的第i項要是 0x80和我&後面的0x80都要是0x80才能進入嗎
那我有問題是&後面就己經是0x80了 為何還要&判斷
這有點牽涉到邏輯設計的概念
刪除在這之前,我先解釋一下「&」的意義
在 C# 中,「&&」、「&」分別有不同意義
注意:以下說的「true」代表「成立」、「false」代表「不成立」
「&&」代表是,如果符號前後都是 true,就是 true,如果前後有一個是 false,那整個式子就是 false
「&」比較特別,我們稱之為「位元運算子 Bitwise operator」
他必須要配合數字或者可以存數字的變數使用
首先必須要把符號前後的數字拆成二進位
然後進行「AND 運算」
你可以參考下面那個網址左上角的表,如果看不懂可以再問我
http://www.csie.nctu.edu.tw/~skyang/figures/bitwiseops.gif
舉例來說:
假設 A = 00101, B = 11001
00101 <-- 這是 A
11001 <-- 這是 B
-----
00001 <-- 結果
因此 A & B = 00001
那閣下所問的 0x80 是八進位表示法
所以必須先把 0x80 轉換為二進位,也就是 10000000(二進位)
然後再跟 x[i] 進行上面說的 AND 運算
最後在看結果是否等於 0x80
我相信這應該不太好懂
如果有問題歡迎再問~
如果說同樣長度的話我就懂
刪除比方說 A=00011 B=11010 在去& 在去比較
但現在他是x[i] 但i隨著FOR為 1 2 3
假如他現在是x[1]的話 要怎麼跟0x80去&
首先,如果長度不一樣的話
刪除會藉由補 0 將短的先變得跟長的一樣長
例如:
a = 1001
b = 1110001
如果做 a & b
就會先把 a 變成 00001001 (左邊補四個 0)
然後再做 & 運算
如果你的 x[i] 是 int 陣列
那 x[1] 裡面自然就會存著一個 int 數值
所以就是拿那個 int 數值去跟 0x80 做 &
另一個新問題
回覆刪除針對位元組的部份
byte[] a = new byte[b]
這個意思是說我將b以位元形式放到a位元矩陣 這樣嗎
位元是不是無法以Message.show show出來
首先,在 C# 中 byte 跟 int 都是代表整數
刪除唯一的差別是在 byte 只能存 0 到 255 的整數
(因為 byte 儲存空間是 1 byte = 8 bit = 255 種組合)
int 則可以存 -2,147,483,648 至 2,147,483,647
(int 儲存空間是 4 byte = 32 bit = 2 的 32 次方種組合)
就你的例子來看
假設 b = 20
byte[] a = new byte[b];
只是代表建立一個可以「分別」存放 20 個 byte 數值的陣列而已
因為 byte 也是一種整數
所以同樣也能夠顯示出來
假設你宣告 byte a = 10;
只要打 MessageBox.Show("" + a); 就可以顯示了
如果你指的是用「二進位」的方式顯示 a
就打 MessageBox.Show(Convert.ToString(a, 2));
打錯了,byte 是 2 的八次方 => 256 種組合
刪除感謝您 目前有詢問您的問題全都了解了
回覆刪除另一新問題
a[0] <<= 1 這個是位移運算子吧 就是將我的位元往左移一個單位
沒錯~
刪除小山老師 我想請教一下
回覆刪除例如說
student student1 = new student(); //第一個學生
如果有60個學生
並且使用for編寫
請問student1~student60 數字與文字組成的新名稱該如何組合?
for(int i = 0; i < 60; i++)
{
student ????? = new student();
}
?????這邊該如何編寫?
作者已經移除這則留言。
回覆刪除你這個問題正契合了陣列存在的目的
回覆刪除陣列就是為了要儲存「大量且同型別」的資料而存在的
因此你這個問題應該要用陣列編寫如下:
Student[] students = new Student[60]; // 先宣告一個可以存放 60 筆資料的陣列
for (int i = 0; i < 60; i++)
students[i] = new Student(); // 一個一個地建立學生物件,注意左側的 i 會隨 for 改變
您好,請問一下
回覆刪除請建立c#應用程式宣告5個元素的一為陣列後,使用亂數類別來產生陣列的元素值,其範圍是1~200的整數,然後將陣列內容排序後,顯示在標籤控制項。
這要怎麼做?我在標籤上都只能顯示一個數值,要如何同時顯示5個數值且不重複?
我有不太懂顯示一個數值的意思,是指你有一個標籤(Label)
刪除然後你想一次塞入五個數值嗎?
像是 "1 2 5 8 10" 這樣嗎?
關於不重複的部分
我大概想到兩種做法:
1. 你有建立陣列(Array)對吧,那當你亂數產生一個數字的時候
先檢查一下陣列裡是否已經存在一樣的數值
如果有的話,就重新產生一個新的數值
如果沒有,就把這個數值存進陣列
一直到塞滿五個為止
2. 你可以把 1~200 切成五段
分別是 1~40, 41~80, 81~120, 121~160, 161~200
然後每一段各自產生一個數字
這樣就能夠保證不重複了
作法一的缺點是,每次都要搜尋陣列很耗時間
但是你只需要產生五個,所以其實也還好
作法二的缺點是,產生出來的數字並非真的亂數
同一個區間的數字無法同時出現
如果想要用上述的做法,可能需要斟酌一下
小山你好 , 我剛好跟joe有相同的問題
刪除我問題是不知道怎麼去『一次和陣列裡全部的數字做比較』
int random_number;
int[] NumberArr = new int[2];
for (int a = 0; a< 2; a ++)
{
bool key = false ;
random_number = Random.Range (1, 3);
if(key == false)
{
for(int d = 0; d<NumberArr.Length ; d++)
{
if(NumberArr[d] == random_number)
{
random_number = Random.Range (1, 3);
}
}
}
NumberArr [a] = random_number;
key = true ;
我發現我這樣比較NumberArr[1]的時候會有機會出現跟Number[0]的數字(重複)
我在猜是因為一開始NumberArr[1]也沒設數值的關係所以以沒法判斷
請教一下要怎麼跟全部的數字作判斷呢? (假設有10個好了)
一般來說,在不借助其他資源的情況下
刪除應該是每次得到一個數字之後
就要使用一個 for 迴圈依序檢查陣列中的所有數字
不過我這裡提供一個更快速的解法:
在 C# 中有一種資料結構叫做 HashSet
所謂資料結構就是一種可以幫你有效率保存大量資料的物件
Set 就是一種資料結構
Set 的特點在於裡面所有的值都「不會重複」
HashSet 的則是一種查詢速度很快的 Set
所以如果你今天想要得到一群不重複的亂數 (假設 10 個)
只要這樣寫就可以了:
HashSet numbers = new HashSet();
while (numbers.Count < 10) {
numbers.add(Random.Next());
}
你好,想請問小山大大
回覆刪除(1) 第一天存10元,第二天存20元,第三天存30元,依此類推。
(2) 當存款達到5000元後,再回到(1)的存錢方式,繼續存錢。
(3) 請問小新存錢到第幾天,他的存款會達到20000元?
(4) 若依此方式繼續存下去,到第50天時,小新會有多少存款?
我知道這麼不知廉恥的問作業題目很不好
但老師教的我實在無法理解
(1) 第一天存10元,第二天存20元,第三天存30元,依此類推。
這題是用While就可解決,但是要讓它停在5000後再重複執行,這我就完全不能明白了
是使用IF跟FOR搭配陣列去解題嗎?
可煩請小山大大幫忙解惑嗎? 感謝你
Hello, 我想先確認一下
刪除(2) 的 5000 是指說「單次存下去的錢 5000」
還是「存款總共有 5000」?
用兩個while+一個if即可解決
刪除public int cash=0 , day=0, reset, total, cash1;
while (cash < 5000)
{
day++;
cash += 10 * day;
}
while (cash <= 20000)
{
reset++;
cash += 10 * reset;
total = day + reset;
if (total == 50)
{
cash1 = cash;
}
}
MessageBox.Show("到第 " + total + " 天,存款達到20000元\r\n" + "第50天時,有 " + cash1 + "存款");
作者已經移除這則留言。
回覆刪除請問前兩則是不是寫錯了@@
回覆刪除int intArray = new int[40];
int intArray = new int[] {92, 83, 100};
前面應該是int[] intArray ?
(還是這是為了測試大家有沒有專心看影片,故意打錯的@@?)
抱歉,應該是我寫錯了XD
刪除感謝指正
小山老師 我想請教一下 若一共有24個物件 分三段選 然後要判斷使用者是否依照順序選出正確的物件七個 12個 五個 就判斷對還錯 對就會顯示一張圖片 要寫c#要怎麼寫
回覆刪除感謝小山老師的指導,老師做的教學很棒,潛顯易懂,讓我這個第一次接觸語言的也能聽懂。期待新作品 謝謝
回覆刪除