2016年5月8日 星期日

給新手的C++教學 (上冊) - 7. 讓程式碼看起來更簡單 (Simplify the code)

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

上一章

上一章有提到,利用前6章所學,已經可以完全掌控電腦了

現在,我想問你,能否寫出一個程式,完成以下任務呢?
輸入一個字元,請判斷這個字元是不是「小寫母音字母 (a、e、i、o、u)」,是的話輸出「Yes」,否則輸出「No」(甚麼是字元?複習一下第2章吧~)

題外話:
怎麼表示「一個字元 (charactor),代表小寫字母『a』」呢?
不知道沒關係,因為之前的章節沒有提到XD
答案是「'a'」(用兩個「'」框住你想表達的字元)
這個表示法雖然是隨手提及,但是非常重要,之後的教學只要看到兩個「'」框起來的東西,你都要把它當作「一個字元」來看待

參考解答:

#include<cstdio>
int main()
{
    char a;
    scanf("%c",&a);
    if(a=='a')
    {
        printf("Yes\n");
    }
    else
    {
        if(a=='e')
        {
            printf("Yes\n");
        }
        else
        {
            if(a=='i')
            {
                printf("Yes\n");
            }
            else
            {
                if(a=='o')
                {
                    printf("Yes\n");
                }
                else
                {
                    if(a=='u')
                    {
                        printf("Yes\n");
                    }
                    else
                    {
                        printf("No\n");
                    }
                }
            }
        }
    }
    return 0;
}

你可能會發現:程式好冗長啊
有沒有簡單一點的寫法呢?
會這樣問,答案當然是「有」啊

可以發現,有很多的大括號 (「{」和「}」) 包起來的部分都只有一行程式碼 (「printf("Yes\n");」或「printf("No\n");」)
在這種情況下,大括號其實是可以省略的

所以,程式碼也可以這樣寫,完全不影響程式的功能:

#include<cstdio>
int main()
{
    char a;
    scanf("%c",&a);
    if(a=='a')
        printf("Yes\n");
    else
    {
        if(a=='e')
            printf("Yes\n");
        else
        {
            if(a=='i')
                printf("Yes\n");
            else
            {
                if(a=='o')
                    printf("Yes\n");
                else
                {
                    if(a=='u')
                        printf("Yes\n");
                    else
                        printf("No\n");
                }
            }
        }
    }
    return 0;
}

另外,一個「if」和一個「else」是配對起來的,不可分離
因此,我們甚至也可以省略將它們包起來的大括號!
廣泛的說,如果大括號裡面包起來的程式碼是不可分離的
那麼這個大括號就可以省略

這樣一來,程式碼又可以簡化成以下這樣了:

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");」可加可不加,因為題目沒有強制要求輸出格式
但這不代表「加」和「不加」的效果相同,建議讀者測試看看兩種情況的差異

好了,陣列講完了(?)

2016年5月3日 星期二

給新手的C++教學 (上冊) - 5. 迴圈 (Loop)

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

上一章

有時候,你希望某部分的程式碼重複執行3次
利用前四章所學,你可能會選擇把程式碼複製成3倍

但是,如果你希望這部分的程式碼執行500次呢?
如果你可以很有有耐心的進行「複製、貼上」的動作,這可能還不成問題
如果你希望這部分的程式碼是永遠的重複執行下去,直到我們手動把程式關掉呢?
亦或者你可以做到「輸入一個數字,這個數字是多少,程式就會重複執行多少次」嗎?

別擔心,以上的問題可以用一個很輕鬆的方法一次搞定!
換句話說,我們又有新朋友要認識啦~

它就是「while (當......的時候)」
用法如下:

while(繼續重複執行的條件)
{
    需要被重複執行的程式碼
}

因此,就算你不是高斯,你也可以輕鬆地寫出一個程式來計算「1+2+3+......+100」的結果!

#include<cstdio>
int main()
{
    int answer=0;
    int a=1;
    while(a<=100)
    {
        answer=answer+a;
        a=a+1;
    }
    printf("%d\n",answer);
    return 0;
}

程式輸出「5050」了!
你可能會對「=」的用途感到陌生 (雖然說之前有用過「int a=1;」之類的東西)
千萬別和「==」搞混了
「=」的作用是把左邊變數的值「設定成」右邊的數字
「==」是「判斷」左邊的數字和右邊的數字有沒有相等
雖然奇怪,但是習慣了就好,以後會很常用到的 ^_^

這種會被重複執行的程式碼,我們稱作「迴圈 (loop)」
還有另一種迴圈叫做「for」,雖然說「while」迴圈已經可以實現「for」迴圈的所有功能
但是「for」迴圈的獨特寫法,讓我們能夠更容易了解這個迴圈執行的事情
之後的進階章節將介紹這種神奇迴圈的用法 (但還是建議先照著順序讀完本教學)

當while中「繼續重複執行的條件」永遠成立時,程式就會永遠的重複執行下去直到天荒地老
這種情況我們稱之為「無窮迴圈 (infinite loop)」
當然,這不會太常用到,畢竟我們通常會希望程式會自己判斷甚麼時候要自己結束,而不是依賴使用者自己去按右上角的「X」按鈕來關閉程式
當你學會了怎麼製作「表單 (Form)」後,你可能會發現,當你的程式進入「無窮迴圈」時,有時候會導致程式「停止回應」(雖然說導致程式「停止回應」的原因不一定是如此)
因為這時程式已經不會再理會使用者的操作,而是專注於重複執行某一段程式碼
使用「多線程 (multithreading)」技術可以避免程式因此停止回應,但這已經遠遠超出本教學的範圍
「表單就是外觀有設計過的程式,而不是單純的「輸入和輸出文字」
相對於「表單」,這種看起來只有黑色背景、上面只會顯示文字的程式,我們稱作「終端機 (Terminal)」
這種程式比較容易製作,也就是我們現在使用C++寫的程式
當然,用C++也可以寫出「表單」

以下程式碼可以讓你體驗一下「無窮迴圈」:

2016年5月1日 星期日

給新手的C++教學 (上冊) - 4. 條件判斷 (Decision making)

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

上一章

利用前三章提到的知識,我們已經可以寫出自己的計算機了!
但是,其實我們的程式還可以變得更強!
在本章,我們將賦予程式「判斷、決策」的能力,讓程式也可以像人一樣思考!

先來講個簡單的例子:
輸入一個數字,如果這個數字是2的話輸出「Yes」,不是的話輸出「No」

這裡請出我們的新朋友,「if (如果)」
用法如下:

if(條件)
{
    條件成立時要執行的程式碼
}

所以,程式碼可以這樣寫:

#include<cstdio>
int main()
{
    int n;
    scanf("%d",&n);
    if(n==2)
    {
        printf("Yes\n");
    }
    if(n!=2)
    {
        printf("No\n");
    }
}

趕快試試看吧! :)

你可能會發現另外兩個新朋友:「==」和「!=」
其中
「==」的作用是判斷左邊是不是「等於」右邊
「!=」的作用是判斷左邊是不是「不等於」右邊
類似的用法還有:
「<」的作用是判斷左邊是不是「小於」右邊
「>」的作用是判斷左邊是不是「大於」右邊
「<=」的作用是判斷左邊是不是「小於或等於」右邊
「>=」的作用是判斷左邊是不是「大於或等於」右邊

你可能還會發現:『「==」成立』不就是『「!=」不成立』嗎?
只要其中一方成立,另一方就會不成立
反之亦然
只要其中一方不成立,另一方就會成立

給新手的C++教學 (上冊) - A. 補充資料 (Additional materials)

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

上一章 (這要怎麼定義上一章啦喂)

本教學以「容易理解」為目標,因此對某些觀念進行了簡化
以下提供更正確、更詳細的資訊供讀者們參考
但還是建議新手們先看懂教學內文的解說
(我們學物理時也是先學錯誤但簡單的牛頓力學,沒有一開始就在教量子力學的對吧?)

(注意:註釋的編號並不代表在教學中出現的順序)

註1:(感謝pr3pony)
int 在標準中只規定至少要 2 bytes
雖然幾乎所有編譯器實作依據的標準都是 ILP32 或 LP64
也就是常見的 4 bytes

註2:(感謝pr3pony)
float 的底數其實是 2 不是 10
因此事實上在儲存 float 前,並沒有「轉成二進位」的這個操作
一切都是直接以「二進位」的模式處理
並沒有牽涉到任何「二進位和十進位互相轉換」的操作 (除非要輸出給我們看)
因此,「24005」應該會被轉換成「$(1.01110111000101)_2*2^{14}$」(二進位版的科學記號)
其中「$(1.01110111000101)_2=(1.46514892578125)_{10}=1.46514892578125=\frac{24005}{2^{14}}$」
詳細資料

註3:(感謝pr3pony)
其實 C++ 並無規定負數的實作方法
常見的方法有三種:two's complementone's-complementsign-magnitude
第三篇提到的方法屬於「two's complement」(感覺也是最常見的方法(?) )

註4
電腦學過C++,很聰明地解決了這個問題
電腦會在字串的後面補上一個特殊字元「'\0'」,這個特殊字元我們稱作「結束字元」,對應到的數字是「0」
這樣就可以知道這個字串的結尾在哪裡了
p.s. 「結束字元 ('\0')」也是一種「隱藏字元」
關於結束字元的中文資料(維基百科)
原文詳細資料

註5:(感謝李旺陽學長)
這個規則是C++被定義明確的標準規範
詳細資料

註6
事實上,以現代的觀點來看,「float」的誤差太大
因此一般計算我們會習慣使用增強版float--「double」
除非記憶體不足或使用到GPU運算,不然float很少會被用到
但是因float的輸出入單純許多,本教學以「float」作為新手們學習浮點數的進入管道

註7:(感謝uzk)
實際上,在C++的標準裡面
「int a[n];」裡面的「n」只能是常數 (而非變數)
這裡我們能夠使用一個變數來當作陣列的長度
是因為我們的編譯器是GCC
當使用的編譯器非GCC時 (雖然這種情況較少見),宣告陣列時不能使用變數當作長度

註8:(感謝李旺陽學長)
宣告的部分跟語法解析有關
有逗點的用的是這條
decl-specifier-seq init-declarator-list;
重點在 * (or & && etc) 是一個 Declarators 不是 Specifiers
 int * p ;
被解析為
Specifiers : int
Declarators : *p (Pointer declaration)
int * p , q;
被解析為
Specifiers : int
Declarators : *p (Pointer declaration) , q ((int var) Names declaration)
以哲學觀點

註9 (全範圍)
其實,C++在「#include<cstdio>」之後
一定會將「printf」放入「std」命名空間
卻不一定會將「printf」放入全域命名空間
(C則是完全相反)
因此,最好的寫法是把全部的「printf」改成「std::printf」
或者每次include完之後加上一行「using namespace std;」
資料來源

註10:(感謝李旺陽學長)
C++小數的捨去有更精確的定義是「Round towards zero (向0靠攏)」
超級超級超級詳細的資料 (第99頁 (頁碼85),Floating-integral conversions)

註11:(感謝奕均的留言)
「\」後面接甚麼會發生甚麼事
來解答囉~
「\a」聲音 (例如:printf("123\a456");)
「\b」退格鍵 (例如:printf("123\b456");)
「\e」ASCII碼是27 (16進位:1b),在黑色視窗會顯示一個向左的箭頭,我也不知道為甚麼XD
「\f」ASCII碼是12 (16進位:0c),在黑色視窗會顯示一個女生的符號,我也不知道為甚麼XD
「\n」你知道的
「\r」類似鍵盤上的「Home」鍵 (例如:printf("1234\r56");)
「\t」類似鍵盤上的「Tab」鍵 (例如:printf("123\t456");)
「\u」後面加4位數的16進位數字,會變成該Unicode碼對應到的字元 (例如:printf("\u001b");)
「\v」ASCII碼是11 (16進位:0b),在黑色視窗會顯示一個男生的符號,我也不知道為甚麼XD
「\x」後面加2位數的16進位數字,會變成該ASCII碼 (或Unicode碼) 對應到的字元 (例如:printf("\x1b");)
「\E」和「\e」的效果一樣
「\U」後面加8位數的16進位數字,會變成該Unicode碼對應到的字元 (例如:printf("\U0000001b");)
「\%」和「%」的效果一樣
「\(」和「(」的效果一樣
「\[」和「[」的效果一樣
「\{」和「{」的效果一樣
「\\」會輸出「\」 (例如:printf("123\\456");)
「\'」和「'」的效果一樣
「\"」會輸出「"」 (例如:printf("123\"456");)
「\?」和「?」的效果一樣

注意:
「\n」雖然說類似鍵盤上的「Enter」鍵,但其實在非常非常特殊的情況下,「\n」並不等於鍵盤上的「Enter」鍵,反而比較像「↓」方向鍵 (例如:printf("123\r78\n56");)

註12
這裡介紹的for迴圈功能僅限C++
C語言也有for迴圈,但功能受限,並不像C++的for迴圈這麼好用

註13
可能會有人覺得奇怪,「char」不是用來表示「一個字元」的嗎?為甚麼會被歸類在「整數」呢?
事實上,「char」的儲存和運作方式跟其他整數型別一模一樣
只是「char」的「數字範圍」很適合用來表示英文字母、數字和一些符號等等的字元而已,所以「char」就莫名其妙被用來「表示字元」了XD

註14
這樣的struct定義方式無法在 C (而不是C++) 使用
C的struct必須使用更迂迴的方式來定義:

typedef struct
{
    float a,b,c;
}Line;

這相當於C++這種定義struct的方式:

struct Line
{
    float a,b,c;
};



下一章 (這要怎麼定義下一章啦喂)

感謝:pr3pony、李旺陽學長、uzk、奕均的留言
(版權所有 All copyright reserved)

2016年4月29日 星期五

給新手的C++教學 (上冊) - 3. 認識運算子 (Acquaintance to operators)

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

上一章

利用先前學到的概念,我們已經有能力可以讓程式跟人互動了!
不過,這樣似乎還缺了甚麼?
我們的程式目前好像只能模仿我們的輸入

如果我們的程式除了記憶力之外,還可以擁有強大的運算能力,把計算結果輸出給我們,那該有多好啊~
這樣,就可以真正的利用程式來幫助我們計算了!

要讓我們的程式開竅,我們可以使用「運算子 (Operator)」

運算子是甚麼呢?
千萬別被它的名稱嚇到了,其實「運算子」就只是「加減乘除」而已XD
比較需要注意的是,「乘法」的符號是「*」,「除法」的符號是「/」
(WTF原來這麼簡單?!)

還記的你在寫數學題目時會用到的算式嗎?
舉個例子:1+2的答案是?
你一定知道答案是3
信不信,電腦在學會「C++」之後 (電腦學會C++?請見第一章),也知道答案是3!
不信嗎?我們來做個小測試:

#include<cstdio>
int main()
{
    int a=1,b=2;
    printf("%d\n",a+b);
    return 0;
}

不用說你也知道要做甚麼吧?
趕快在Dev-C++裡面把這份程式碼打出來,然後按下鍵盤上的「F11鍵」查看程式執行結果吧!

程式輸出3了!
(可能有細心的讀者發現,我把Dev-C++的背景改成黑色了,這只是個人習慣,因為我覺得黑色背景比較好看XD)

在打出這份程式碼的過程中,聰明的你可能會注意到
原本的寫法
int a,b;
變成了
int a=1,b=2;
意思就是,我們定義型別為int的兩個變數,a和b (不懂?複習一下第二章吧)
然後把a設定成1,b設定成2
這種「將剛被定義出來的變數設定數值」的動作
我們稱之為「初始化 (Initialization)」(這個看起來很難的字眼,其實真的就是這麼簡單XD)
如果你有使用過Windows XP作業系統,你可能在登入畫面看過這個字眼
沒錯,這時候「Windows XP」這個巨大的程式,正在設定它裡面每個變數的數值

這是Windows XP的登入畫面,有時候會顯示「正在初始化...」
回到正題
程式輸出3了!電腦果然厲害!
那麼該來考考電腦了
現在,請你問問看電腦
2+3
567+789
273*7122
91/13
87411-24005
105-324
分別是多少呢?

答案是
2+3=5
567+789=1356
273*7122=1944306
91/13=7
87411-24005=63406
105-324=-219
你的電腦答對了嗎?
現在,請你嘗試問電腦更難、更刁鑽的問題
甚麼情況下電腦會答錯呢?

電腦真的有可能會算錯喔
舉兩個例子:
100000*100000
5/3

如果你覺得驚訝,代表你是個正常人

100000*100000的答案是「10000000000」
但是電腦卻回答了「1410065408」
5/3的答案是「1.6666666666......」
但是電腦卻回答了「1」
Why?
我們來回顧一下程式碼:

#include<cstdio>
int main()
{
    int a=100000,b=100000;
    printf("%d\n",a*b);
    return 0;
}
 

以及

#include<cstdio>
int main()
{
    int a=5,b=3;
    printf("%d\n",a/b);
    return 0;
}
 

可以發現,我們的程式是用兩個int去進行計算的
數學上,整數的加減乘法具有封閉性
也就是兩個整數相加、相減、相乘後的結果還是一個整數
程式上也一樣,「int」的運算也具有封閉性,不過封閉性更強了,連「除法」也具有封閉性!
事實上,你對兩個int進行任何運算,結果一定還是一個int!

int無法處理小數,所以「1.6666666666......」就捨去小數部分,變成了「1」,合情合理
(如果結果是「-1.6666666666......」,以int的型別儲存後就會變成「-1」) (註10)

至於「1410065408」,這就揭露了int的另外一個秘密了

事實上,你電腦的記憶體再怎麼多,還是有限的,因此不可能儲存很大很大的數字
對於int這種類型的變數,電腦會撥出大小為「32個位元」的記憶體去儲存它 (註1)
甚麼是位元?
就是0或1,電腦中最基本的儲存和運算單位

也就是說,int其實就是一個「最多32位數的二進位數字」
哪有?我們看到的int怎麼看都是一個十進位數字啊
那是因為電腦學會了C++,所以知道要怎麼把這個二進位數字轉換成十進位數字,輸出給我們看
那「負數」怎麼辦呢?
電腦學會了C++,很聰明的解決了這個問題
方法就是把32個位元的其中一個位元拿掉,這個位元就不用來表示二進位數字的其中一個位數了
電腦拿這個位元來表示這個數字的正負號
如果這個位元是0,表示這個數字是正數
如果這個位元是1,表示這個數字是負數
很聰明吧!

所以,剩下的「31個位元」所能表示的數字範圍就是「$0\sim 2^{31}-1$」(表示正數時) 或「$-2^{31}\sim -1$」(表示負數時) 了 (每個位元有2種情況 (0或1),因此31個位元可以有$2^{31}$種組合,這牽涉到一點數學排列組合的知識)
也就是「$0\sim 2147483647$」或「$-2147483648\sim -1$」(註3)
因此,int的最小值是「-2147483648」,最大值是「2147483647」

也因此,如果int的計算結果超出了「-2147483648~2147483647」的範圍,電腦就會因為撥出來給int變數的記憶體不夠而算錯喔~
這種情況,我們稱作「溢位 (Overflow)」,這是我們寫程式的人需要注意的,因為它會導致錯誤的計算結果

上面我們有提到,int無法處理小數,因此5/3的答案是「1」
不知聰明的你有沒有想到
那我們乾脆就用可以處理小數的「float」來計算就好啦!

廢話不多說,馬上來試試看!

#include<cstdio>
int main()
{
    float a=5,b=3;
    printf("%f\n",a/b);
    return 0;
}
 

要注意的是,float也滿足加減乘除的封閉性,因此計算出來的東西也是一個float,要用「%f」來輸出,而不是int的「%d」

用「float」計算5/3的結果
耶!果然有小數了!
等等,為甚麼最後一位是7?
剛剛有提到,電腦的記憶體是有限的,因此不可能儲存很大很大的數字,當然也不可能儲存很多很多的小數
float是用「科學記號」的方式儲存的,換句話說,「24005」會被當作「$2.4005*10^{4}$」來看待 (事實上不是如此,請見「註2」)
其中,「2.4005」和「4」是分開儲存的,和int一樣會被轉成二進位數字,儲存在電腦撥出來給它的記憶體中 (事實上不是如此,請見「註2」)
這兩個數字當然也有其範圍極限

還記得第二章提到的誤差問題嗎?
就是這樣來的喔~

綜合起來
float的範圍約落在「$-10^{38}\sim -10^{-38}$」、「0」、「$10^{-38}\sim 10^{38}$」
誤差約「0.00001% (也就是$10^{-7}$)」
這裡看不懂沒關係,你只要知道float有誤差就好 ^_^ (float非主流,見註6)

最後,再跟大家報告一個好消息
數學上,我們習慣「先乘除,後加減」
因此「$5\times 6+9\div 3$」的答案是「$5\times 6+9\div 3=(5\times 6)+(9\div 3)=30+3=33$」
而不是「$5\times 6+9\div 3=30+9\div 3=39\div 3=13$」喔
程式上,「先乘除,後加減」的規則也是成立的!
而且,還可以使用括號喔!

以下提供兩個例子,讓你深入了解C++程式的奧妙!
「先乘除,後加減」

#include<cstdio>
int main()
{
    int a=5,b=6,c=9,d=3;
    printf("%d\n",a*b+c/d);
    return 0;
}
 
「先乘除,後加減」,因此程式輸出「33」

「有括號,要先算」

#include<cstdio>
int main()
{
    int a=5,b=6,c=9,d=3;
    printf("%d\n",a*(b+c)/d);
    return 0;
}
 
「有括號,要先算」,因此程式輸出「25」

現在,換你了!
你玩出了甚麼東西呢?

下一章

感謝:pr3pony、李旺陽學長、WillyPillow
(版權所有 All copyright reserved)

2016年4月28日 星期四

給新手的C++教學 (上冊) - 2. 變數 (Variable)

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

上一章

利用上一章學到的東西,我們已經有能力可以在螢幕上顯示任何文字了!
但是,這樣的程式還無法和人互動

我們的程式要怎麼和人互動呢?
方法是人輸入一些文字然後按下鍵盤上的Enter鍵,把這些文字輸入給程式
然後程式就可以依照輸入的東西來作出對應的回應了 (這裡的「回應」指的是在螢幕上顯示東西)

這裡先來向大家解釋甚麼是「輸入 (Input)」和「輸出 (Output)」
它們可以當動詞也可以當名詞,在以後的文章看到時,可能需要自行判斷一下
當動詞時,「輸入」代表將一段文字傳給程式,「輸出」代表程式將一段文字顯示在螢幕上
當名詞時,「輸入」代表傳給程式的一段文字,「輸出」代表程式在螢幕上顯示的一段文字
懂了嗎?^_^
(p.s.其實輸入輸出的意義不僅僅是這樣,但在以後的教學中,它們就只會是這個意思)

不過,要做到「程式依照輸入的東西來作出對應的回應」,就代表
你的程式必須記住你輸入了甚麼東西

我們要怎麼實現讓程式擁有記憶呢?
方法就是把資訊以「變數 (Variable)」的形式儲存起來

變數要怎麼使用呢?
在C++裡面,變數有很多種類型,我們稱作「型別 (Type)」
有哪些型別呢?
我想想喔,有short、int、long long、bool、char、float、double、......,甚至在新版的C++ (C++11) 又新增了一些型別
不過,大部分都不會用到 (或很少用到)
事實上,你只要學好int、char、float這三種型別,就足夠應付所有功能了!
其他的型別就只是int、char、float這三種型別的「功能增強版」或「功能削弱版」(?)

「int」是「整數 (Integer)」,這種型別的變數是用來儲存「一個整數」的
「char」是「字元 (Charactor)」,這種型別的變數是用來儲存「一個字」的
「float」是「浮點數 (Floating-point number)」,別被它的名字嚇到,其實「float」做的事情就和「int」一樣,只是「float」可以允許「小數」的存在,缺點是你必須接受些微的計算誤差。現階段,這個誤差你可以不用考慮它

介紹完了,那要怎麼使用呢?
來看個範例
我們希望輸入一個整數,然後程式就會輸出一個跟你輸入的數值相同的整數 (例如:輸入「12」或「012」,會得到輸出「12」)
也就是『輸入一個「int」,輸出一個「int」』
程式碼在這裡: