書名:高中程式設計使用C/C++
出版商:泉勝出版公司
作者:洪國勝
序言
高中程式設計為2學分選修課,18週,所以規劃以下教材大綱與目錄,頁數200頁左右。
著作權聲明
本書著作權屬與洪國勝,洪國勝所屬公司網站是 www.goodbooks.com.tw 著作權屬於洪國勝。
著作財產權聲明
本電子教材財產權屬於泉勝出版,僅供老師選書參考,請共同尊重智慧財產權,不可散播此檔案,也不可將此全部或部分檔案複製成為自己上課教材,這樣以後沒有傻瓜願意繼續編輯與投資教材,以後也沒有教材讓老師們複製了。
選用紙本教材優點
選用本教材,學生看者紙本,將範例程式打一次,就是很好的學習過程與方式,老師也有時間喝口水喘口氣,快快樂樂春風化雨到六五。老師自編電子書教學,學生只會複製與貼上,永遠不會自己除錯,反而害了學生。
本書特色
1、用範例闡述指令。本書用範例闡述程式指令。這樣才會輕鬆明瞭。
2、程式解說融入程式。本書採用一面講解,一面寫程式,這樣學生才能很快融入程式情境。不會程式一大堆,程式寫完了才解說,這樣學生根本看不懂。
3、充分的自我練習。程式設計不是老師一直講,也不是學生一直讀,一定要讓學生依樣畫葫蘆,讓學生看著範例作出與範例相近的自我練習,這樣才是舉一反三,這樣學習才有效果,可以很快開竅,並自己寫出驚人程式。
4、單元教學。本書所有程式都很精簡,這樣學生才能專注的學習每個重點。
目錄
第一單元 程式的編輯、編譯與執行
第二單元 算術運算
第三單元 資料的種類與亂數的產生
第四單元 程式的輸出入
第五單元 程式的除錯
第六單元 決策if運算
第七單元 for迴圈
第八單元循序法
第九單元 while迴圈
第十單元 二分法
第十一單元 巢狀迴圈
第十二單元 一維串列
第十三單元 二維串列
第十四單元 函式
第十五單元 用Python學英文
第十六單元 時間
第十七單元 排序
第十八單元 搜尋
第一單元 程式的編輯、編譯與執行
目前C/C++ 語言常用熱門的開發環境有Code::Blocks、Dev-C++,因為APCS 考場採用Code::Blocks,所以本書介紹Code::Blocks
如下:
Code::Blocks
Code::Blocks 是目前最熱門的C/C++ 自由整合式開發環境(IDE),APCS 考試也提供此IDE,Code::Blocks 官網(https://www.codeblocks.org/),其下載與安裝方式如下:
下載軟體
點選「Downloads」,畫面如下圖:
點選「Download the
binary release」,畫面如下圖:(往下捲動)
初學者請直接點選「codeblocks-20.03mingw-setup.exe」,因為它才有內含「C/C++」編譯軟體,否則需自備編譯軟體。
安裝軟體
下載的檔案即是「.exe」執行檔,請在「下載區」點按程式兩下,就可自動執行,開啟「Code::Blocks」,畫面如下圖:
範例1a試寫一程式,可以於螢幕輸出"Hello"。
提示:本例所需程式僅為cout<<"Hello world!";。
操作步驟
Step 1 開新專案。點選功能表的「File → New → Project」,畫面出現要求點選專案類型,本例點選『Console application』/『Go』,如下圖。
出現歡迎畫面,如下圖,請點選「skip」。
Step 3 接著,要求點選開發C 或C++,本例點選「C++」。
Step 4 點選專案名稱與資料夾位置,本例於「Project title」輸入a1,資料夾位置為ch01,如下圖。
Step 5 點選輸出路徑,本例使用預設值,如下圖。
Step 6 完成以上設定,並展開下圖Sources
的main.cpp,畫面如下圖。
Step
7 編譯程式。點選功能表的「Build → Build」。
Step
8 執行程式。點選功能表的「Build → Run」。
(以上Step 7、8 兩個步驟,亦可點選工具列的「Build and Run」。)
Step
9 以上cout << "Hello world!"
<< endl;,就是本例所執行的程式,往後要寫任何的程式,只要將此敘述刪除,並在此位置寫下程式即可。
Step
10 開啟檔案總管,全部檔案如下圖:(本例於Step 4 的「Project title」輸入為a1,資料夾位置點選ch01,系統會自動建立a1 資料夾)。
Step
11 調整編輯器字型大小。點選功能表「Settings」/「Editor」,畫面如下圖,繼續點選「Choose」,即可依照指示完成字型大小的設定。
Step
12 若出現找不到編譯器?(若之前有安裝其他C 語言,例如Dev-C++,有可能系統誤判而找不到編譯器)
1. 請點選功能表「Setting」/「Compiler」,畫面如下圖,在此畫面中,可以指定要使用的編譯器版本。(C++ 語言編譯器版本非常多,分別是11、14與17 等等,往後線上查詢時就會明瞭。)
2. 繼續點選「Toolchain
executables」,畫面如下圖,請留意您的編譯器路徑是否正確,若不正確請在此修改。
以下程式可計算長方形的面積與周長,請練習於main() 內輸入程式,並觀察執行結果。程式執行結果
int a=3;
int b=4;
int c,d;
c=a*b;
d=2*(a+b);
cout<<"面積="<<c<<endl;
cout<<"周長="<<d<<endl;
加上系統預設的程式樣版,全部程式如下:
#include <iostream>
using namespace std;
int main()
{
int a=3;
int b=4;
int c,d;
c=a*b;
d=2*(a+b);
cout<<"面積="<<c<<endl;
cout<<"周長="<<d<<endl;
return 0;
}
1. 本例若不指定命名空間,也就是不寫using namespace std;則每次鍵入cout、cin 時,都要指定命名空間std::,程式如下:
#include <iostream>
int main() {
std::cout<<"Hello";
return
0;
}
2. 本例因為使用cout 物件,所以要預先載入其函式庫
#include
<iostream>
3.C 的函式庫均為.h, 例如: 數學函式庫為math.h。為了方便區分,C++ 新增函式的函式庫,則均沒有.h,例如:C++ 新增cmath 用來包含與取代math.h。又例如:C++ 新增的輸出入物件為cout 與cin,其函數庫為iostream 則用來取代 <stdio.h> 函式庫的scanf() 與printf()函式。
4. 鍵入程式應該要有層次感。例如:函式實作應該要使用 Tab 鍵內縮(初學者常用空白鍵內縮,那會很吃力,且無法完全整齊)。例如:以下的cout<<"Hello";,請先鍵入 Tab 鍵,再鍵入程式。
int main() {
cout<<"Hello";
return 0;
}
自我練習
1、以下是計算一元二次方程式兩根的程式,請自行練習鍵入程式。
#include <iostream>
#include <cmath>
using namespace std;
int main()
{
int a=1;
int b=-7;
int c=6;
double d,x1,x2;
d=b*b-4*a*c;
x1=(-b+sqrt(d))/(2*a);
x2=(-b-sqrt(d))/(2*a);
cout<<x1<<endl;
cout<<x2<<endl;
return 0;
}
第2單元 算術運算
前面第1單元,我們已經給一個計算長方形面積的程式,讓大家鍵入程式,觀察執行結果,本單元就要開始介紹如何『設計』程式。
範例2a已知長方形的長與寬,請寫一個程式,求其面積。
資料的數位化
1、本題若使用掌上型計算機,其方法是直接將鍵入『長*寬=』,就可得到答案。例如,鍵入『15*8=』,就可得到答案『120』。
2、但使用電腦計算,必須先將所要計算的值先以一個英文代號儲存,例如a,b或score,此稱為『變數』。目標是將資料與程式分開,這樣當資料改變時,還可重複計算。而且,計算過程都是以程式語言描述,此稱為程式設計,只要第一次對,往後都對,計算結果有一致性。不用像計算機要按兩次,才能確認計算結果正確。
3、評估資料來源的大小。每一種資料均需要不同大小的記憶體儲存,電腦為了有效率的處理這些資料,所以有資料型態的規劃,也就是大的資料用大盒子裝,小的資料用小盒子裝,如此一來,即可節省記憶體,又加快處理效率。反過來說,若不分資料大小,通通用大盒子裝資料,那將會非常浪費記憶體,也拖慢執行效率,就像滑鼠都用冰箱的箱子裝,當然可以,但就會很浪費空間,且搬運很費時。下表是C/C++語言的數值資料型態,unsigned表無號整數,即非負數整數:
數值資料型態 |
佔用記憶體的大小(位元) |
所能代表的數值的範圍 |
short |
16 |
-32,768 ~ +32,767 |
int |
32 |
-2,147,483,648 ~ +2,147,483,647 |
long |
32 |
-2,147,483,648 ~ +2,147,483,647 |
unsigned short |
16 |
0 ~ 65,535 |
unsigned int |
16 |
0 ~ 4,294,967,295 |
unsigned long |
32 |
0 ~ 4,294,967,295 |
float |
32 |
3.4x10-38 ~ 3.4x1038 |
double |
64 |
1.7x10-308 ~ 1.7x10308 |
long double |
80 |
3.4x10-4932 ~ 3.4x104932 |
上表有點複雜,所以取常用資料型態如下:初學者遇到整數就取int,遇到浮點實數就取系統預設的double。
數值資料型態 |
佔用記憶體的大小(位元) |
所能代表的數值的範圍 |
int |
32 |
-2,147,483,648 ~ +2,147,483,647 |
double |
64 |
1.7x10-308 ~ 1.7x10308 |
4、變數的宣告
變數宣告的優點是可配置恰當的記憶體而提高資料的處理效率。例如,有些變數的值域僅為整數,則不用宣告為float或double。此即為小東西用小箱子裝,大東西用大箱子裝,才能有效運用空間與提升搬運效率。C/C++語言的變數宣告語法如下:
資料型態
變數名稱[=初值];
例如,
int
a;
即是宣告變數 a 為int 型態。變數的宣告亦可連同初值一起設定,如下所示:
double
d = 30.2;
宣告d是double型態,
並設其初值是30.2。以下程式,同時宣告兩個整數,且指派其初值。
int
f1=3,f2=4;
變數經過宣告之後,編譯器即會根據該變數的資料型態配置適當的記憶體儲存此變數,所以若要提高程式的執行效率,則應儘量依照資料性質,選擇佔用記憶體較小的資料型態。本例變數宣告與賦與初值如下:
int a=15,b=8;
5、使用程式語言寫出運算結果。前面已將初值以變數儲存,面積的計算也是先將結果先以變數儲存如下,本例宣告面積以area儲存,且其型態是int。
int area;
area=a*b;
6、輸出結果。本例將結果輸出如下:
cout<<area;
7、全部程式如下:
#include <iostream>
using namespace std;
int main()
{
int a=15,b=8;
int area;
area=a*b;
cout<<a;
return 0;
}
識別字(Identifiers)
真實的世界裡,每個人、事、物都有一個名稱,程式設計亦不例外。於程式設計時,必須為每一個變數、常數、函式、結構及類別命名,以上所有變數、常數、函式、結構及類別等名稱,統稱為程式語言的識別字。C/C++語言的識別字命名規則如下:
1. 識別字必須是以字母(大小寫的A 至Z)或底線(_)開頭。例如:以下是一些合法的識別字。
a
i
sum
_sum
Income
以下是一些非法的識別字。
7eleven
// 不能由數字開頭
%as //不能由符號開頭
2. 識別字由字母開頭後,僅可由字母、底線及數字組合而成,但不得包含空白。例如:以下是一些合法的識別字。
a123
a123b
a_b
以下是一些非法的識別字。
A=
//不能含有 = 號 */
sum!
//不能含有 ! 號 */
Age#3 //不能含有 # 號 */
a
c // 不能含空白
c+3 // 不得含有加號 */
3. 識別字的長度不可以超過32 個字元。
4. 識別字的大小寫均視為不同,例如Score、score 及SCORE 皆代表不同的識別字。
5. 識別字不得使用保留字,如if、for 等。但是,if1、fora 等則可使用。
保留字(Keywords)
保留字(又稱關鍵字)是任一程式語言已事先賦予某一識別字(可識別的文字或字串,稱為識別字)一個特別意義,所以程式設計者不得再重複賦予不同的用途。例如if已賦予決策敘述,程式設計者當然不得再定義if為另外的用途,以下是C/C++語言的保留字,請於 https://en.cppreference.com/w/點選
『Keywords』。
算術運算子(Arithmetic operators)
算術運算子用來執行一般的數學運算,包括指派(=)、取正負數( +/- )、加( + )、減( -
)、乘( * )、除( / )、取餘數(%)、遞增(++)及遞減(--)等,下表是C/C++語言的算術運算子列表:
運算子 |
定義 |
優先順序 |
結合律 |
= |
指派 |
14 |
由右至左 |
++,-- |
後置遞增/遞減 |
1 |
由左至右 |
++/-- |
前置遞增/遞減 |
2 |
由右至左 |
+/- |
正負號,一元運算子 |
2 |
由右至左 |
* |
乘法運算 |
3 |
由左至右 |
/ |
除法運算 |
3 |
由左至右 |
% |
求餘數(Modulus) |
3 |
由左至右 |
+/- |
加法/減法運算 |
4 |
由左至右 |
以上運算子的運算結果、運算子優先順序、運算子結合律等,分別說明如下:
指派運算子(Assignment operators)
指派運算子的符號為(=),又稱為賦值運算子,其作用為將運算符號右邊運算式的值指派給運算符號左邊的運算元。所以,以下敘述sum=sum+a是將sum+a先運算,再將運算結果的值指派給sum。
int
sum = 0,a = 3;
sum
= sum + a;
上式與數學的『等號』是不同的,所以不要一直糾結為什麼0會等於8。其次,你是不能將常數放在指派運算子的左邊,例如,
8
= a ;
此為一個不合法的敘述,但以下敘述,將常數8指派給變數a是合法的。
a
= 8 ;
算術五則運算
以下是一些算術五則運算,請鍵入以下程式,並寫出執行結果。
#include <iostream>
using namespace std;
int main() {
int
x=5, y=4;
cout
<<x+y<<endl; // 9
cout
<<x-y<<endl; // 1
cout
<<x*y<<endl; // 20
cout
<<x/y<<endl; // 1 兩者都是整數,商也是整數
cout
<<x%y<<endl; // 1
return
0;
}
整數除法或實數除法
C/C++ 語言的除法運算,只有被除數與除數的型態均為整數,才是整數除法,得到整數商。其次,只要被除數與除數有一型態為實數即為實數除法,得到實數商。請鍵入以下程式,並寫出執行結果。
int main() {
int
x=5, y=4;
double
z=4;
cout
<<x/y<<endl; // 1
cout
<<x/z<<endl; // 1.25
cout
<<y/x<<endl; // 0
cout
<<z/x<<endl; // 0.8
z=x/y;
cout<<z<<endl;
//
}
整數除法與取餘的應用
整數除法與取餘可以將一個整數分解為數個數字。例如:若要將一個整數152 分解為1、5、2 三個數字,其方法如下:
int
a=152;
int
a3=152%10; // 個位數
a=a/10;
int
a2=a%10; // 十位數
a=a/10;
int
a1=a ; // 百位數
cout<<a1<<a2<<a3;
取餘
若要讓一個數字在累加的過程中,保持一定的循環,那也是用取餘。例如:
while(1)
{ // 無窮迴圈,參看第6 單元
b=a[i];
i=(i+1)
%4;
}
那i 就永遠在0、1、2、3 循環,這樣i才不會越來越大,讓索引溢位。
程式與數學的差異
數學有
19/10=1…9
的書寫習慣,但電腦並沒有此運算方式,因此以上運算方式,一定要先取餘數,再求整數商如下:
int
a=19,b=10;
int c=a%b;
int d=a/b;
順序錯也不行,以下程式,先除再取餘數,結果就不一樣。
int
a=19,b=10;
int d=a/b;
int
c=a%b;
自我練習
1. 請指派一個四位數,並將其分解輸出為四個數字。例如:輸入1234,可以輸出4,3,2,1,且輸出其數字和,本例為10。
2. 請指派一個0 到86399 的整數,並分解為HH:MM:SS 等時間格式。
3. 請任意指派一個5 位數,請問如何分解為兩個一組。例如:a=25678,如何分別得到78,67,56,25 等4 個數字;其次,要如何得到78,56,2 等三組數字呢。
4. 請任意指派一個5 位數,如何得到最左邊與最右邊數字的和。例如:a=12345,那結果是6。
5. 請任意指派一個5 位數,那如何得到最左邊兩位數與最右邊兩位數字的和。例如:a=12345,那結果是12+45=57。
6. 請任意指派一個6 位數,那如何得到最左邊三位數與最右邊三位數字的和。例如:a=123456,那結果是123+456=579。
7. 請任意指派一個6 位數, 並計算其奇位數與偶位數之和。例如:a=123456,那結果是12 與9。
遞增(++)及遞減(––)
遞增(++)及遞減(––)是C/C++ 語言特有的運算子,此二個運算子又分為前置與後置,前置是運算子在運算元之前,如:
a=1;++a;cout<<a<<endl;
// 2
後置是運算子在運算元之後,如:
a=1;a++;cout<<a<<endl;
// 2
原則上不論++a 或a++ 都是將a 值加1 並放回a,但若是
a=1;b=++a;
// a=a+1;b=a;2 2
和
a=1;b=a++
; // b=a;a=a+1;2 1
則其a 值均會加1,但b 值會有差異,前置b 值會得到加1 的結果,後者只能得原a 值。請鍵入以下程式,寫出執行結果。程式執行結果
#include <iostream>
using namespace std;
int main() {
int
a,b;
a=1;++a;cout<<a<<endl;
a=1;a++;cout<<a<<endl;
a=1;b=++a;cout<<a<<endl;cout<<b<<endl;
a=1;b=a++;cout<<a<<endl;cout<<b<<endl;
return
0;
}
複合指派運算子
結合指派與算術的運算子稱為複合指派運算子,此乃C語言特有的運算子,例如程式設計者常會鍵入sum=sum+5,程式語言乃制定此一複合指派運算子『+=』,所以上述sum=sum+5,即可寫成sum + = 5,下表是C/C++語言常用的複合指派運算子:
運算子 |
定義 |
優先順序 |
結合律 |
= |
指派內容 |
14 |
由右至左 |
+= |
相加之後再指派內容 |
14 |
由右至左 |
-= |
相減之後再指派內容 |
14 |
由右至左 |
*= |
相乘之後再指派內容 |
14 |
由右至左 |
/= |
相除之後再指派內容 |
14 |
由右至左 |
%= |
取餘之後再指派內容 |
14 |
由右至左 |
例如,
int
sum=0,a=5;
sum+=5;
cout<<sum;//5
sum/=a;
cout<<a;//1
運算子的優先順序(Precedence)
同一敘述,若同時含有多個運算子,此時即需定義運算子的優先順序。例如:
x=a+b*c;
在數學裡,我們定義先乘除再加減,程式語言也是相同,必須定義這些運算子的優先順序,C語言的運算子優先順序如下表:
優先順序 |
運算子 |
說明 |
結合律 |
1 |
++,-- |
後置遞增與遞減。例如a++,a--。 |
由左至右 |
2 |
++,-- +/- ! |
前置遞增與遞減。例如++a,--a。 取正或取負。 邏輯否定。 |
由右至左 |
3 |
*,/,% |
算術乘、除、取餘。 |
由左至右 |
4 |
+,- |
算術加、減 |
|
6 |
>,>=,<,<= |
關係運算的大小。 |
|
7 |
==,!= |
關係運算的相等或不相等。 |
|
11 |
&& |
邏輯的and。 |
|
12 |
|| |
邏輯的or。 |
|
14 |
=,+=,-=,*=,/=,%= |
指派與複合指派。 |
由右至左 |
由以上各運算子的『優先順序』可知,乘號『*』的優先順序是第3,而加號『+』則是第4。所以,以上敘述:
x=a+b*c;
的結果與
x=(a+(b*c));
的效果相同。同理,
x=a>b && b>z;
的結果同義於
x=(a>b)
&& (b>z);
自我練習
1、鍵入、執行以下程式,並寫出執行結果。
程式 |
執行結果 |
#include <stdio.h> #include <stdlib.h> int main() { int
a,b,c; a=1;b=2;b=3; a=a+a*2/2-3%2; cout<<a<<endl; a=5;b=4; c=
a>2 && !(b>3)
||(a==3); cout<<c; return
0; } |
|
運算子的結合律(Associativity)
當同一敘述,相鄰的運算子擁有相同優先順序的運算子,此時即需定義運算子是『由左至右』的左結合或『由右至左』的右結合。例如:
x=a-b-c;
同樣是減號(-),優先順序相同,此時就要靠定義結合律,減法結合律是由左至右,所以以上同義於
x=((a-b)-c);
而
a=b=c=2;
指派運算子的結合律是由右至左,所以以上式子同義於:
(a=(b=(c=2)));
以上式子,a、b、c的結果都是2。
自我練習
1、鍵入、執行以下程式,並寫出執行結果。
程式 |
執行結果 |
#include <stdio.h> #include <stdlib.h> int main() { int
a=3,b=2,c=1; c=a-b-c; cout<<c; a=b=c=2; cout<<a<<b<<c<<endl; return
0; } |
|
關於以上運算子的詳細說明可點選https://en.cppreference.com/w/c裡面的『Expressions』,如下圖:
繼續點選上圖的『operator
precedence 』,還可得運算子的優先順序,如下圖:
次方與根號
C/C++ 語言的算術運算子只有以上+, –, *, /, %,若所需運算沒有運算子,那就要用數學函式。例如:您想要次方或開根號運算應,因為C/C++ 並沒有次方運算子(^)與開根號,所以若要執行次方運算,那就要使用數值處理函式中的pow() 函式,如下所示為計算3 的平方:,
a=pow(3,2); //
include<math.h> 或<cmath>
若要執行根號運算,則應使用數值處理函式的sqrt() 函式。如以下敘述是計算9 的開根號。
x=sqrt(9); // include<math.h> 或<cmath>
但以上數值函數,C 語言是放在math.h,C++ 是放在cmath,因為C++ 包含C,所以在標頭檔通通使用
#include<cmath>
載入函式,就可以使用所有數學函式。請留意以上敘述載入標頭檔,不用分號「;」結束。請鍵入以下程式,並觀察執行結果。
自我練習
1、請寫一程式,可以指派長方體的長、寬、高,計算其表面積與體積。
範例2b請寫一程式,滿足以下條件。
(1)
可以指派兩個座標。
(2)
計算此兩點座標距離。
(3)
輸出此兩點距離。
(4)
例如:P(0,3)與Q(4,0)的距離是5。
解題步驟
1.資料的數位化。
int
x1=0,y1=3;
int
x2=4,y2=0;
2.寫出演算法。本例已知兩點座標分別是(x1,y1),(x2,y2),則其距離的公式的數學語言是:
3.將演算法以程式語言表示。
double
d=sqrt(pow((x1-x2),2)+pow((y1-y2),2));
cout<<d;
自我練習
1.已知三角形三邊長a、 b、 c,求其面積。
提示:先計算d=(a+b+c)/2,則三角形面積= ,本例假設所輸入的三角形三邊長可圍成三角形,例如:指派int a=3,b=4,c=5;則得三角形面積6,但並不是任意三條線都可圍成三角形,若要判斷是否可圍成三角形,請繼續研讀下一單元。
計數器
日常生活常需要計數,例如,景點通常有一個計數器,累計今天進園人數,程式設計也不例外,常常需要統計執行幾次,此件事由電腦做的程式如下:首先,先宣布與清除計數值變數。
int num=0;
每執行一次計數值加1的程式如下:
num=num+1;
請鍵入以下程式,並觀察執行結果:
#include <iostream>
using namespace std;
int main()
{
int num=0;
int a=8,b=3;
a=a-b;
num=num+1;
a=a-b;
num=num+1;
cout<<a<<endl;
cout<<num<<endl;
return 0;
}
自我練習
請鍵入以下程式,寫出執行結果。
題號 |
題目 |
輸出結果 |
1 |
#include <iostream> using namespace std; int main() { int
a=321; int
s=0; int
num=0; int
b; b=a%10; s=s+b; a=a/10; num++; cout<<"b="<<b<<endl; cout<<"s="<<s<<endl; cout<<"a="<<a<<endl; cout<<"num="<<num<<endl; b=a%10; s=s+b; a=a/10; num++; cout<<"b="<<b<<endl; cout<<"s="<<s<<endl; cout<<"a="<<a<<endl; cout<<"num="<<num<<endl; b=a%10; s=s+b; a=a/10; num++; cout<<"b="<<b<<endl; cout<<"s="<<s<<endl; cout<<"a="<<a<<endl; cout<<"num="<<num<<endl; return
0; } |
|
變數內容的交換
程式設計常常需要將兩個變數的內容交換,兩個變數的內容要交換,就如同兩隻手的東西要交換位置。所以假設你有a、b 兩隻手,各拿一樣東西,那要交換其位置的方法如下:
1. 先找來第3 隻手t。
2. 將a 的東西交給t 暫存。
t=a;
3. 將b 的東西交給a。
a=b;
4. 將t 的東西交給b,而完成兩隻手東西的交換。
b=t;
5. 其次,若未先找來第三之手t 幫忙,電腦並沒有這個能力,同時拋出雙手東西,再同時接住另一手的東西,如以下敘述:
a=b;
b=a;
6. 這就是一種運算思維,電腦運算要很明確,全部程式如下:
#include <iostream>
using namespace std;
int main() {
int
a=3,b=4;
int
t;
t=a;a=b;b=t;
cout<<"a="<<a<<endl;
cout<<"b="<<b<<endl;
return
0;
}
自我練習
試寫一程式,可以指派三個數,並將1
交給2、2 交給3、3 交給1,並輸出。
資料抽象化
若有一直線方程式是ax+by+c=0,點p(m,n)到直線的距離是
這件事若要由電腦做,就是將資料從人類約定的書寫習慣ax+by+c=0獨立抽象出來。例如,直線方程式是3x+4y+5=0,求點p(1,2)到直線的距離,首先,以
int
a=3,b=4,c=5;
約定此為直線
3x+4y+5=0
然後以
int
m=1,n=2;
約定此為p(1,2),所以全部程式如下:
#include
<iostream>
#include
<cmath>//使用abs() and sqrt()
using namespace
std;
int main( )
{
int a=3,b=4,c=5;
int m=1,n=2;
double d;
d=abs(a*m+b*n+c)/sqrt(a*a+b*b);
cout<<d;//3.2
return 0;
}
範例2c
寫一個程式,可以指派一個一元二次方程式ax2 + bx + c
= 0的係數a,b,c,並求其解(本例假設所輸入的方程式恰有二解)。
參考解答
解一元二次方程式的公式法,演算步驟如下:
(1) 設有一元二次方程式如下:
ax2 + bx + c = 0
(2)輸入a,b,c三個整數。(本例假設整係數方程式,先指派其為a=2;b=-7;c=3)
(3)令d=。提示:此為數學語言,C/C++語言是d=sqrt(b*b-4*a*c); ,括號、乘號均不能省。)
(4) 則其二解分別為,。(提示:此為數學語言,C/C++語言是x1=(-b+d)/(2*a),括號、乘號均不能省。)
(5)例如,2x2-7x+3=0。其解為x1=3.0 ,x2=0.5。
參考解答
本例先假設所指派的係數一定有實數解,待下一單元再判斷所輸入係數有沒有實數解。
#include
<iostream>
#include
<cmath>//使用 sqrt()
using
namespace std;
int
main( )
{
int a=2,b=-7,c=3;
double d=sqrt(b*b-4*a*c);
double x1=(-b+d)/(2*a);
double x2=(-b-d)/(2*a);
cout<<x1<<endl;
cout<<x2;
return 0;
}
什麼是『運算思維』?
近來運算思維廣為被大家討論,筆者淺見是各有各的特性與優勢,所謂運算思維,就是要學習電腦有哪些特性與優勢,並使用電腦的運算思維寫程式。以本範例解一元二次方程式為例,人類用十字交叉法較快,但是電腦使用公式法較快,此即為電腦的運算思維,往後各單元還有更多電腦運算思維,學習這些運算思維,就可增加程式設計功力。
自我練習
1、寫一個程式,可以指派一個二元一次方程式,並求其解(本例假設所指派的方程式恰有一解)。
提示:解二元一次方程式的克拉馬公式演算過程如下:
(1). 設二元一次方程式如下:
(2)資料的抽象化。本例可指派a1,b1,c1,a2,b2,c2等六個整數。
(3) 令 = a1b2 – a2b1。
(4). 則其解分別是
(5)例如,
3x+y=5
x-2y=-3
指派變數如下:
a1=3;b1=1;c1=5;
a2=1;b2=-2;c2=-3;
則其解為
x=1 y=2
補充說明
解二元一次方程式,國中會先教代入消去法與加減消去法,這都需要一點判斷,但可以簡化計算,本題使用公式法,可完全不用判斷,直接計算而得,這樣最適合計算機了,也是電腦的運算思維。
亂數
程式設計常常需要一些任意整數來測試,或模擬結果,此時就需要請電腦取亂數, C++ 取亂數的方法較為複雜,以下是C語言取亂數的方法。
rand()
C 語言傳回0 到32767 的亂數,例如:
int
a=rand();
cout<<a;
傳回0 到32767 的任意整數。使用前應先匯入
#include
<stdlib.h> // 使用rand()
但電腦不是萬能,要如何於亂數表任意選擇一個起點呢?因為每次執行的系統時間不同,所以就可以以系統時間,當作亂數的起點,全部程式如下:
#include <iostream>
#include <time.h> // 使用time()
#include <stdlib.h> // 使用rand()
using namespace std;
int main()
{
srand(time(NULL));
int
a=rand();
cout<<a;
return
0;
}
以下程式,可取0 到5 的任意整數。
int
a=rand()%6;
以下程式,可取1 到6 的任意整數。
int a=1+rand()%6;
小寫字元的ASCII是97∼122,以下程式,可產生1個小寫字元。
#include <iostream>
#include <time.h> // 使用time()
#include <stdlib.h> // 使用rand()
using namespace std;
int main()
{
srand(time(NULL));
int
a=97+rand()%26;
cout<<a<<endl;
cout<<(char)a;
return
0;
}
自我練習
1、
請問如何取3到8的亂數。
2、
請問如何取小數點兩位的實數亂數。
發聲
要讓電腦發出聲音,可使用_beep()函式,此函式C語言放在stdlib.h,所以要載入標頭檔
#include <stdlib.h>,C++則放在<iostream>,其與法如下:
void
_beep(unsigned int x,unsigned int y);
x是要發出的頻率,單位是Hz,y是發聲的時間,單位是ms。其次,鋼琴鍵盤頻率對照表如下:
G1003
例如,以下敘述可發出『Do』的音,且持續0.5 秒。
_beep(523,500);
又例如,以下程式可發出Do、Re、Me、Fa…等八個音。
#include
<iostream>
int main()
{
_beep(523,500);
_beep(587,500);
_beep(659,500);
_beep(698,500);
_beep(784,500);
_beep(880,500);
_beep(988,500);
_beep(1046,500);
return 0;
}
演奏音樂
要讓電腦演奏音樂,那就要先下載一個簡譜,如下圖。(摘自http://blog.roodo.com/midiland/archives/1679070.html,特別致謝)
G1004
本例一分鐘80拍,以一個四分音符為1拍,所以1拍的時間是,60000ms/80。上圖一個八分音符所佔的時間是60000ms/(2*80),每小節是2拍。其次,上圖所有音符的最小速度是八分音符,所以我就取八分音符的時間為1個單位。以下僅作4 小節,『我有一隻小毛驢我從來也不騎』。
#include
<iostream>
int main()
{
int t=60000/160;
_beep(523,t);
_beep(523,t);
_beep(523,t);
_beep(659,t);
_beep(784,t);
_beep(784,t);
_beep(784,t);
_beep(784,t);
_beep(880,t);
_beep(880,t);
_beep(880,t);
_beep(1064,t);
_beep(784,4*t);
return 0;
}
自我練習
1、
請繼續完成以上音樂。
2、
請用輸出指令讓輸出音樂的同時,銀幕也輸出歌詞,那就是KTV了。
3、
請自己找一首歌,完成輸出歌詞與音階。
補充說明
1、請熟悉以上發音方式,第五章還會介紹如何製作電子琴。
2、以上僅輸出一小節,程式就有點冗長,那寫完一首歌不就累垮。請放心,待介紹迴圈與陣列就會明瞭。
警車聲音
警車的警報聲是連續發出頻率265Hz 與350Hz 所形成,以下以C語言示範發出此聲音。
#include <stdio.h>
#include <stdlib.h>
int main()
{
while(1){//無窮迴圈,請看第六章
_beep(265,300);
_beep(350,700);
_sleep(50);//空白
}
return 0;
}
自我練習
1. 市內電話來電大都採用1000Hz 與500Hz 交錯形成的樂音,請寫程式完成。
2. 同上題,練習讓鈴聲可越來越急。(此題可待學完迴圈再作)
3. 音感練習。請觀察您家微波爐、洗衣機、汽車安全帶未繫、倒車警告、手機的各種聲響,並寫程式完成。
4. 作曲練習。請嘗試發出不同頻率的聲音,觀察是否悅耳而吸引人,您是否能作曲呢?
第3單元 字元、字串與布林型態
字元常數(Character literals)
使用單引號(')圍住的單一字元,稱為字元常數,例如'A' 或'a' 等。C++ 語言使用8 bits 的ASCII,所以可表示256 個字元,包含大/小寫英文字母、數字、標點符號及其它特殊符號。C++使用 char
型態儲存字元。例如:
char
a='a';
cout<<a;
字元轉數字
字元轉數字靠轉型。例如:
int main(){
char
a='a';
int
b=(int)a;
cout<<b;
return
0;
}
數字轉字元
數字轉字元也是靠轉型。例如:
int main()
{
int
a=65;
char
b;
b=(char)a;
cout<<b;
return
0;
}
字串(String)
C/C++ 語言中,字串以雙引號(")所圍住,例如:"Gwosheng"、" 臺灣" 等。C使用字元陣列儲存,例如,
char
a[]="gwosheng";
cout<<a;
C++新增 string型態儲存,例如,
string
b="gwosheng";
cout<<b;
且原來的字元陣列也可以在C++使用。請鍵入以下程式,觀察執行結果。
#include
<iostream>
using namespace
std;
int main()
{
char
a[]="gwosheng";
cout<<a<<endl;
string
b="gwosheng";
cout<<b;
return 0;
}
字串的運算
除非要考APCS學科,不然就不用學C的字串處理方式,因為C++處理字串,和上一單元數值處理的習慣較相同,較合乎我們的使用習慣。例如,以下程式是字串的複製、清除與相加:
#include
<iostream>
using namespace
std;
int main()
{
string
a="123",b="456",c;
c=a;
cout<<c<<endl;//123
c="";
cout<<c<<endl;
c=a+b;
cout<<c<<endl;//123456
return 0;
}
字串與數值轉換
字串與數值轉換要使用string
物件的方法,使用前請先載入
#include<string>
or #include<cstring>
但因cstring 包含string,所以本書直接通通載入
#include<cstring>
stoi
將字串轉數值。請鍵入以下程式,並寫出執行結果。
string a="123";
string b="123";
string c=a+b; // 123123
cout<<c<<endl;
int d=stoi(a)+stoi(b);
cout<<d<<endl;
// 246
to_string
將數值轉字串。請鍵入以下程式,並寫出執行結果。
int a=123;
int b=123;
int c=a+b;
cout<<c<<endl;
// 246
string d=to_string(a)+to_string(b);
cout<<d<<endl;
// 123123
鍵入以下程式,寫出執行結果。
#include
<iostream>
#include<string>
using namespace
std;
int main()
{
int a=6;
int n=2;
int r=0;
string
d="";
r=a%n;
a=a/n;
d=to_string(r)+d;
cout<<d<<endl;
r=a%n;
a=a/n;
d=to_string(r)+d;
cout<<d<<endl;
r=a%n;
a=a/n;
d=to_string(r)+d;
cout<<d<<endl;
return 0;
}
更多的物件方法,線上查詢basic_string:https://en.cppreference.com/w/cpp/string/basic_string)
第4單元 程式的輸出入
C++ 使用cout 與cin 物件作為輸出入,分別說明如下:
cout
cout 物件可輸出指定任何文數字與變數內容,而且不用去管變數的資料型態。其語法如下:
cout
<< 字串或變數 [<< 字串或變數] [<<endl] ;
語法中的中刮號"[]" 表示可省略,例如:
int
a=5;
cout<<a;
可輸出5,又例如:
int
a=5;
cout
<<"a="<<a;
則可輸出「a=5」。其中第一個『a』用雙引號刮住『"a="』表示字串內容,將會以字串方式輸出,第二個「a」,則是變數,將會往前找對應變數的內容,且輸出此內容。『endl(endline)』代表此列的輸出結束,跳離此列,往後的輸出移至下一列的開頭。例如:
cout
<<"Good"<<endl;
cout
<<"Good";
可輸出
Good
Good
但是,
cout
<<"Good";
cout
<<"Good";
則輸出
GoodGood
請鍵入以下程式,並觀察執行結果。
#include
<iostream>
using
namespace std;
int main()
{
cout
<<"Good"<<endl;
int
a=5;
cout
<<"a="<<a<<endl;
return
0;
}
cin
cin 物件可輸入文數字至指定的變數。其語法如下:
cin>>
變數 [>> 變數] ;
例如:
char
a;
cin
>>a;
cout
<<"a="<<a<<endl;
可輸入字元至變數a。又例如:
int
b;
cin
>>b;
cout<<"b="<<b<<endl;
可輸入整數至變數b。C語言使用字元陣列表示字串,以下程式可輸入字串:
char
c[5]; // 字元陣列,代表字串,C style
cin>>c;
cout<<c<<endl;
C++語言使用string型態表示字串,以下程式可輸入字串:
string
d; // 字串,C++ style
cin>>d;
cout<<d;
若要輸入含空白字串,例如,"This is a book.",則要使用getline()
函式,程式如下:
string
b;
getline(cin,b);
// 可輸入含空白字串
cout<<b;
以下程式則可連續輸入3 個變數,輸入時,變數之間請以空白隔開,例如:輸入3 4 5 ,則三個變數變數a,b,c 分別得到3,4,5。
int
a,b,c;
cin>>a>>b>>c;
cout<<a<<"
"<<b<<" "<<c;
自我練習
1. 請寫一個程式,程式一開始要求使用者輸入人名,有提示字「Pleaseinput
your name:」,接著要求輸入身高,有提示字「input yourheight」,最後輸出「Your Name is..., your height is...」。
2. 請於「https://en.cppreference.com/w/」搜尋cout 與cin 的語法。
提示: 請點選「Stream-based I/O」。
第5單元 決策運算
人類的生活必須不斷地面對決策問題。程式語言是協助解決人類問題的工具,當然也有決策指令。本單元即是探討C++決策所需使用的運算子與指令。請先鍵入以下程式,並觀察執行結果。
#include
<iostream>
using namespace
std;
int main( )
{
int a=66;
string r="不及格";
if (a>=60){
r="及格";
}
else{
r="不及格";
}
cout<<r;
return 0;
}
以上『>=』稱為關係運算子,『if else』稱為決策運算指令。請繼續建議以下程式,並觀察執行結果。
#include <iostream>
using namespace std;
int main()
{
int
x=3,y=5;
string
r="";
if (x>0
&& y>0){
r="第1象限";
}
cout<<r<<endl;
return 0;
}
以上『&&』稱為邏輯運算子,此為本單元所要介紹的內容。
關係運算子(Relational
Operators)
關係運算子又稱為比較(Comparison) 運算子,用於資料之間的大小比較,比較的結果可得到int 型態的1(true) 或0(false),下表是C/C++ 語言中的關係運算子符號。
例如:
#include <iostream>
using namespace std;
int main() {
int
x=3,y=4;
cout<<(x>0)<<endl;
//1
cout<<(x>=y)<<endl; //0
cout<<(x==y)<<endl; //0
cout<<(x!=y)<<endl; //1
return 0;
}
邏輯運算子(Logical
Operators)
當同一個運算式要同時存在兩個以上的關係運算子時,每兩個關係運算子之間必須使用邏輯運算子連結,例如,您要找男生且年齡大於40,此一選擇就同時含有兩個關係運算式,此時就要使用邏輯運算子。C/C++ 的邏輯運算子有否定not『!』、邏輯and『&&』、邏輯or『 ||』,如下表所示:
!
邏輯!是取反相。例如,
int
x=3;
cout<<!(x>0);//0
&&
邏輯and 是兩件事都true,結果才是true,其餘都是false,其真值表如下:
例如:
int
x=3,y=4;
cout<<((x>0) && (y>=0));
||
邏輯or 是兩件事只要有一件為true,那就為true,只有兩件事全為false,才為false,其真值表如下:
例如:
int
x=3,y=4;
int
x=3,y=4;
cout<<((x>0) || (y<0));
//1
自我練習
1. 若有一數學式,判斷x 是否滿足1<x<=6,請轉換為C/C++ 敘述。
2. 請指派1 個x,判斷是否x<3 或x>7,請以C/C++ 表示。
3. 輸入三角形三邊長a,b,c,圍成三角形的條件是,任兩邊之和要大於第三邊,那如何以C/C++ 語言表示?
提示: 任兩邊之和大於第三邊的數學語言是a+b> c and a+c> b andb+c> a,請將以上數學語言轉為C/C++ 語言。(測資:a=1,b=2,c=7 is 0;a=3,b=4,c=5 is 1)
4. 若有一數學式,同時判斷六個變數是否滿足,請轉換為C/C++ 敘述。(測資:a1=1,b1=2,c1=3,a2=2,b2=4,c2=6
is 1; a1=1,b1=2,c1=3,a2=2,b2=4,c2=8 is 0)
5.同上題, 又如何表示?(測資:a1=1,b1=2,c1=3,a2=2,b2=4,c2=6
is 0; a1=1,b1=2,c1=3,a2=2,b2=4,c2=8 is 1)
if...else
在日常生活領域中,當出現“假如∼則∼,否則∼”時,此種決策流程模式有兩種解決問題的方案,故稱為雙向分歧決策流程,此時可使用if...else敘述。if...else敘述的語法如下:
if(運算式)
{
敘述區塊1;
}
[else
{
敘述區塊2;
}]
以上語法說明如下:
1. 運算式的值若為1(true),則執行敘述區塊1;運算式的值若為0(false),則執行敘述區塊2,其流程圖如下:
請鍵入以下程式,並觀察執行結果。
int main(){
int
a=66;
char
r='';
if
(a>=60)
r='P';
else
r='F';
cout<<r;
}
2.有時為了簡化程式的撰寫,可將否則的部分寫在if前面,並省略else。例如,以下程式同義於上面程式。
int main(){
r='F';
if(a>=60)
{
r=’P’;
}
}
3.if else 後面預設僅執行一個敘述,若要執行兩個以上敘述,請加上{},請要{}對稱排列。請鍵入以下程式,並寫出執行結果。
int main(){ int a=33,b=0,c=0; if (a>=60)
b=b+1;
c=c+1; cout<<b<<endl; cout<<c<<endl; return 0; } |
int main(){ int a=33,b=0,c=0; if (a>=60){
b=b+1;
c=c+1; } cout<<b<<endl; cout<<c<<endl; return 0; } |
4、if()後面不用加分號(;),請鍵入以下程式,並觀察執行結果。
int main(){ int a=33,b=0,c=0; if (a>=60)
b=b+1; cout<<b<<endl; return 0; } |
int main(){ int a=33,b=0,c=0; if (a>=60);
b=b+1; cout<<b<<endl; return 0; } |
8. C語言為了強調語法的簡潔性,若決策流程的結果,只為求得簡單的運算式,則可用以下敘述的三元運算子(?:),
r=(運算式1)?(運算式2):(運算式3)
其中『運算式2』與『運算式3』的括號只是增加程式的可讀性,此兩括號的有無並不影響程式的執行結果。當運算式1的值為1(true)時,z=運算式2,當運算式1的值為0(false)時,則Z=運算式3,例如,請鍵入以下程式,並寫出執行結果。
int main(){
int a=66;
char r;
r=(a>=60)?('P'):('F');
cout<<r<<endl;
return 0;
}
7. 敘述區塊內可以放置任何合法敘述,當然也可以再放置if;if中有if,稱為巢狀if,請看以下範例。
範例 5a
請寫一個程式,完成以下要求:
1. 輸入一個0~100的分數。
2. 當分數大於90分時,輸出A。
3. 當分數介於80~89時,輸出B。
4. 當分數介於70~79時,輸出C。
5. 當分數介於0~69時,輸出D。
【流程分析】
1. 使用流程圖分析如下:
2. 以上每一個決策流程點,都有兩個分歧點,所以適用if~else。
3. 每一個else後面均需進一步決策流程,所以可在每一else後面再放置if。
#include <iostream>
using namespace std;
int main() {
int a=88;
char
r;
if(a>=90) /* 高於90分為A */
r='A';
else
if(a>=80) /* 介於 80與90分為B */
r='B';
else
if(a>=70) /* 介於 70與80分為C */
r='C';
else
r='D'; /* 不符合上述情況則為D */
cout<<r<<endl;
return 0;
}
補充說明
1、此題有人會寫成 if
(90<a<100 ),但C/C++並沒有這種運算式,因為90<a<100
是數學語言,不是程式語言。
2、有人會這樣寫,這樣也可以,這樣可以減少一直縮排。
if(a>=90) //高於90分為A
r='A'
else
if(a>=80)
//介於 80與90分為B
r='B';
else if(a>=70) // 介於 70與80分為C
r='C';
else
r='D'; // 不符合上述情況則為D
cout<<r<<endl;
3、有人會寫成
if (a<100 &&
a>=90) r='A';
if
(a<90 && a>=80) r='B';
if
(a<80 && b>=70) r='C';
if
(a<70 && b>=0) r='D';
這樣雖然也可以,但是其執行效率非常差,因為不管分數為何,僅有一項會成立,但卻都要進行四次判斷,如此會讓電腦不斷進行無效的判斷。而且,電腦的判斷時間遠大於執行計算的時間。
自我練習
1.請寫一程式,由電腦產生-3∼3的整數,電腦判斷是正數、0或負數。
2.某一貨品定價100元,若購買500件,(含)以上打7折,若購買499∼300件則打8折,若購買299∼100件則打9折,購買100件以下則不打折,試寫一程式可以輸入購買件數而得總價。
測試資料:
編號 |
輸入 |
|
1 |
20 |
100*20=2000 |
2 |
200 |
100*200*0.9=18000 |
3 |
400 |
100*400*0.8=32000 |
4 |
500 |
100*500*0.7=35000 |
3.直線。直線標準式為ax+by+c=0,請寫一程式,可以指派一直線係數a,b,c。其次,可再輸入任一點座標,並判斷所輸入點式否在直線上。例如,指派a,b,c分別是1,2,-3,那方程式就是x+2y-3=0,其次,輸入點若是(1,1),是在直線上,若是(1,2),則不在直線上。
4.請寫一程式,可以由電腦產生一個小寫字元,請判斷其是否為母音。說明,字元a,e,i,o,u稱為母音,其餘為子音。
5.請寫一個程式,可以產生一個0到25的亂數,且依以下分數顯示燈號
21∼25:五個燈。
16∼20:四個燈。
11∼15:三個燈。
6∼10:兩個燈。
1∼5:一個燈。
0:零個燈。
範例 5b 請寫一個程式,可以判斷所輸入座標的所在象限。
【程式列印】
#include <iostream>
using namespace std;
int main() {
int x=3,y=4;
char
r;
if(x>0)
if(y>0)
r='1'; // 第一象限
else
r='4'; //第四象限
else
if(y>0)
r='2'; // 第二象限
else
r='3'; //第三象限
cout<<r;
return 0;
}
補充說明
1、此題目有人會寫成
if
(x>0 && y>0) r='1';
if
(x<0 && y>0) r='2';
if
(x<0 && y<0) r='3';
if
(x>0 && y<0 ) r='4';
這樣雖然沒有錯,但是執行效率非常差,因為電腦要不斷的比較。
自我練習
1、同上範例,但增加先判斷是否在原點或x、y軸上。
2、同上題,但程式一執行,要求先輸入密碼,密碼若為數字1234,那才可執行本程式。
範例5c打字練習。
請由電腦產生一個小寫字元,讓使用者輸入,電腦並判斷是否正確。
程式列印
#include
<iostream>
#include
<time.h> // 使用time()
#include
<stdlib.h> // 使用rand()
using namespace std;
int main()
{
srand(time(NULL));
int a=97+rand()%26;
//cout<<a<<endl;
cout<<(char)a;
char b;
cin>>b;
if ((int)b==a)
cout<<"right"
else
cout<<"wrong";
return 0;
}
自我練習
1、心算練習。請由電腦產生兩個1位數,讓使用者練習加法,電腦並評判是否正確。
switch...case
一個決策流程點若同時擁有三個或三個以上的解決方案,則稱此為多向分歧決策流程。多向分歧決策流程雖也可使用5-1的巢狀if else解決,但卻增加程式的複雜度及降低程式可讀性,若此一決策流程點能找到適當的運算式,能使問題同時找到分歧點,則可使用switch case敘述。switch case語法如下:
switch(運算式)
{
case常數1:
敘述區塊1;
break;
case常數2:
敘述區塊2;
break;
case常數3:
敘述區塊3;
break;
〔default:
敘述區塊n;]
}
以上語法說明如下:
1. switch的運算式值僅能為『整數』或『字元』。
2. case的常數僅能『整數』或『字元』,且其型態應與上面的switch運算式相同。
3. 電腦將會依switch的運算式值,逐一至常數1、常數2尋找合乎條件的case,並執行相對應的敘述區塊,直到遇到break敘述,才能離開switch。
4. default可放置特殊情況,也就是沒有適當的case,則執行default。若省略default,且若沒有任何case滿足switch運算式,則程式會默默離開switch敘述。語法中,兩旁加中括號表示此敘述可省略。
5. 敘述區塊可放置任何合法的敘述,當然也可放置switch或if。
6.
以下敘述,可將1、2、3、4轉為字元'A' 、'B'、 'C'、 'D'。
#include <iostream>
using namespace std;
int main() {
int a=1;
char
r;
switch(a) {
case
1:
r='A';
break;
case
2:
r='B';
break;
case
3:
r='C';
break;
case
4:
r='D';
break;
default
:
r=' ';
}
cout<<r;
return 0;
}
7. 有些語言可用逗號將兩種case放在一起,但在C/C++語言中每一case僅能放置一個常數,所以若兩個或兩個以上case,有相同的處理方法,則應將兩個case分成兩個敘述,且共用1個break,如以下程式。
case
10:
case 9:
r='A';
break;
請看以下範例。
範例5d
試以switch case重作範例5-1a。
【程式列印】
2. 使用return可提早離開main()函式。
#include <iostream>
#include<cmath>
using namespace std;
int main()
{
int a;
char
r;
cout<<"input
a grade: ";
cin>>a;
if(a>100
|| a<0) { // 如果輸入的成績大於100或小於0,則 提早離開
return
0;
}
switch(a/10)
{
case
10:
case
9:
r='A';
break;
case
8:
r='B';
break;
case
7:
r='C';
break;
case
6:
case
5:
case
4:
case
3:
case
2:
case
1:
case
0:
r='D';
break;
}
cout<<"the
grade is:"<<r;
return 0;
}
自我練習
1、請寫一程式,將所輸入的0、1、2…6,轉為'S'、'M'、'T'、'W'、'T'、'F'、'S'等字元。
2.請寫一個程式,可以產生一個0到25的亂數,且依以下分數顯示燈號
21∼25:五個燈。
16∼20:四個燈。
11∼15:三個燈。
6∼10:兩個燈。
1∼5:一個燈。
0:零個燈。
範例 5e 電子琴。前面我們已經介紹電腦如何使用_beep()函式發Do、Re、Me等音,本例則要依此製作一個電子琴。
解題步驟
1.
使用cin輸入字元都還要輸入Enter,這樣不像電子琴。所以線上查尋,發現getche()(放在conio.h)可輸入字元,但不用輸入Enter,所以本例使用此函式輸入字元。
#include <iostream>
#include <conio.h>//本例使用getche
int main()
{
char a;
while(1){//無限迴圈,請看下一章
a=
getche();//輸入後,不用按Enter
switch(a) {
case('1'):
_beep(523,500);//Do
break;
case ('2'):
_beep(587,500);//Le
break;
case ('3'):
_beep(659,500);//Mi
break;
case ('4'):
_beep(698,500);//Fa
break;
case ('5'):
_beep(784,500);
break;
case ('6'):
_beep(880,500);
break;
case ('7'):
_beep(988,500);
break;
case
('8'):
_beep(1046,500);
break;
}
}
return 0;
}
範例5f 猜拳遊戲。請寫一個程式,可以由人和電腦猜拳。
解題步驟
1、這一任務就是寫人工智慧程式的入門了,寫程式前先想一下您和一個3歲小孩或沒玩過猜拳的人猜拳,那您們如何開始此遊戲呢?首先,我們先規定有三種拳,分別是『剪刀、石頭與布』,且『剪刀贏布,石頭贏剪刀、布贏石頭,兩者相同則平手等』。『人工智慧』就是您聰明,它傻瓜,要把這些規定以程式語言表示,並由以上規定來執行遊戲與評判勝負。
2、資料的數位化。我們人類猜拳是直接用手勢表示『剪刀、石頭與布』,但是如何讓電腦瞭解您的拳法呢,裝一個攝影機當然可以,但是也還要影像處理,這不是我們這一單元任務,我們電腦只有鍵盤,所以可以先將以上『剪刀、石頭與布』以『1,2,3』表示,此即為資料的數位化。因為用『1,2,3』,表示只要1byte就可以,若您用『剪刀、石頭與布』表示,當然也可以,但一個中文字就佔用3byte,且往後的處理也是比較複雜。
3、本例因為電腦有三種拳法,可以用一個switch,人也有三種拳法,所以每一個switch裡面還有一個switch,所以共有9種情況,您要讓電腦也能思考,其實就是將以上所有可能發生的情況,以程式語言先規定好,如以下程式。
範例5g 求極大值。假如有資料如下:
3,2,5
如何求極大值。
參考解答
1、資料數位化。本例以單一變數儲存如下:
int a=3,b=2,c=5;
2、求極大值的演算法如下:
(1)
指派第1個為極大值。
int max=a
(2)從第2個資料起,都要和極大值比較,若大於極大值,則取代極大值。
if (b> max)
max=b;
3、輸出極大值。
4、根據以上演算法,程式撰寫如下:
#include <iostream>
using namespace std;
int main()
{
int a=3,b=2,c=5;
int max=a;
if (b>max)
max=b;
if (c>max)
max=c;
cout<<max;
return 0;
}
自我練習
1、若有4筆資料如下:
33,22,77,66
請寫一個程式,可以求其極小值。
2、有一批資料,含有3個人的人名與成績,請寫一程式,可以找出最低分的人名與成績。例如,
aa,60
bb,30
cc,80
3、請寫一程式,可以輸入5個數值,請去掉最大值與最小值,再求其平均。
一元二次方程式
前面我們直接假設所輸入的一元二次方程式有解,因為不是隨便給三個係數,一個方程式就通通有解,本例則要加上判斷了,解一元二次方程式的演算法如下:
1、設有一元二次方程式如下:
ax2 +
bx + c = 0
2、若a=0則輸出“輸入錯誤”。
3、令d=b2-4ac。
4、若d=0,則方程式有唯一解;否則,若d>0,則方程式有二解,;否則,無實數解。
5、例如:2x2-7x+3=0。其解是x1=3.0,y1=0.5。
以上演算分析,以流程圖說明如下:
範例 5h
請設計一個程式,可以解一元二次方程式ax2 + bx + c = 0。
#include <iostream>
#include<cmath>
using namespace std;
int main()
{
int a=2,b=-7,c=3;
double
d,x1,x2;
if(a==0) {
cout<<"input
error"; // 若a=0,則列印錯誤訊息
return
0;
}
d=pow(b,2)-4*a*c; // 計算d值
if(d==0)
cout<<"only one
answer,x1,x2="<< (-b/(2*a));
else
if(d>0){
x1=(-b+sqrt(d))/(2*a);
x2=(-b-sqrt(d))/(2*a);
cout
<<"two answer x1="<<x1;
cout
<<" ,x2= "<<x2<<endl;
}
else
cout<<"no real answer:";
return 0;
}
自我練習
1.解二元一次方程式。解二元一次方程式的演算法如下:
(1) 設二元一次方程式如下:
(2) 令 (表示d = a1b2 - a2b1)
(3) 假如,則方程式無限多解,且程式結束。(代表兩重疊直線)
(4) 假如,則方程式無解,且程式結束。(代表兩平行直線)
(5)
(6)
(7)例如:
3x+y=5
x-2y=-3
的解為x=1,y=2
請設計一個程式,可以解二元一次方程式。
2、三角形判斷(APCS105第二梯次試題)
若已知三角形三邊長,判斷是否構成三角形、評定三角形種類與計算三角形面積的演算法如下:
(1)
輸入三角形的三邊長a、b、c。
(2)任兩邊之和要大於第三邊,才能構成三角形,否則程式結束。
(3)若c是最長邊,假如a2 + b2 > c2則為銳角三角形;否則,假如a2 + b2 = c2,則為直角三角形;否則此三角形為鈍角三角形。
(4)令
(5)三角形面積
請輸入三角形三邊長,首先判斷是否構成三角形、其次判別三角形的種類,最後計算其面積。
範例一:輸入 3 4 5 範例一:正確輸出 3 4 5 Right (說明) a×a + b×b =
c×c 成立時為直角三角形。 |
範例二:輸入 101 100 99 範例二:正確輸出 99 100 101 Acute (說明) 邊長排序由小到大輸出, a×a + b×b
> c×c 成立時為銳角三角形。 |
範例三:輸入 10 100 10 範例三:正確輸出 10 10 100 No (說明) 由於無法構成三角形, 因此第二行須印出 「No」。 |
第6單元 迴圈運算
我們小時候常常被老師罰寫某個句子十遍,這件事若讓電腦做,那可就輕鬆了,因為電腦有for迴圈運算。例如,以下敘述可將『洪國勝』重複寫10次。
for
(int i=1;i<=10;i++)
cout<<"洪國勝"<<endl;
for指令的語法如下:
for([計數變數=起始值] ;[迴圈運算式];[計數變數的改變量]) {
[指令區塊1;]
[break;]
[continue;]
[goto
(標籤名稱);]
[指令區塊2;]
}
以上語法說明如下:
1.
只要“迴圈運算式”結果為1(真),則繼續執行迴圈內的指令區塊。
2.
計數變數的改變量可為遞增,請留意終值較大。請鍵入以下程式,並寫出執行結果。
int main(){
for (int i=1;i<=5;i++)
cout<<i<<" ";
cout<<endl;
for (int i=2;i<=6;i+=2)
cout<<i<<" ";
cout<<endl;
}
3.
計數變數的改變量可遞減,請留意終值較小。請鍵入以下程式,並寫出執行結果。
int main(){
for (int i=5;i>=1;i--)
cout<<i<<" ";
cout<<endl;
for (int i=9;i>=1;i-=3)
cout<<i<<" ";
cout<<endl;
return 0;
}
2.只要迴圈運算式為0(false),就離開迴圈。請鍵入以下程式,並寫出執行結果。
int main(){
for (int i=1;i>=5;i++)
cout<<i<<" ";
cout<<endl;
for (int i=5;i<=1;i++)
cout<<i<<" ";
cout<<endl;
return 0;
}
4.
關係運算子通常使用『<,<=,>,>=』,若使用『==,!=』,也沒有錯誤訊息,但執行結果不同。
int main(){ for (int i=1;i==5;i++)
cout<<i<<" "; cout<<endl; return 0; } |
int main(){ for (int i=1;i!=5;i++)
cout<<i<<" "; cout<<endl; return 0; } |
5.
for 運算僅預設執行1個敘述,若要執行兩個以上敘述,請加上{}。
int main(){ int s=0; for (int i=1;i<=5;i++)
cout<<i<<endl;
s=s+i; cout<<s<<endl; return 0; } |
int main(){ int s=0; for (int i=1;i<=5;i++){
cout<<i<<endl;
s=s+i; } cout<<s<<endl; return 0; } |
6.
以上變數i的有效範圍僅在迴圈內,所以以下程式的i無效。
int main(){ int s=0; for (int i=1;i<=5;i++)
cout<<i<<endl;
s=s+i; cout<<s<<endl; return 0; } |
int main(){ int s=0; for (int i=1;i<=5;i++){
cout<<i<<endl;
s=s+i; } cout<<i<<endl; cout<<s<<endl; return 0; } |
7.
以下程式都可以,但是變數i的有效範圍不同。
int main(){ int i=0; for (int i=1;i<=5;i++){
cout<<i<<endl; } cout<<i<<endl; return 0; } |
int main(){ int i=0; for (i=1;i<=5;i++){
cout<<i<<endl; } cout<<i<<endl; return 0; } |
8.
計數變量也可在迴圈內改變。例如:
int main(){
for (int i=1;i<=10 ;i++){
cout<<i<<endl;
i++;
}
return 0;
}
9.
程式若執行到break,則會提早離開for迴圈。
int main(){
int i, sum=0;
for(i=1;
i<=6; i++) {
cout<<i<<endl;
if(i==4)
break; //強制離開迴圈
cout<<i<<endl;
}
cout
<<"when out of loop, i="<<i;
return 0;
}
10.
程式若執行到continue,則會略過continue下面的指令區塊2,繼續執行下一個計數變量。
int main(){
int i, sum=0;
for(i=1;
i<=6; i++) {
cout<<i<<endl;
if(i==4)
continue; //強制離開迴圈
cout<<i<<endl;
}
cout
<<"when out of loop, i="<<i;
return 0;
}
9程式若執行到goto,則會略過goto下面的指令區塊2,跳躍至 (標籤名稱) 所在的位置,繼續執行標籤以下的指令區塊。
int main(){
int i, sum=0;
for(i=1;
i<=6; i++) {
cout<<i<<endl;
if(i==4)
goto
aa; //強制離開迴圈
cout<<i<<endl;
}
aa:
cout
<<"when out of loop, i="<<i;
return 0;
}
8. 指令區塊內可以放置任何合法的指令,當然也可含for。for內有for,稱為巢狀迴圈。例如,以下指令可印出1至10 五次,請看6_2節。
int
main(){
for (int i=1;i<=5;i++){
for
(int j=1;j<=10;j++)
cout<<j;
cout<<endl;
}
return 0;
}
11.
運算式只要合理就好,不一定要用計數變數。例如:
int main(){ int i=0,s=0; for (i=1;s<=10;i++){
cout<<i<<endl;
s=s+i; } cout<<i<<endl; cout<<s<<endl; return 0; } |
int main(){ int i=0,s=0; for (i=1;i<=10
&& s<=10;i++){
cout<<i<<endl;
s=s+i; } cout<<i<<endl; cout<<s<<endl; return 0; } |
範例6a 請寫一個程式,電腦可以連續出現6個字元,由使用者輸入,並判斷是否正確,統計正確與錯誤題數。
程式列印
#include <iostream>
#include <time.h> // 使用time()
#include <stdlib.h> // 使用rand()
using namespace std;
int main()
{
srand(time(NULL));
int
r=0,w=0;
for
(int i=1;i<=10;i++){
int
a=97+rand()%26;
cout<<(char)a;
char
b;
cin>>b;
if
((int)b==a){
cout<<"right"<<endl;
r++;
}
else{
cout<<"wrong"<<endl;
w++;
}
}
cout<<"right="<<r<<endl;
cout<<"wrong="<<w<<endl;
return
0;
}
自我練習
1、請產生6個-3~3的亂數,統計正數、0、負數的個數。
2、請產生10個1~6的亂數,統計偶數與奇數個數。
3、請產生10個1~6的亂數,統計所有數字出現的次數。
4、請產生10個1~6的亂數,統計哪一個數字出現的次數最多。
5、請連續產生8題兩個1位數,由使用者輸入相加結果,電腦回應對或錯,並統計正確與錯誤的題數。
6、請由電腦自動產生30個大於等於0且小於等於100的亂數x,統計0~59,60~69,70~79,80~89,90~100的個數。
7、請寫一個程式,電腦可以連續出現50個小寫字元,電腦統計出現母音的個數。
aa
#include <stdio.h>
int main( )
{
int Sum=0, Array[] ={1,
2, 3}, i;
printf("%d",Array[7]);
for(i=1; i<4; i++)
Sum+=Array[i];
printf( "%d",
Sum);
return 0;
}