2016年12月23日 星期五

給新手的C++教學 (上冊) - 13 - 10. 轉型

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

回到「13. 額外語法 (Extra syntax)」

上一頁

註: 小莫使用的程式碼上色網站掛掉了,因此本頁的程式碼都沒有顏色,等該網站恢復之後會再進行程式碼上色的動作,暫時造成不便敬請見諒。若您發現該網站已經恢復運作,本頁程式碼卻還沒更新,也歡迎以各種方式提醒小莫哦~ ^_^

顧名思義,「轉型」就是「轉換型別」
「將某個小數無條件捨去到整數位」就是「從float『轉型』到int」的一個例子
因為小數位不見會變成整數 (int) 嘛XD

不過,「轉型」並不是把某個變數a的型別從float「變成」int,而是依據a的值「產生」一個int變數,其值接近型別為float的a (為甚麼說接近? 因為你不可能把一個int變數的值設定成2.4,頂多設定成2或3)

那麼,要怎麼將一個變數「轉型」呢?

2016年12月19日 星期一

小莫演講用過的ppt下載

以下是小莫參加過的演講,用的ppt都是從上一場演講修改來的XD

  1. 高雄中學105級科學班專題成果發表會《 Möbius 》

2016年11月23日 星期三

Digging Game 3開發之路 - 第1站:猜數字遊戲 (Number guessing game)

回到「Digging Game 3開發之路」

Digging Game 3開發之路

咦? 你不知道Digging Game是甚麼?趕快看一下行前介紹吧~

Digging Game 3開發之路
↓行程表↓


2016年11月21日 星期一

Digging Game 3開發之路 - 行前介紹

有沒有玩過小莫製作的鑽礦遊戲Digging Game 2呢?
哈哈沒玩過也沒關係,趕快去玩玩看~

稍稍提一下小莫的背景

2016年11月14日 星期一

[教學]Google Blogger留言被吃字問題解決方法

為了問一些關於程式的問題,我們常常在留言中貼上程式碼,按下「發布」之後,「#include<cstdio>」竟然只剩「#include」、每一行開頭的空白也全部都不見了!

慘掉的程式碼www

這樣整個程式碼既不完整,排版也整個慘掉QQ
這是因為程式碼的某些特殊字元和網頁HTML格式衝突造成的
以下提供小莫自製的線上轉換器,專門解決這種問題
使用方法:
  1. 將留言貼到第一個文字框
    貼到第一個文字框
  2. 按下「轉換成HTML」按鈕
    按下轉換鈕
  3. 第二個文字框(在按鈕下面)會產生一串東西,這串東西有時看起來會很奇怪
    將產生的東西複製下來
  4. 不用擔心,直接將這串東西複製、貼到要留言的地方直接當作留言發布,應該就會看到您的留言變得很漂亮很正常囉~
    直接貼上當成留言發布
    正常的程式碼顯示出來了!\(^o^)/
發現任何問題要講哦~小莫才能知道哪裡需要改善^_^
轉換器:

2016年10月26日 星期三

給新手的C++教學 (上冊) - 13 - 25. 「新版C++」--「C++11」的好用功能

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

回到「13. 額外語法 (Extra syntax)」

上一頁

C++看起來已經是一個很完整、功能強大的程式語言了
但事實上,世界各地的專家們仍然致力於改善C++,讓原本已經很強的C++的功能更加強大!
因此,C++也是有版本的哦~
別擔心,您在較舊版本C++使用的語法,在新版C++也能無縫接軌的使用!

注意:請先依據這篇設定好編譯參數,才能使用本頁所教的語法

請注意,此篇語法有些適合搭配STL (Standard Library 標準函式庫) 使用,STL的介紹和用法將在下冊講到

「auto」的用法:

先備知識:1~12章的某些基本語法
功能:可以讓電腦在宣告變數的時候自動判斷該變數的型別

簡單舉例:

#include<cstdio>
int main()
{
    double a=8.3;
    //double b=a;
    auto b=a;//這一行和上面那一行被註解掉的程式碼是等價的 
    printf("a=%f, b=%f\n",a,b);
    return 0;
}
執行結果


再舉一個例子:

2016年10月17日 星期一

給新手的C++教學 - 未來之章

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

此頁還沒撰寫哦~
但不一定是小莫的最優先撰寫文章
如果想快點看到本文內容,請寄信到fsps60312@yahoo.com.tw讓小莫知道您的閱讀意願
這樣小莫才能知道您期待的是哪一篇文章,就會提早開始撰寫它囉~

另外,整個code風景區全部都是小莫一個人在管理,目前還是忙忙忙的學生,所以如果文章撰寫速度不符合您的預期請見諒><

小莫的email: fsps60312@yahoo.com.tw

---Motivation驅動力教學,Mobius扭帶公司發行---

2016年9月27日 星期二

給新手的C++教學 (上冊) - 13 - 9. 進階的檔案處理

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

回到「13. 額外語法 (Extra syntax)」

上一頁

讀取檔案「in.txt」並同時輸出其內容:

#include<cstdio>
int main()
{
    FILE *file_reader=fopen("in.txt","r");
    for(char c;fscanf(file_reader,"%c",&c)==1;)
    {
        printf("%c",c);
    }
    return 0;
}
輸出結果:可以發現黑色視窗上輸出的內容就是「in.txt」的內容

輸入3個檔名,依據輸入的檔名讀取那3個檔案並同時輸出其內容:

#include<cstdio>
void ReadFile()
{
    char file_name[1000];
    scanf("%s",file_name);
    FILE *file_reader=fopen(file_name,"r");
    for(char c;fscanf(file_reader,"%c",&c)==1;) printf("%c",c);
    printf("Finish reading %s!\n",file_name);
}
int main()
{
    ReadFile();
    ReadFile();
    ReadFile();
    return 0;
}
可以隨時決定要從哪一個檔案讀取資料 (fscanf) 或者直接從黑色視窗取得輸入 (scanf)

將「1+2+3+......+100」的完整計算過程寫入到檔案「out.txt」:

2016年9月19日 星期一

給新手的C++教學 (上冊) - 13 - 8. 簡易的檔案處理

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

回到「13. 額外語法 (Extra syntax)」

上一頁

您是否有想過要用C++來讀取和寫入檔案呢?
真的可以嗎?需不需要解析磁碟機NTFS、FAT32之類的格式啊?
當然不需要!

放心,這件事連小莫都不知道怎麼做
所謂「站在巨人的肩膀上」,這種事情不用再由我們自己處理了!
在先人的努力之下,「C++」這個偉大的程式語言,已經讓電腦可以只依據簡單的幾行程式碼,就可以執行許多複雜卻需要經常執行的工作

事實上,C++讀寫檔案的方法比你想的任何方式都簡單!
更具體地來講
我們在撰寫C++程式碼的時候,只需要告訴電腦「讀取哪個檔案」和 (或)「寫入哪個檔案」就好了!

要怎麼告訴電腦「恩,我要從這個檔案名稱為『in.txt』的檔案讀取」呢?
(請先到檔案總管設定顯示附檔名以取得完整的檔案名稱 (點我查看教學))
寫下一行程式碼就夠了:

2016年9月16日 星期五

給新手的C++教學 (上冊) - 13 - 7. 中文字元字串的處理

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

回到「13. 額外語法 (Extra syntax)」

上一頁

先前有網友提問,他想寫一個程式:
輸入「是」會輸出「真是識相!\n」
輸入「不是」會輸出「你眼光有問題!\n」

我們先來看看這個程式的英文版本怎麼寫:
輸入「YES」會輸出「真是識相!\n」
輸入「NO」會輸出「你眼光有問題!\n」

#include<cstdio>
int main()
{
    printf("我是天才? YES or NO\n");
    char answer[4];
    scanf("%s",answer);
    if(answer[0]=='Y'&&answer[1]=='E'&&answer[2]=='S'&&answer[3]=='\0')
    {
        printf("真是識相!\n");
    }
    if(answer[0]=='N'&&answer[1]=='O'&&answer[2]=='\0')
    {
        printf("你眼光有問題!\n");
    }
    return 0;
}
輸入「YES」
輸入「NO」

請注意,「answer」的長度只有4,因此一旦輸入的長度超過3 (注意,還有一個表示字串結尾的「'\0'」) 就有可能導致程式出錯

那麼,要怎麼改成中文版本呢?是這樣嗎?

#include<cstdio>
int main()
{
    printf("我是天才? YES or NO\n");
    char answer[3];
    scanf("%s",answer);
    if(answer[0]=='是'&&answer[1]=='\0')
    {
        printf("真是識相!\n");
    }
    if(answer[0]=='不'&&answer[1]=='是'&&answer[2]=='\0')
    {
        printf("你眼光有問題!\n");
    }
    return 0;
}

很遺憾的,事情並沒有這麼簡單

2016年9月15日 星期四

給新手的C++教學 (上冊) - 13 - 6. 更彈性的取得和釋放記憶體

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

回到「13. 額外語法 (Extra syntax)」

上一頁

名詞解釋:
「釋放」記憶體:將某塊記憶體標記為「使用完畢」,讓這塊記憶體之後或讓其他程式可以再被利用

在之前的字元字串章節,我們使用了一個很大很大 (大小為100萬) 的陣列來儲存「一個名字」
除非要處理特別多的資料,否則應該是不會需要這麼大的陣列啦XD
但接下來,您會發現,當陣列太大的時候,會發生問題的
為了節省版面,這裡以字元字串章節的最後一份程式碼為例:

#include<cstdio>
int main()
{
    char name[1000001];
    scanf("%s",name);
    printf("Hello, %s!\n",name);
    return 0;
}
輸入名字「Motivation」,會輸出「Hello, Motivation!」

假如哪天你發現某人的名字太長了 (?),大小100萬的陣列不夠用 (!),想要宣告大小1000萬的陣列 (......)
好啊!欣然同意啊XD

#include<cstdio>
int main()
{
    char name[10000001];
    scanf("%s",name);
    printf("Hello, %s!\n",name);
    return 0;
}
欸欸等等我甚麼是都還沒做耶!

咦?怎麼程式掛了?!
根本都還沒開始輸入名字呀!

2016年9月12日 星期一

給新手的C++教學 (上冊) - 13 - 5. 陣列就是指標,指標就是陣列

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

回到「13. 額外語法 (Extra syntax)」

上一頁

當您讀到「陣列」這個單元時,大可將「宣告一個大小為n的陣列」理解成「讓電腦幫你一次宣告n個變數」
但是,事實真的是如此嗎?

當您宣告一個變數的時候,電腦會挪出一塊記憶體給你用,啊然後咧?
這就像您想要網購某個東西,在購物網站上點了「購買」按鈕、付了錢,然後就以為沒事了(?)
不對啊,你總要知道要去哪裡取貨吧!
因此,程式向電腦「訂購」了記憶體之後,電腦就要告訴程式「取貨地址」--也就是「記憶體編號」,或稱「指標」

當程式執行到「int a;」這一行,程式會向電腦訂購32位元記憶體,然後電腦會告訴程式這32位元記憶體的「指標」。程式會小心翼翼地把這個「指標」記好,這樣才能隨時去使用它訂購的32位元記憶體

然而,有一件殘酷的事實是:
「記住指標」這個動作會讓程式需要額外的static記憶體 (之後會學到甚麼是static記憶體)

那這樣的話,把「宣告一個大小為$n$的陣列」理解成「讓電腦幫你一次宣告$n$個變數」會有甚麼問題嗎?
注意到,與其「訂購$32$位元記憶體$n$次,並記住$n$個指標」,還有另一種更有效率的方式:
直接一次性地訂購$32n$位元記憶體 (恩對一條街被買下來了(?)),然後依照「門牌號碼」分配給每個變數各$32$位元記憶體

差別在哪?這時程式只需要記住1個指標 (而非$n$個),也就是那「$32n$位元記憶體」的指標
當程式要取得第$i$ ($1\leq i\leq n$) 個變數的指標時,只要將第1個變數的指標加上$32(i-1)$位元就好了

怎麼證明電腦真的在做這件事?
信不信,陣列的名稱可以直接當指標來用XD (?!)
當然,小莫還要示範給你看!

2016年9月2日 星期五

給新手的C++教學 (上冊) - 13 - 4. 指定輸出格式

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

回到「13. 額外語法 (Extra syntax)」

上一頁

您是否有想過要固定輸出數字的寬度呢?
當您想要讓輸出的格式類似表格,行行之間的數字要對齊,就會想要這樣做
這時候該怎麼辦呢?
用代表「Tab」的「\t」來排版吧!
可是數字太長會讓「\t」跳到下一個位置,反而加大行行數字間的差距甚至造成混淆......
先想辦法算出數字有幾個位數,再決定每個數字前面各要補幾個空格?
功能完美!可是似乎有點麻煩......

哈哈,相信您已經猜到了--本章將教您如何簡單的設定輸出格式!
本方法僅限「scanf」和「printf」的使用者哦~
如果您是使用「cin」和「cout」,小莫真的不知道怎麼辦呢......XD

類似表格的東西喔......就拿九九乘法表來當例子吧!
首先,我們先把輸出九九乘法表9*9個數字的程式碼寫出來~

#include<cstdio>
int main()
{
    for(int row=1;row<=9;row=row+1)
    {
        for(int column=1;column<=9;column=column+1)
        {
            if(column>1)printf(" ");//除了第一個數字之外,其餘的數字前面都要有一個空格
            printf("%d",row*column); 
        }
        printf("\n");
    }
    return 0;
}
九九乘法表~寫錯了也沒關係,可以直接貼程式碼哦
我們來把每個數字的寬度都固定成2吧~

#include<cstdio>
int main()
{
    for(int row=1;row<=9;row=row+1)
    {
        for(int column=1;column<=9;column=column+1)
        {
            if(column>1)printf(" ");//除了第一個數字之外,其餘數字的前面都要有一個空格
            printf("%2d",row*column); 
        }
        printf("\n");
    }
    return 0;
}
耶~所有數字的寬度都固定成2了
耶~所有數字的寬度都固定成2了 \(^o^)/
等等,為甚麼?程式碼看起來沒差呀
其實真的沒差多少,我們只是把輸出數字的「%d」改成「%2d」而已 (在「printf("%d",row*column);」那裡)
就這麼簡單!
當然,如果想要把數字的寬度固定成3,把「%2d」改成「%3d」即可

您可能會想問,可以用一個「變數」來指定數字的寬度嗎?
沒問題!

給新手的C++教學 (上冊) - 13 - 3. 進階型別的介紹

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

回到「13. 額外語法 (Extra syntax)」

上一頁

請注意,這裡只介紹小莫用過的型別,但應該已經非常非常夠用了!
為了方便介紹,小莫將其分為兩大類:「浮點數」和「整數」(註13)
  1. 浮點數
    • 特色:支援小數、有微小誤差、數字範圍大
    • 溢位會怎樣:超過最大值會變成inf,超過最小值會變成-inf
    • 除以0會怎樣:正數除以0會變成inf、負數除以0會變成-inf,0除以0會變成nan (「not a number」的縮寫)
    • 型別有哪些:
      名稱floatdoublelong double__float128
      占用記憶體32位元64位元96位元128位元
      誤差和數字範圍占用記憶體越大,誤差越小、數字範圍越大
      輸入(scanf)%f%lf不支援不支援
      輸出(printf)%f%f不支援不支援
      斜體標示 (針對__float128):如果要使用此型別,請先參考前一頁並設定好編譯參數,以使用C++11的功能
  2. 整數
    • 特色:不支援小數、沒有誤差、數字範圍小
    • 溢位會怎樣:超過最大值會變成最小值,超過最小值會變成最大值
    • 除以0會怎樣:會造成不可預知的錯誤,通常是程式出錯並停止運作
    • 型別有哪些:
      名稱boolcharshortintlong long__int128
      占用記憶體8位元8位元16位元32位元64位元128位元
      數字範圍$0\sim 1$$(-2^{占用記憶體-1})\sim (2^{占用記憶體-1}-1)$
      輸入(scanf)不支援%c不支援%d%lld不支援
      輸入(scanf)不支援%c不支援%d%lld不支援
      粗體標示 (針對char):輸入輸出皆以字元的方式進行 (而不是數字)
      斜體標示 (針對__int128):如果要使用此型別,請先參考前一頁並設定好編譯參數,以使用C++11的功能
    • 另外,整數還可以用「unsigned」修飾而有更多玩法!意者請Google搜尋「C++ unsigned 用法」
對於不支援輸入輸出的型別的其中一種處理方式 (以相加兩個「long double」為例):

2016年8月29日 星期一

給新手的C++教學 (上冊) - 13 - 2. 編譯參數的建議設定

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

回到「13. 額外語法 (Extra syntax)」

上一頁

你在寫程式的時候,是否曾經犯過白癡錯誤呢?
有些錯誤是人可以很輕易識別的,但是卻恰好符合C++的語法而不會讓電腦察覺異狀
例如:

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

我知道你要做出小數加法,但是程式可以正常執行卻輸出錯誤答案 (不知道的趕快去試試看!輸入「0.1 0.1」,保證輸出不是「0.2」)
怎麼會這樣?Orz

又偏偏錯誤在寫程式當下很難被察覺,可能直到整個幾十行甚至幾百行的程式碼寫完之後,才發現程式執行起來不對勁 (你發現哪裡寫錯了嗎?XD)
這樣一來要回去檢查整個程式碼就是非常麻煩的一件事
偷偷告訴你,這種白癡錯誤其實可以偷懶叫學過C++的電腦幫你找哦~
保證萬無一失!

方法如下:

給新手的C++教學 (上冊) - 13 - 1. 「註解」的使用

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

回到「13. 額外語法 (Extra syntax)」

上一頁 (這是第一頁)

如果有一天你想不開 (X) 去看了一年前寫的程式碼,很大的機會你是無法在短時間內就看懂的 (如果不相信的話可以實驗看看^_^)
真的嗎?
那就在寫程式的當下記錄這份程式碼在幹嘛的就好啦~
可是好麻煩喔,這樣有些想解釋更清楚的地方不就要再數數看在第幾行嗎?
例如以下程式碼:

#include<cstdio>
int main()
{
    printf("Hello world!\n");
    return 0;
}

你可能會想 (用Microsoft Word或記事本之類的) 寫個說明存成另一個檔案之類的:

這個程式會輸出「Hello world!\n」
第1行會引入標頭檔「cstdio」
第2行的「int」是主函式的型別
第2行的「main」是主函式的名字
第4行的「printf」是用來輸出的函式名字,兩個「"」裡面是要輸出的字串,所以這一行會讓程式輸出「Hello world!\n」
第5行是讓程式回傳0來正常結束

但是這樣的說明不論修改或閱讀都很麻煩 (因為還要指定或找到第幾行)
而且說明檔和程式碼是分開的,很不好管理
這時,「註解」就很好用了,它可以讓你直接把說明寫在程式碼裡面
用法如下:

/*灰色的字都是註解
它們可以讓你輕易地看出這份程式碼在幹嘛
例如這份程式碼會讓程式輸出「Hello world!\n」*/
#include<cstdio>//引入標頭檔「cstdio」
int main()//int是主函式的型別,main是主函式的名字
{
    printf("Hello world!\n");//輸出「Hello world!\n」
    /*「printf」是用來輸出的函式名字
      兩個「"」裡面是要輸出的字串*/
    return 0;//讓程式回傳0來正常結束
}

這樣就可以很清楚的知道程式的每個地方在做甚麼事了!
當然,註解並不會對原本程式碼的功能產生任何影響,你想寫甚麼就寫甚麼、想寫多少就寫多少!

甚麼,你說你還是覺得另外開檔案存說明比較好?

2016年7月20日 星期三

[公告]code風景區瀏覽量破2萬!

如題,耶!
code風景區歡迎您的光臨!
記得要留言哦~
建議、感謝、討論、心得、提問、要求、評論、糾正......等等,都很歡迎!
同時,小莫也會每天檢查明顯不適當的留言並刪除
給大家一個乾淨舒適的空間!

YA! Happy!
Welcome to Code Scenic!
You can call me Motivation or Burney. ;)
Remember to leave your precious comments!
Recommendations, thanks, discussions, experiences, questions, quests, reviews, corrections ... etc. , are all highly welcome!
Also, I'll check and delete those which are obviously inappropriate, in order to give everyone a friendly and peaceful space!

p.s. 也有在經營部落格的朋友們,我們互加友情連結吧 <3
p.s. If you also own a blog, could we add links to each other's?

2016年7月8日 星期五

[教學]隨身碟裡面的檔案都不見了!

出於無聊,將系統語言設定成英文 (雖然我是台灣人),因此圖片皆為英文版的畫面,說明文字將以「英文 (中文)」形式代表英文和其可能的中文,例如以下會出現的「View (檢視)」和「Options (選項)」
英文很差,所以不保證中文翻譯會和實際情況完全相符

有一天,去了影印店,把隨身碟裡面的文件列印出來
回家之後,用電腦一看
檔案呢?怎麼都不見了?!
整個隨身碟只剩下一個沒有名字的捷徑
千萬不要去點這個捷徑!!!
您的隨身碟中毒了
請放心,小莫來教您如何找回不見的檔案

找回檔案:
  1. 這是發生悲劇的隨身碟,裡面只剩一個沒有名字的捷徑(千萬不要點開!)



  2. [此步可跳過]小心檢查這個捷徑的內容,發現這個捷徑的路徑很詭異(小莫也看不懂>_<)



  3. 點選「View (檢視)」



  4. 點選「Options (選項)」



  5. 在跳出來的視窗中點選標籤「View (檢視)」(那個背景不一樣就別管了,因為上面兩張是後來才做的XD)



  6. 在下面那一串清單中找到「Hidden files and folders (隱藏檔案及資料夾)」,選擇「Show hidden files, folders, or drives (顯示隱藏的檔案、資料夾及磁碟機)」,點選按鈕「Apply (套用)」,然後把這個小視窗關掉



  7. 看到多出來的兩個資料夾了嗎?不見的檔案都在那個名字叫「_」的資料夾裡面!



  8. 點進那個名字叫「_」的資料夾。還沒結束!先將這些檔案複製到電腦裡面備份,我們準備將隨身碟格式化 (這樣隨身碟內的資料都會不見) 以杜絕後患!




2016年7月6日 星期三

鑽礦遊戲Digging Game 2下載連結

(下載連結在下面)

因為遊戲時常更新,同步更新各地的下載連結常有遺漏
Because of frequently game-updating, somewhere could be easily omitted when updating the game download links.

因此決定將所有連結導向至此,以方便維護和發佈新版本
So I've decided to redirect all links here in order to improve and release game updates more efficiently. Thanks!

這是我自己寫的遊戲,有參考網路上原本的鑽礦遊戲,但是沒有版本繼承關係
This is a game create by myself. There's a similar game, Motherload, which was one of the games I took reference from. But this does not mean that Digging Game 2 have any relation of inheritance from Motherload.

是不是很期待「鑽礦遊戲Digging Game 3」呢?XD
Excited about "Digging Game 3" ?  ;)

目前版本 (Current version):Digging Game 2.2.16
更新時間 (Update time):2016/8/27 13:20

遊戲下載連結(Download links):

下載壓縮包(zip file):https://www.dropbox.com/s/m1g8bj54snerqen/Digging%20Game%202.2.16.zip?dl=0
直接下載檔案(download game files directly):https://www.dropbox.com/sh/t5udv0o2baaotov/AAAjIxgzH03LspxcDW_3sOXLa?dl=0

遊戲影片(Videos for Digging Game 2):

介紹&教學 (introduction & instruction):https://www.youtube.com/watch?v=xTjyu5uaWmM&feature=youtu.be&list=PL0srVz2dbivUrw6S1p2wr8o0wmh0V9EJc


遊戲技巧&彩蛋&破梗 (Tip & Easter eggs) (其實沒有全部破梗啦www)
中文版(chinese subtitle):https://www.youtube.com/watch?v=UBdoBuSRJV0&index=3&list=PL0srVz2dbivUrw6S1p2wr8o0wmh0V9EJc

Video in English:https://www.youtube.com/watch?v=Ib3NL5SoDc8&index=2&list=PL0srVz2dbivUrw6S1p2wr8o0wmh0V9EJc


後來手癢又加了AI (人工智慧) 功能 (AI added into the game! For fun!):https://www.youtube.com/watch?v=vao7gNxJpBY&index=4&list=PL0srVz2dbivUrw6S1p2wr8o0wmh0V9EJc


粉絲專頁(Facebook Page):https://www.facebook.com/DiggingGame2/

2016年6月22日 星期三

[教學]用C++寫出表單 (Form) 的簡單方法 (非Visual C++)

本文並不教您如何從頭寫出全部的程式碼
僅說明如何利用Dev-C++這個編輯器來產生「編譯出來是一個表單 (Form)」的程式碼

步驟:


  1. 開啟Dev-C++ (下載連結)


  2. 點選「File→New→Project...」


  3. 會出現一個視窗,選擇「Windows Application」後按「OK」


  4. 它會叫你存檔,選擇一個喜歡的名稱和存檔位置後按「存檔(S)」


  5. 好了,這就是「表單」的程式碼,程式碼的各個部分還有附註解說明


  6. 按下鍵盤上的「F11」編譯並執行,它會叫你選擇執行檔的儲存位置


  7. 選個喜歡的儲存位置後按「存檔(S)」,程式碼就會開始被編譯 (編譯需要一段時間),編譯完成後會出現一個空白乾淨(?)的視窗,這就是我們的程式碼產生的「表單 (Form)」


或許你可以試著亂改這份程式碼,研究一下C++產生表單的方式和程式碼每個部份的功能

程式碼:

2016年6月1日 星期三

給新手的C++教學 (上冊) - B. 遇到困難了? (There are troubles?)

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

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

本章列出新手在進行本教學的練習時可能會遇到的困難
並提供解決方案
希望能幫助新手們更快、更方便的利用本教學學習新知識!

Q:
看不懂教學在說甚麼QAQ

A:
請問您真的有動手把程式碼用鍵盤打出來,並按下F11執行過嗎?
程式的學習非常依賴自己動手試試看
就像做實驗一樣,在一個字一個字慢慢的打出程式碼的過程中,您才會去觀察規律、猜測其規則、自己修改程式碼來驗證看看,相信很快 (10分鐘內) 就可以掌握觀念!
(真的,不動手試試看就永遠學不會)
這些規則其實是很簡單的,類似小學在玩的益智遊戲,但如果每一個規則都要弄成文字說明,大概在看懂之前就會眼花了吧XD
如果還是不懂,或者理解時間超過10分鐘,歡迎在文章下面留言~
您看不懂,一定還有另一個人也看不懂,所以請別吝嗇,在文章下面勇敢留言說出您遇到的困難吧!

Q:
電腦一直說我的程式寫錯,我不知道為甚麼?
我寫出來的程式就是無法依照預期的方式運作,我不知道為甚麼?

A:
這種情況對新手來說通常不是自己能解決的事,請先參考本教學提供的範例程式碼,並嘗試照著打一遍看看
如果還是出錯,請直接用「複製」、「貼上」的方式,將程式碼貼到你的「Dev-C++」裡面,再按一次鍵盤上的「F11」試試看
當電腦成功讀懂你的程式碼,並且程式是正確執行出預期的結果之後
請再回去比對你原本會出錯的程式碼,找出出錯的原因
這很重要,可以幫助你以後更不會再犯相同的錯誤
如果還是出錯......就代表非常緊急的狀況發生了--本教學的程式碼也錯了!!!
請務必盡快通知小莫,將盡快做修正,感激不盡!
電子信箱:fsps60312@yahoo.com.tw

Q:
怎麼教學看到一半就突然出現看不懂的專有名詞?
怎麼教學看到一半就突然出現還沒教到的東西?

A:
代表小莫沒有考慮好初學者的立場,不小心用到了很專業的術語或進階的語法
請務必盡快通知小莫,將盡快做修正,感激不盡!
電子信箱:fsps60312@yahoo.com.tw

Q:
怎麼辦?上面都沒有提到我的問題QAQ

A:
唉呀呀,你遇到了甚麼問題?
趕快在本章下面留言,或者用任何方式和管道通知小莫
小莫會盡快提供解答,並更新本章內容!
感激不盡!
電子信箱:fsps60312@yahoo.com.tw

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

感謝:
(版權所有 All copyright reserved)

給新手的C++教學 (上冊) - 12. 指標 (Pointer)

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

上一章

這一章,我們將更深入地探討電腦的運作原理
進而更完善的掌控電腦的記憶體

你會發現,你將會有能力控制更多平常想不到的東西!

你有想過嗎?
當我們宣告一個變數的時候,電腦會撥出一些記憶體來讓程式儲存變數的資訊
但是,電腦的記憶體是有限的,總不可能每一塊記憶體都只有使用一次吧?
這樣的話每一台電腦的記憶體大概都只夠用10分鐘了XD
因此,允許記憶體被重複使用的機制是必要的

為了讓記憶體能夠被重複使用,我們必須確認用過的記憶體中,哪些現在還在使用中、哪些已經使用完畢了
那麼,我們的程式當然只能使用那些已經使用完畢的記憶體,否則修改到其他程式正在使用的記憶體,進而導致其他程式出錯

觀念簡單,但是要有效率地做到這件事 (避免每次找記憶體前都要老老實實的把每一塊記憶體都確認一遍),需要許多先進的演算法知識,而且程式碼寫起來非常的麻煩

放心,這件事連我都不知道怎麼做
所謂「站在巨人的肩膀上」,這種事情不用再由我們自己處理了!
在先人的努力之下,「C++」這個偉大的程式語言,已經讓電腦可以只依據簡單的幾行程式碼,就可以執行許多複雜卻需要經常執行的工作
換句話說
我們在撰寫C++程式碼的時候,只需要告訴電腦「需要使用多少記憶體」和「哪些記憶體已經使用完畢」就好了!

我們在宣告變數的時候,就等於是告訴電腦「恩,我需要這麼多記憶體來儲存這一個變數的資訊」,然後電腦就會把你要的記憶體給你

但是,我們有告訴過電腦「哪些記憶體已經使用完畢」嗎?
有的!

還記得在第十章的時候,我們有提到「每一個變數都有它自己的作用範圍」嗎?
那麼,當正在執行的程式碼位於一個變數的作用範圍外,這個變數所使用的記憶體該怎麼辦呢?
這時我們不會需要用這個變數來儲存任何資訊
也就是,這個變數目前不需要使用記憶體來儲存資訊

電腦學過C++,想當然會利用這個「作用範圍外記憶體就不需要了」的特性
不管是甚麼變數,只要程式執行到它的「作用範圍」之外
電腦就會「自動」把這個變數使用的記憶體當作「使用完畢」
也就是說,現在,這塊記憶體可能是閒置的,或者被其他的程式拿去使用了
如果我們再去修改這塊記憶體,會造成不可預知的錯誤
當然,你還沒開始學習本章的內容,不會知道怎麼在作用範圍外修改這塊記憶體

在作用範圍外修改記憶體?
有需要嗎?
是的,有時候會很需要,請看本章範例
感覺很危險?
是的,使用不當會造成其他程式的錯誤,甚至讓整台電腦當機,必須將電腦插頭拔掉再重新開機

因此,在學習本章前,請務必將重要資料存檔,以避免造成不必要的損失

嘿嘿嘿~
現在
我們開始吧XD

2016年5月25日 星期三

給新手的C++教學 (上冊) - 11. 結構 (Structure)

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

上一章

第九章,我們學到了函式
函式真的好好用耶!

咦?真的嗎?
現在,給你三個直線方程式
請你輸出這三條直線相交所形成的三角形的三個頂點座標 (也就是直線的三個交點的座標)

輸入格式:有三行,第$i$行包含第$i$條直線的資訊:三個數字$a_i$、$b_i$、$c_i$,代表第$i$條直線的方程式$a_i x+b_i y=c_i$ (保證三條直線可以形成一個三角形)
輸出格式:有三行,第$i$行包含第$i$個頂點 (交點) 的座標資訊:兩個數字$x_i$、$y_i$,代表第$i$個頂點座標$(x_i,y_i)$ (請輸出小數,頂點順序隨意)

提示:兩條直線$a_{1}x+b_{1}y=c_{1}$、$a_{2}x+b_{2}y=c_{2}$的交點求法:

$\begin{cases}
    &a_{1}x+b_{1}y=c_{1}\\
    &a_{2}x+b_{2}y=c_{2}
\end{cases}\cdots\cdots ①$

$①\Rightarrow
\begin{cases}
    &a_{1}a_{2}x+b_{1}a_{2}y=c_{1}a_{2}\cdots\cdots ②\\
    &a_{1}a_{2}x+a_{1}b_{2}y=a_{1}c_{2}\cdots\cdots ③
\end{cases}$

$②-③\Rightarrow (b_{1}a_{2}-a_{1}b_{2})y=c_{1}a_{2}-a_{1}c_{2}$

$\Rightarrow y=\frac{c_{1}a_{2}-a_{1}c_{2}}{b_{1}a_{2}-a_{1}b_{2}}$

$①\Rightarrow
\begin{cases}
    &a_{1}b_{2}x+b_{1}b_{2}y=c_{1}b_{2}\cdots\cdots ④\\
    &b_{1}a_{2}x+b_{1}b_{2}y=b_{1}c_{2}\cdots\cdots ⑤
\end{cases}$

$④-⑤\Rightarrow (a_{1}b_{2}-b_{1}a_{2})x=c_{1}b_{2}-b_{1}c_{2}$

$\Rightarrow x=\frac{c_{1}b_{2}-b_{1}c_{2}}{a_{1}b_{2}-b_{1}a_{2}}$

p.s. 以上推導過程看不懂也沒關係

$\therefore$兩線交點為$(\frac{c_{1}b_{2}-b_{1}c_{2}}{a_{1}b_{2}-b_{1}a_{2}},\frac{c_{1}a_{2}-a_{1}c_{2}}{b_{1}a_{2}-a_{1}b_{2}})$

啊不就三條直線兩兩求交點就好?
懶得寫三遍同樣的東西,就弄成一個函式吧~
引數 (甚麼是引數?) 就傳遞兩條線的資訊,然後函式就可以進行計算,最後回傳交點的座標......
等等,怎麼回傳「一個座標」?
float、int、char,都不對呀
我們需要一次回傳「兩個float」

2016年5月19日 星期四

給新手的C++教學 (上冊) - 10. 變數的作用範圍 (Scope)

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

上一章

不知你在之前的章節中做練習時,電腦是否莫名其妙地說你寫錯呢?
舉個例子
還記得第6章的練習題嗎?
題目是這樣的:
「輸入一個整數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;
    }
    int i=n-1;
    while(i>=0)
    {
        printf("%d ",a[i]);
        i=i-1;
    }
    printf("\n");
}

然後,電腦就說你寫錯了
然後,電腦就說你寫錯了XD
哦~原來我前面已經宣告了一個名字為「i」的變數了,不能再宣告一個名字一模一樣 (同樣是「i」) 的變數
p.s. 雖然之前的章節完全沒有提到,這個命名不能重複的規則請讀者務必了解,仔細想想應該就會發現這個規則合情合理,否則最後會分不清楚「i」到底是指哪一個變數

如果你還是搞不懂發生了甚麼事,將上面的程式碼和第6章提供的程式碼解答比對一下,看看有甚麼差別吧~

現階段,這種問題是很好解決的
以目前的知識,可以想到的方法有2種:

2016年5月17日 星期二

給新手的C++教學 (上冊) - 9. 函式 (Function)

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

上一章

依照慣例,在本章依然要給你一個題目,然後你就會發覺需要學習某種新技能,才能有效率的寫出可以解決問題的程式碼 (?)

給你一個正整數$n$,請求出第$n$個卡特蘭數
提示:
第$n$個卡特蘭數$=C^{2n}_{n}-C^{2n}_{n+1}$
其中$C^{a}_{b}=\frac{a!}{b!(a-b)!}$
其中「$x!$」念作「$x$階層」,$x!=1*2*3*...*x=\prod_{k=1}^{x}k$

當然,$n$不能太大,否則會發生溢位 (overflow) 的情況 (甚麼是溢位?)
所以$n$的範圍會在$1\sim 6$內

卡特蘭數列:1、2、5、14、42、132、......

你的程式答對前6項了嗎?

參考程式碼:

#include<cstdio>
int main()
{
    int n;
    scanf("%d",&n);
    int a=1,b=1,c=1;
    int i=1;
    while(i<=2*n)
    {
        a=a*i;
        i=i+1;
    }
    i=1;
    while(i<=n)
    {
        b=b*i;
        i=i+1;
    }
    i=1;
    while(i<=2*n-n)
    {
        c=c*i;
        i=i+1;
    }
    int first=a/(b*c);
    a=1,b=1,c=1,i=1;
    while(i<=2*n)
    {
        a=a*i;
        i=i+1;
    }
    i=1;
    while(i<=n-1)
    {
        b=b*i;
        i=i+1;
    }
    i=1;
    while(i<=2*n-(n-1))
    {
        c=c*i;
        i=i+1;
    }
    int second=a/(b*c);
    printf("%d\n",first-second);
    return 0;
}

程式碼中,變數a、b、c分別表示$C^{a}_{b}$中的$a!$、$b!$、$(a-b)!$

當輸入$n=6$時,程式輸出第6個卡特蘭數「132」了!
你可能會覺得:程式碼好冗長呀~
然後心裡想說:等一下一定會教一個更簡單的方法
咦?XD

沒錯!
接下來,本章會教你,怎麼利用「函式 (Function)」來化簡你的程式碼!

2016年5月10日 星期二

給新手的C++教學 (上冊) - 8. 字元 & 字串 (Charactor & String)

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

上一章

不知你是否嘗試過讓程式做到以下事情:
輸入一個名字 (大小寫字母組成),輸出「Hello, 名字!」

1. 土法煉鋼法

我們已經學過怎麼輸入一個字元 (甚麼是字元?),也知道怎麼用直接的方式 (用兩個「'」框起來) 表示一個字元
所以,我們可以一個一個的輸入字元,然後一一判斷是不是大小寫字母,當輸入的字元不是大小寫字母時,我們就知道一個「名字」已經輸入完了 (因為名字只能由大小寫字母組成)

套用上一章所學的簡化方式,我們就可以實現這個輸入名字的功能 (以下程式碼已經假設名字的長度$\leq$一百萬):

#include<cstdio>
int main()
{
    char name[1000001];
    int i=0;
    while(1==1)
    {
        scanf("%c",&name[i]);
        char c=name[i];
        if(c!='a'&&c!='b'&&c!='c'&&c!='d'&&c!='e'&&c!='f'&&c!='g'&&c!='h'&&c!='i'&&c!='j'&&c!='k'&&c!='l'&&c!='m'&&c!='n'&&c!='o'&&c!='p'&&c!='q'&&c!='r'&&c!='s'&&c!='t'&&c!='u'&&c!='v'&&c!='w'&&c!='x'&&c!='y'&&c!='z'&&c!='A'&&c!='B'&&c!='C'&&c!='D'&&c!='E'&&c!='F'&&c!='G'&&c!='H'&&c!='I'&&c!='J'&&c!='K'&&c!='L'&&c!='M'&&c!='N'&&c!='O'&&c!='P'&&c!='Q'&&c!='R'&&c!='S'&&c!='T'&&c!='U'&&c!='V'&&c!='W'&&c!='X'&&c!='Y'&&c!='Z')break;
        i=i+1;
    }
    printf("Hello, ");
    int j=0;
    while(j<i)
    {
        printf("%c",name[j]);
        j=j+1;
    }
    printf("!\n");
    return 0;
}

我才不信你會想這樣搞咧,對吧?
52個字母一一判斷實在是太累了,而且容易打錯

很幸運地,對電腦來說,「一個字元」其實就是「一個數字」
例如:「M」對應到「77」、「o」對應到「111」
如果你硬要把這些字元用整數的「%d」輸出 (而不是字元的「%c」),你看到的就是這些字元所對應到的數字
我用以下程式碼做示範:

#include<cstdio>
int main()
{
    printf("%d %d\n",'M','o');
}

沒意外的話,程式會輸出「77 111」

程式輸出「77 111」了!

因此,你甚至可以把每個直接表示的字元用數字來取代
把上面輸入一個名字的程式改寫成這樣:

#include<cstdio>
int main()
{
    char name[1000001];
    int i=0;
    while(1==1)
    {
        scanf("%c",&name[i]);
        char c=name[i];
        if(c!=97&&c!=98&&c!=99&&c!=100&&c!=101&&c!=102&&c!=103&&c!=104&&c!=105&&c!=106&&c!=107&&c!=108&&c!=109&&c!=110&&c!=111&&c!=112&&c!=113&&c!=114&&c!=115&&c!=116&&c!=117&&c!=118&&c!=119&&c!=120&&c!=121&&c!=122&&c!=65&&c!=66&&c!=67&&c!=68&&c!=69&&c!=70&&c!=71&&c!=72&&c!=73&&c!=74&&c!=75&&c!=76&&c!=77&&c!=78&&c!=79&&c!=80&&c!=81&&c!=82&&c!=83&&c!=84&&c!=85&&c!=86&&c!=87&&c!=88&&c!=89&&c!=90)break;
        i=i+1;
    }
    printf("Hello, ");
    int j=0;
    while(j<i)
    {
        printf("%c",name[j]);
        j=j+1;
    }
    printf("!\n");
    return 0;
}

測試看看,程式依然是同樣的邏輯!

輸入「Mobius」,程式依然是輸出「Hello, Mobius!」
(順帶一提,「Mobius」是我們「105級高雄中學科學班成果發表會的名稱,歡迎大家前去看看~~~)