2016年5月4日 星期三

給新手的C++教學 (上冊) - 6. 陣列 (Array)

回到「給新手的C++教學 (上冊)」

上一章

不知你有沒有想要實現過以下這件事,卻遇到阻礙呢?
輸入一個整數n,然後輸入n個數字
最後把這n個數字的順序顛倒,然後輸出

例如:輸入「4 24 5 105 411」,輸出為「411 105 5 24 」(注意:每個數字後面都有空格,最後一個數字也一樣)

你可能有想過要做類似以下的事情:
如果n是1就宣告 a,輸入 a,輸出 a (「宣告」是「定義變數」的專業說法)
如果n是2就宣告 a、b,輸入 a、b,輸出 b、a
如果n是3就宣告 a、b、c,輸入 a、b、c,輸出 c、b、a
如果n是4就宣告 a、b、c、d,輸入 a、b、c、d,輸出 d、c、b、a
......
然後你就會發現沒完沒了XD

事實上,我們可以直接指定一個整數n,讓電腦一次幫我們宣告n個變數!(並非任何情況都可行,見註7)
這就是「陣列 (Array)」的好用之處

用法如下 (假設你想宣告n個int變數、陣列的名稱取作「array_name」):
int array_name[n];

這樣一來電腦就幫你把n個變數命名為array_name[0]、array_name[1]、array_name[2]、......、array_name[n-1]了!
(心理偷偷的想:耶~小中大括號都用到了耶 \(^o^)/ )

請注意,第1個變數是array_name[0] (而不是array_name[1]),第n個變數是array_name[n-1] (而不是array_name[n])
不知你在第一次看到本教學時,有沒有注意到有一章叫做「0. 目錄 (Catagories)
這就是暗示了
中括號 (「[」和「]」) 裡面的數字,我們叫做「索引值 (Index)」
有別於數學上常見的正整數系統
陣列的「索引值」是從「0」開始的
也就是說:
索引值為0時代表第1個變數
索引值為1時代表第2個變數
索引值為2時代表第3個變數
索引值為3時代表第4個變數
索引值為4時代表第5個變數
......
以此類推
至於原因,之後的進階章節會講到 (建議你不要現在就直接看它),目前你只要記住有這個現象即可

因此
「輸入一個整數n,然後輸入n個數字
最後把這n個數字的順序顛倒,然後輸出」
這個問題就迎刃而解了:

#include<cstdio>
int main()
{
    int n;
    scanf("%d",&n);
    int a[n];
    int i=0;
    while(i<n)
    {
        scanf("%d",&a[i]);
        i=i+1;
    }
    i=n-1;
    while(i>=0)
    {
        printf("%d ",a[i]);
        i=i-1;
    }
    printf("\n");
}
 

←「i」要從0開始跑,因此先把i設定成0
←「i」會從0跑到n-1

    (這樣會讓程式照順序輸入a[0]~a[n-1])


←「i」要從n-1開始跑,因此先把i設定成n-1
←「i」會從n-1往回跑到0

    (這樣會讓程式倒序輸出a[n-1]~a[0])

那個「printf("\n");」可加可不加,因為題目沒有強制要求輸出格式
但這不代表「加」和「不加」的效果相同,建議讀者測試看看兩種情況的差異

好了,陣列講完了(?)


現在,給你一個練習題:
給你n個介於1和10的整數,請你統計每個數字的數量
輸入:一個整數n和n個介於1到10之間的整數
輸出:10個數字,第i個數字代表數字i的數量
例如:輸入「15 5 6 6 3 7 4 1 7 6 2 8 5 1 10 4」,要輸出「2 1 1 2 2 3 2 1 0 1」

警告:有個意外簡單的方法

提示:請善用陣列

參考解答:

#include<cstdio>
int main()
{
    int a[11];
    int i=1;
    while(i<=10)
    {
        a[i]=0;
        i=i+1;
    }
    int n;
    scanf("%d",&n);
    i=0;
    while(i<n)
    {
        int v;
        scanf("%d",&v);
        a[v]=a[v]+1;
        i=i+1;
    }
    i=1;
    while(i<=10)
    {
        printf("%d\n",a[i]);
        i=i+1;
    }
    return 0;
}

欲罷不能?
還是想雪恥?
再給你一個挑戰題:
給你n個整數,請你把這n個整數由小到大輸出
輸入:一個整數n和n個整數
輸出:由小到大的n個整數
例如:輸入「5 24 5 105 411 87」,要輸出「5 24 87 105 411 」

警告:挑戰性極高,考驗邏輯能力,做得出來堪稱天才 (?)

提示:每次找出最小的數字,然後把這個最小的數字拿掉

參考解答:

#include<cstdio>
int main()
{
    int n;
    scanf("%d",&n);
    int a[n];
    int i=0;
    while(i<n)
    {
        scanf("%d",&a[i]);
        i=i+1;
    }
    i=0;
    while(i<n)
    {
        int j=i,minimum=i;
        while(j<n)
        {
            if(a[j]<a[minimum])
            {
                minimum=j;
            }
            j=j+1;
        }
        printf("%d ",a[minimum]);
        a[minimum]=a[i];
        i=i+1;
    }
    printf("\n");
    return 0;
}

感覺已經可以完全掌控電腦了,對吧?
的確如此喔~ ^_^

接下來的章節教的東西,利用這6章所學也可以弄出來
只是,它們可以把一切變的更簡單、更好寫、更好想!

下一章

感謝:uzk、栢淵
(版權所有 All copyright reserved)

3 則留言:

  1. #include <iostream>
    using namespace std;
    int main()
    {
        int A[10]={1,2,3,4,5}, B[10];
        for (int i=0;i<10;i++)
            A[i]=B[i];
            
        cout<<B[1];
    }

    請問一下
    我要複製A陣列到B
    輸出B[1]=2
    但結果為何是0呢??

    回覆刪除
    回覆
    1. 啊啊我知道了
      我寫反了
      是B[i]=A[i]

      刪除
    2. 哈哈恭喜您自行解決問題 ^_^
      加油~~~

      刪除

歡迎留言或問問題~
若您的留言中包含程式碼,請參考這篇
如果留言不見了請別慌,那是因為被google誤判成垃圾留言,小莫會盡快將其手動還原