第二章
建立主控台應用程式
2-1 程式語言的基本結構
對Visual C++ 2005 Express Edition版本的 工作環境有了初步認識後,接下來介紹
C/C++語言的基本架構。
無論是那一種程式語言,都是由一行行的 敘述組成。
在這些敘述中,可以加入變數的宣告,加 入條件判斷,或是執行運算。
一個程式中到底包含那些?我們將為你進
一步探討!
2-1-1 程式的註解
我們先透過一個簡易的程式來瞭解基本架構:
表示許解文字 表示許解文字 表示許解文字 表示許解文字 前置處理指令 前置處理指令 前置處理指令 前置處理指令 宣告名稱空間 宣告名稱空間 宣告名稱空間 宣告名稱空間
_tmain()為主函式為主函式為主函式為主函式 輸出格式 輸出格式輸出格式 輸出格式
程式組成
由圖2-1可以瞭解程式的結構分成好幾個部 份:
註解
前置處理指令
名稱空間
_tmain()主函式
輸出格式
除此之外,當然也包含了
流程控制、函式和類別等,我們將在後面章節
陸續介紹
認識程式的註解
首先,說明程式註解
一個好的程式會在需要的地方加入註解,方便日 後的閱讀。
例如,我們在程式第一行加入註解來說明程式的名稱 和程式的用途。當程式進入編譯程序時,便會忽略此 註解,不會導致程式發生錯誤。
一般來說,我們將註解分成
單行註解
多行講解
單行註解
以兩個斜線「//」字元來表示單行註解。
在程式敘述後面加入註解,說明此行敘述的作用
或者直接將註解放在程式碼最前端,如圖2-1的第一行也 是一個單行註解。
多行註解
若要加強閱讀效果,也可以使用多行註解
多行註解以「/*」為開始,再以「*/」為結束
使用者可以依據需要加入註解文字
圖2-1中,程式碼第7~9行就是多行註解文字。
回程式基本架構
2-1-2 前置處理指令
前置處理指令能讓編譯器在執行編譯前,利用指 令將相關的檔案內容加入程式碼中
一般常見的指令為「include」敘述,使用時必須在敘 述前端加入「#」符號,稱為「前置處理指令」
(Preprocessor directive)
這些引入的檔案通稱為「標頭檔」(header file)。
Visual C++提供了不同作用的標頭檔,在後面的章節 還會繼續討論。
使用標題檔
有了這樣的概念,再參閱圖2-1:
程式碼第4行加入的「iostream」標頭檔,用 來處理資料的輸入或輸出。
然後透過程式碼第11、12行的cout物件來輸出 內容。如果沒有引用此標頭檔,編譯時就會顯 示錯誤訊息,以下圖2-2來說明:
編譯易顯示的錯誤訊息 編譯易顯示的錯誤訊息編譯易顯示的錯誤訊息 編譯易顯示的錯誤訊息
回程式基本架構
2-1-3 使用名稱空間
名稱空間的功能是為了讓不同區域的相同名稱不 會因為重覆性而產生衝突。
由於C++標準函式庫中提供了不同用途的函式,
為了避免程式的函式名稱與標準函式庫的名稱相 同,C++提供名稱空間,標準函式庫的所有函式 都存放在「std」這個名稱空間。
當我們使用cout物件時,必須使用範圍解析運算子
「::」來存取,程式碼必須寫成「
std :: cout
」。不過這樣的撰寫方式並不是很方便,因此C++提供 using directive作法,
因此在程式碼第5行加上名稱空間的宣告,如下所示:
使用std名稱空間
告知編譯器,目前的函式屬於std名稱空間。那麼,程式碼 中就不需要同時標示函式名稱和名稱空間。
如此一來,利用cout物件輸出內容時,就能直接撰寫如下:
若未使用名稱空間,則利用cout物件輸出內容時,結果如 下:
回程式基本架構
2-1-4 主程式.
所有的程式都會有一個執行程式的進入點。
以C/C++語言來說,程式進入點主要是透過main() 主函式。
表示程式執行時會先找出main()主函式作為程式的進 入點,若程式中沒有main()主函式,則會產生錯誤訊 息!
對Visual C++ 2005來說,則是以_tmain()主函式 作為程式的進入點。
_tmain()主函式包含函式名稱_tmain()和函式主體 (body)。
由「{」右大括號為函式的開始,「}」左大括號為函 式的結束;大括號的內容屬於函式主體,由{ }包含的 敘述稱為區塊(Block)。
主程式..
一般來說,所有的函式都是由函式名稱和函式主 體所構成,當函式主體沒有任何敘述時,表示此 函式不會做任何動作。
除了_tmain()主函式之外,C/C++原有的main() 函式也會在後面的範例中繼續使用。
而Visual C++ 2005為了處理Unicode的問題,也
提供wmain()主函式,其用法和main()相同,會
在後面章節做介紹。
2-1-5 識別字和關鍵字
在Visual C++ 2005中,無論是我們宣告的變
數、常數、函式名稱或是類別名稱,通常將這些 名稱稱為「識別字」(identifier)。
這些識別字必須由英文字母、底線和數字組成。
使用這些識別字時必須注意幾件事情:
識別字的第一個字元必須由英文字母或是底線符號來 做為開頭。例如:myObj、_studentName。
其他的識別字元可由英文字母、阿拉伯數字和底線符 號所組成。
識別字的英文字母有大小寫之分,字母和字母之間不 能有空白符號。
識別字可區分為使用者自行定義和系統提供,儘可能 少用單一底線_或兩個底線__來做為開頭,它通常是 C++語言關鍵字的範圍。
識別字長度可達32個字元,不能使用關鍵字來做為識 別字的名稱。
關鍵字(keyword).
除了識別字之外,另一種是關鍵字(keyword),這在C/C++語 言中有特殊用途,做為程式設計或呼叫使用,下表2-1為一 些常用的關鍵字。
protected property
private operator
nullptr
_ _noop noinline
destructor new
interior_ptr
namespace mutable
long literal
initonly
_ _interface int
inline if
_ _identifier
_ _hook goto
generic gcnew
delegate
friend for
float finally
false
extern explicit
except _ _event
event
enum else
dynamic_cast double
do
delete default
continue const_cast
const
class char
catch case
break
bool auto
array _ _asm
abstract
關鍵字(keyword)..
在上述關鍵字中,如果是以「__」雙底線為開頭的,通常是 系統強制保留。
while volatile
void
using virtual
_ _unaligned union
typename
typeid typedef
unsigned try
true
throw thread
this template
switch
_ _super struct
_ _single_inheritance static_cast
sizeof
static signed
reinterpret_cast short
sealed
safecast return
register _ _raise
public
2-1-6 資料的輸入和輸出
一般來說,撰寫的程式要與使用者產生互動時,
需要透過介面來提供使用者進行資料的輸入,或 是輸出程式的執行結果。
輸入裝置包含鍵盤、滑鼠等週邊硬體,以及硬碟中的 檔案;
而輸出裝置亦包含螢幕、印表機等硬體和硬碟中的檔 案。
輸出、輸入敘述
以下範例將示範常用的輸出、輸入敘述:
在C++中處理資料輸入及輸出最常用的方法就是cin與cout物 件。後面範例將會使用它們來執行資料的輸出入程序。
cin物件及>>運算子:
無論是cin或cout物件,在使用前都必須引入
「iostream」標頭檔。
cin是一個類別式的物件,不是指令。
使用cin必須配合輸入重載運算子「>>」來進行,我們稱之
「標準輸入器」。
下面程式碼片段說明其用法:
使用cin物件
使用cin物件來取得輸入資料時,如果字串中含有 空白,cin物件會停止讀取資料。
為了改善上述情形,cin物件提供getline()成員函 式,處理由鍵盤輸入含有空白的字串,直到按下 Enter鍵,會在字串末端自動加上「\0」結束字 元。語法如下:
str:使用者輸入的字串。
int n:用來設定輸入字串的最大長度。
char ch:此參數可省略,用來設定輸入字串的結束字 元
使用cin敘述
舉例說明:
cout物件及<<運算子:
同樣地,cout也是一個類別式的物件,它配合輸入重載運 算子「<<」進行輸出的動作,我們稱為「標準輸出器」
此外,還有一個物件「endl」,將輸出於螢幕上的資料進 行「換行」工作。它的用法與「\n」有異曲同工之妙!
cout物件程式碼片段
以上只說明C++基本架構使用的概念。接下來將會慢慢帶 領讀者有更深入瞭解。
程式解說
第4行:加入處理輸入、輸出資料的iostream 標頭檔。
第5行:名稱空間的宣告。
第10行:「主程式」通常使用Win32應用程 式精靈,選擇先行編譯標頭檔時,會 以_tmain()主函式做為程式的進入點。
然後第11、12行利用cout物件來輸出字串內
容。
建置程式碼
輸入程式碼後,將專案進行編譯的動作,請執行 下列步驟:
步驟1:進行編譯
執行 執行 執行
執行「「「「建置建置建置建置/建建建建 置方案
置方案 置方案
置方案」」」」指令指令指令指令 或按
或按 或按
或按F7按鍵按鍵按鍵按鍵
步驟2:檢視編譯結果
從「輸出」視窗檢視編譯結果
檢視檢視
檢視檢視「「「「輸出輸出輸出輸出」」」」視窗表示視窗表示視窗表示視窗表示 程式碼沒有任何錯誤 程式碼沒有任何錯誤 程式碼沒有任何錯誤 程式碼沒有任何錯誤
步驟3:
以「啟動但不偵錯」指令來執行程式。
執行執行
執行執行「「「「偵錯偵錯偵錯偵錯/啟啟啟啟 動但不偵錯 動但不偵錯 動但不偵錯 動但不偵錯」」」」 指令或按
指令或按 指令或按
指令或按「「「「Ctrl + F5」」」」按鍵來按鍵來按鍵來按鍵來 啟動程式
啟動程式 啟動程式 啟動程式
步驟4:
呼叫「命令提示字元」視窗顯示輸出結果如
下圖:
執行步驟說明:
執行「步驟1」建置專案過程中,會在此專案底 下自動產生一個「Debug」資料夾,然後把專案 底下的相關檔案進行編譯、連結,然後產生一個
「ShowData.exe」的執行檔。
然後利用「步驟2」輸出視窗來顯示編譯過程,
編譯的相關資訊會記錄於「BuildLog.htm」檔案
中。
2-2-2 利用命令提示字元執行程 式
我們也能利用Visual C++ 2005 Express Edition撰 寫一個簡單的C++程式,其步驟如下:
執行執行
執行執行「「「「檔案檔案檔案檔案/新新新新 增
增 增
增/檔案檔案檔案」檔案」」指令」指令指令指令
步驟2:新增C++檔案
選取選取選取選取「「「「Visual C++」」」」 選取選取選取選取「「「「C++檔檔檔檔」」」」 按按按按「「「「開啟開啟開啟開啟」」」」鈕鈕鈕鈕
程式碼:
Ch02\Native\data.cpp
程式碼非常簡短,利用Visual C++ 2005來建立一個
data.cpp檔案,利用C/C++原有的main()主函式來做為程 式進入點。
此處並沒有加入名稱空間,直接以「std :: cout」來做為 輸出內容。
完成上述動作後,我們在程式碼編輯視窗輸入下列程式碼:
儲存檔案
我們將程式碼進行儲存,其步驟如下所示:
儲存於儲存於儲存於儲存於「「「「Native 」」」資料夾」資料夾資料夾資料夾 檔名檔名檔名檔名「「「「data.cpp」」」」 按按按按「「「「儲存儲存儲存儲存」」」」鈕鈕鈕鈕
編譯程式
完成檔案的儲存後,編譯data.cpp檔案須利用「命令提示 字元」視窗來進行。
首先,啟動命令提示字元視窗,請按下「開始」功能鍵,
執行「所有程式」→「Visual C++ 2005 Express
Edition」→「Visual Studio Tools」→「Visual Studio 2005 命令提示字元」,接著在「命令提示字元」執行以
下動作: 輸入編譯輸入編譯輸入編譯輸入編譯「「「「 cl/EHsc data.cpp」」」」命令命令命令命令
執行檔案執行檔案執行檔案執行檔案
「
「
「
「data.exe」」」」 如果沒有任何錯誤 如果沒有任何錯誤如果沒有任何錯誤 如果沒有任何錯誤 會輸出這兩個檔案 會輸出這兩個檔案會輸出這兩個檔案 會輸出這兩個檔案
輸出結果輸出結果 輸出結果輸出結果
程式編譯後
data.cpp檔案經過編譯後,若無任何錯誤,會產 生data.obj目的檔和data.exe執行檔。只要輸入
「data」就會執行檔案並輸出結果。
cl/EHsc編譯指令..
圖2-4中的第一行命令『cl/EHsc
data.cpp』是用來編譯程式碼,語法為:
cl:cl.exe是編譯命令,為C/C++的編譯器和連 結器,它只能在Windows 2000、Windows XP 和Windows Server 2003作業系統上執行。
option:表示選項命令,使用時必須加入斜線
「/」字元,例如「/EHsc」是編譯時加入的選 項命令,使用時英文字母有大小寫之分。
file:為欲編譯的原始程式碼,此處是
「data.cpp」檔案。
Cl/EHsc編譯指令..
一般來說,編譯時比較好的作法是加入例 外處理動作。
因此,「EH」即是處理例外狀況模型
『sc』參數是產生例外狀況時讓編譯器回傳錯 誤訊息
在「命令提示字元」視窗下進行程式碼的
編譯時,都會以「cl/EHsc」來執行(有關例
外處理,我們以後面的章節來介紹說明)。
2-2-3 以CLR編譯C++程式
在範例data.ccp中,程式碼撰寫都是利用Visual C++
2005 Express來進行!
如果只是很單純的檔案,也可以直接呼叫「記事本」來 撰寫,並將程式碼以CLR編譯器來進行編譯!執行下列 步驟:
切換到切換到切換到「切換到「「NETprg 」「 」」」目錄目錄目錄目錄
啟動記事本撰寫程式啟動記事本撰寫程式啟動記事本撰寫程式啟動記事本撰寫程式
步驟2:開啟記事本
開啟記事本軟體開啟記事本軟體開啟記事本軟體開啟記事本軟體
按按按按「「「「是是是是」」」」按鈕按鈕按鈕按鈕
程式碼:CH02\NETprog\data2.cpp
我們故意在程式碼第4行最後不加入結束的「;」
分號符號。接著儲存程式碼,執行「檔案/儲存檔 案」指令
再切換到「Visual Studio 2005 命令提示字元」
視窗。
執行程式(錯誤!)
我們利用CLR編譯器來編譯程式。
由上圖2-5得知,命令「cl/clr data2.cpp」是把檔案編譯 成「列管程式碼」,透過clr命令來編譯data2.cpp檔案。
由於程式碼有錯誤,編譯器會指出在程式碼第6行之前產 生錯誤訊息!重新將程式碼修正後並進行儲存。
輸入輸入
輸入輸入「「「「cl/clr
data2.cpp 」」」」編譯命令編譯命令編譯命令編譯命令
顯示錯誤訊息 顯示錯誤訊息 顯示錯誤訊息 顯示錯誤訊息
執行程式(正確)
當我們將data.cpp以「cl」命令進行編譯,
只會產生data.obj和data.exe二個檔案。
重新以重新以重新以重新以「「「「cl/clr
data2.cpp 」」」」來編譯來編譯來編譯來編譯
執行檔案執行檔案執行檔案執行檔案 輸出執行結果 輸出執行結果 輸出執行結果 輸出執行結果
CLR編譯器的不同.
如果透過「clr」編譯器會產生那些檔案,執行結果如下圖:
多了 多了 多了 多了
「
「
「
「data2.exe.mainfest」」」」 檔案
檔案 檔案 檔案 以 以 以
以「「「「dir 」」」命令」命令命令命令 列出所有檔案 列出所有檔案 列出所有檔案 列出所有檔案
CLR編譯器的不同..
由圖2-6可以清楚看到,除了有「data2.obj」和
「data2.exe」檔案之外,還有一個「資料清單」
(manifest)檔案
它是一個中繼資料,用來記錄組件的相關訊息
如果我們使用記事本來打開它,會發現它是以XML標 籤來組成檔案內容
2-3 資料類型和變數
當我們要透過程式來對資料進行處理時,
必須取得記憶體空間。
無論是資料的大小和種類都會影響記憶體 配置和空間大小。
為了有效控管記憶體空間,對於資料的處
理,會以變數、常數和資料型別處理。
2-3-1 基本資料型別
資料型別會影響記憶體空間的大小。
對於Visual C++ 2005來說,資料型別有二種:
基本資料型別
延伸資料型別
基本資料型別,包含三種
integral
floating
void
integral--整數型別
integral用來宣告不具小數點的整數數值
例如12、3658、27…等
其長度會依照作業系統環境而有所不同。
在16位元的作業環境中(如MS-DOS及Windows 3.1)其長度為2個位元組;
而在32位元的作業環境(如Windows 98)中,其長度 就變成4個位元組。
為了要增加或降低變數的精確度和佔用的記憶體空 間,可以加入signed(有號數)和unsigned(無號數)。
整數型別的種類(表2-2)
備註中的__int 8、__int 16、__int 32為CLI所定義的資料型別0 ~ _ _int64 18,446,744,073,709,551,615
8 bytes unsigned long long
_ _int64 -9,223,372,036,854,775,808 至
+9,223,372,036,854,775,808 8 bytes
long long
–2,147,483,648 至 +2,147,483,647 4 bytes
long
0 ~ 4,294,967,295 4 bytes
unsigned int
_ _int32 –2,147,483,648 至
+2,147,483,647 4 bytes
int
0 ~ 65,535 2 bytes
unsigned short
_ _int16 -32,768 至 +32,767
2 bytes short int
_ _int16 -32,768 至 +32,767
2 bytes short
回傳true或false 1 byte
bool
0 ~ 255 1 byte
unsigned char
_ _int8 -128 至 +127
1 byte char
備註 存取範圍
儲存空間 型別名稱
Floating--浮點數型別
floating型別包含float、double和long double三 種,用來宣告具小數點之實數數值型態,
例如5.23、0.3478…等,其長度為4個位元組。
透過下表2-3說明floating型別的儲存範圍。
-1.7×10-308 ~ 1.7×10308 8 bytes
long double
15位數 -1.7×10-308 ~ 1.7×10308
4 bytes double
7位數 -3.4×10-38 ~ 3.4×1038
4 bytes float
有效位數 存取範圍
儲存空間 型別名稱
表 表 表
表2-3 浮點數型別浮點數型別浮點數型別浮點數型別 表
表 表
表2-3 浮點數型別浮點數型別浮點數型別浮點數型別
void--無值
表示使用的main()主函式或是其他的函式無需回傳
任何資料型別的值。
2-3-2 變數和常數
對於Visual C++ 2005的基本資料型態有了初步認識後,要 進一步探討變數
有時程式碼是避免不了運算,運算後的結果該如何處理?
簡單來講,就是透過宣告的「變數」而儲存於記憶體中
宣告變數
所謂「變數」(variable)就是資料內容會隨著處理 過程而改變。
變數名稱也是識別字的一種,宣告時必須遵守識 別字命名的規範。
宣告的語法如下:
資料型別代表記憶體空間大小,利用變數名稱來分配 記憶體空間。
變數的程式碼片段
在程式碼如何加入變數的宣告,程式碼片段如下:
我們可以依據需求,將變數進行連續宣告,變數與變 數之間須以「,」來隔開,或者在宣告變數的同時給予 起始值的設定。
範例:total.cpp
如何取得輸入的設定值?還記得介紹程式語
言的基本結構時所提及的cin物件,利用它來
讀取輸入的變數值!我們利用下面範例來說
明。
執行程式
執行執行執行「執行「「cl/EHsc total.cpp」「 」」」 命令來進行檔案的編譯 命令來進行檔案的編譯 命令來進行檔案的編譯 命令來進行檔案的編譯
輸入輸入輸入「輸入「「 total」「 」」」來執行檔案來執行檔案來執行檔案來執行檔案
輸入欲計算的分數輸入欲計算的分數輸入欲計算的分數輸入欲計算的分數
計算後的三科總分計算後的三科總分計算後的三科總分計算後的三科總分
程式解說
第7行:主程式main()宣告3個變數:
math、eng和chinese。
第9行:利用cin物件來讀取從螢幕輸入的 變數值,並分別儲存在所宣告的變數。
第10行:將這些變數相加並儲存於total變 數中。
第11行:利用cout物件輸出結果。
宣告常數
相對於變數,常數表示的不變的值。
宣告常數時有二種方式:
第一種必須加入「const」修飾詞;
另一種則是利用前端處理指令「#define」。
使用【const】的語法:
範例:radius.cpp
程式碼中如果設定的值不希望被改變時,透過const修飾詞 來宣告常數是一個比較好的方式。我們以下面範例來說明:)
執行程式
執行執行執行執行「「「「cl/EHsc radius.cpp」」」」 命令來進行檔案的編譯
命令來進行檔案的編譯 命令來進行檔案的編譯 命令來進行檔案的編譯
輸入輸入輸入「輸入「「radius」「 」」」命令來執行檔案命令來執行檔案命令來執行檔案命令來執行檔案
計算圓面積的結果計算圓面積的結果計算圓面積的結果計算圓面積的結果
程式解說
在8行:宣告圓周率PI為常數,用來計算圓面積 時防止被改變。
第10行:進行圓面積的計算
第11行:輸出結果!
若圓周率的值並不需要如此精確時,只要去修改 第8行的常數值為「PI = 3.14」,讓程式重新去 計算即可!
如果未以常數來處理,我們就得花費時間去搜尋 程式碼中那些敘述使用了圓周率,然後一一更 正,有時反而更容易造成計算上的錯誤!
另外,大家有無發現,為什麼計算出來的圓面積
是一個整數?這個問題我們留到章節2-5型別轉
換來討論!
以define定義常數
另一個定義常數的方法是使用前端處理指令「#define」,語法 為:
範例:radius2.cpp
如果我們將上一個範例更改為「#define」宣告,使用方式如下:
第5行:以「#define」來宣告常數,其他的程式內容並沒有 改變!
2-3-3 變數的生命週期
一般來說,變數會因為宣告的位置不同,其「有 效範圍」和「生命週期」也會隨之不同。
在C++中我們會以「{ }」來表示某一段敘述是屬 於某個區塊(block)範圍。
同樣地,在main()主函式區塊中宣告的變數,它的有 效範圍(scope)只限於主程式中。
瞭解變數的有效範圍後,才能宣告變數,設定變數 值,進行運算。
當我們執行程式時,所有變數的生命週期都是有 限的。
宣告變數時,表示生命的開始;它可能在某個區塊的 敘述中結束,或是直到程式終結才會停止。
我們將變數的生命週期依據它的有效範圍來分成
「區域變數」(Local Variable)、
全域(globe)變數(請參考6-2-1節)。
2-4 運算子
無論是那一種程式語言都會有運算式,組成運算 式的元素包含運算元(operand)和運算子
(operator)。
「運算元」是被運算子處理的資料,包含變數、常數 值等;
「運算子」指的是運用一些數學符號,例如+(加)、
-(減)、*(乘)、/(除)等。
運算子會針對特定的運算元進行處理程序。
運算子
運算式計算的過程,如果只有一個運算元,稱為
「一元運算子」,例如「++i」;
如果有兩個運算元,稱為「二元運算子」,例如
「A+2」運算式中,字元A與數字2都是運算元,
「+」則是運算子。
Visual C++ 2005提供運算子包含:
算術運算子(Arithmetic Operator)
指派運算子(Assignment Operator)
關係運算子(Relational Operator)
邏輯運算子(Boolean Logical Operator)
遞增和遞減運算子(Increment & Decrement Operator)
2-4-1 算術運算子
算術運算子主要是用來做為變數間的數學運算,使用的 算術運算子整理如下表2-4:
op1 % op2
% 餘數
op1 / op2 / 除
op1 * op2
* 乘
op1 – op2 - 減
op1 + op2 + 加
範例 用法
運算子
表 表表
表2-4 算術運算子算術運算子算術運算子算術運算子 表
表表
表2-4 算術運算子算術運算子算術運算子算術運算子
2-4-2 指派運算子
如果運算式是這樣敘述:
表示要將等號右邊的兩個運算元相加後再指派給等 號左邊的op1運算元,可以簡化為:
利用指派運算子簡化運算式的作法,我們以下表2- 5來表示其用法:
op1 %= 15 op1 =op1 % 15
%=
op1 /= 15 op1 = op1 / 15
/=
op1 *= 15 op1 = op1 * 15
*=
op1 -= 15 op1 =op1 - 15
-=
op1 += 15 op1 =op1 + 15
==
簡化 原有運算式
運算子
2-4-3 關係運算子
「關係運算子」亦稱為「比較運算子」,主要 應用於條件判斷,用來比較運算子左右兩邊運 算元的關係。
關係運算子必須使用二元運算,比較後會傳回true或 false的布林(Boolean)值。
有那些關係運算子,我們整理出下表2-6:
true op1 != op2
!= 不等於
true op1 <= op2
小於或等於
<=
true op1 < op2
< 小於
false op1 >= op2
大於或等於
>=
false op1 > op2
> 大於
false op1 == op2
== 等於
op1=10, op2=20的比較結果 用法
名稱 運算子
範例:relaop.cpp
說明關係運算子
執行程式
程式說明
第8行:宣告兩個變數,並分別設定起始值。
第10~12行將這兩個變數以關係運算子來做比
較,並傳回true或false結果。我們會發現只輸出0 或1的結果。對C++而言,變數要以布林值輸出 時,預設會以0表示為false,以1表示為true。
第15行:為了能輸出true或false字串,加入 boolalpha()函式。
第16~18行:以true或false字串來輸出。
boolalpha()函式語法如下:
_Str是一個iostream的物件!在此範例中則直接呼叫 boolalpha來使用。
2-4-4 邏輯運算子
邏輯運算子主要也是應用於條件判斷。
邏輯運算子的運算結果也會以布林值回傳。當兩項變 數做邏輯運算時,若條件成立則傳回true;若不成立則 傳回false。我們以下表2-7來說明邏輯運算子的用
法:
true
false false 當op1為真,所得結果為假
!op1 true
!
false false
false
true true
false
true false
true 只要op1、op2其中一個為
真,所得結果會為真 true
true true
op1 || op2
||(或)
false true
false
false false
false
false false
true 當op1、op2的值均為真,
所得結果為真 true
true true
op1 && op2
&&(且)
說明 op2值 傳回值
用法 op1值 運算子
2-4-5 遞增、遞減運算子
在程式碼中使用的++(遞增)和--(遞減)運算子都是 屬於一元運算子,讓目前的變數值加1或減1。
如果將運算子放在運算元之前,稱為「前序」
(prefix);
反之,將運算子放在運算元之後,稱為「後序」
(postfix),以下表2-8說明。
op1會與其他運算元做運算,再自行減1 op1--
後序
op1會先自行加入,再與其他運算元運算 ++op1
前序
說明 表示法
運算
範例:prefix.cpp
我們以下面範例來說明前序和後序的使用。
執行程式
第8行:宣告opr1和opr2兩個變數,並設定起始值。
第9行:執行前序運算,表示opr1會自行加入,得到11,
再與opr2相加,其結果儲存於result變數中。
第11行:輸出結果為19。
第13行必須將opr1的變數值重新設定。第14行進行後序 運算,opr1會先與opr2相加得到18,然後opr1本身再加 1。
第15行:輸出的opr1還是1。第16行:result只得18。
因此無論是使用「前序」或「後序」,對於opr1來說,
其值都會加1。result則會受到「前序」或「後序」而影 響計算結果。
2-4-6 運算子的優先順序
不同的運算子在計算時,依其運算優先順序可以下表2-9來執 行:
, 由左而右 12
=、*=、/=、%=、+=、–=、<<=、>>=、&=、|=、^= 由右而左 11
? :(條件運算子) 由右而左 10
||(或) 由左而右 9
&&(且) 由左而右 8
==(相等)、!=(不相等) 由左而右 7
<<(左移)、>>(右移) 由左而右 6
+(加)、-(減) 由左而右 5
*(乘)、/(除)、%(取餘數) 由左而右 4
sizeof、~、!、–(正)、+(負)、new、delete() 由右而左 3
.(成員存取運算子)、–>(取值運算子)、[ ]、( )、++、–– 由左而右
、typeid( ) 2
::(範圍解析運算子) 1
運算順序 運算子
優先順序
2-5 型別轉換
在運算式中倘若兩個資料型別不同的數值要一起運算,除非 是使用強迫資料轉換,要不然C++會以「自動型別轉換」
(Automatic Type Conversion),將資料型別轉換一致後再進 行運算。
那麼同一個運算式中的不同資料型別,編譯器會如何進行型 別轉換?其轉換的順序我們以圖2-7來說明:
型別轉換順序
轉換型別時,如果是由低階的型別轉換成高階型別並不會發 生問題。
如果是由高階型別轉換成低階型別時,由於記憶體空間縮 小,有可能降低資料本身的精確度,倘若資料空間太小也會 形成資料錯誤!這是我們在進行資料轉換時必須特別注意的 地方。
2-5-1 型別自動轉換
運算式中有不同的資料型別,通常會以高階型別為轉換 依據;
也就是說,編譯器會先找尋是否有double型別,然後是 float型別,才是long型別,最後是int型別。請開啟原有範 例「radius.cpp」。
程式解說
因為在第2行已將area變數宣告為整數,即使第3 行的運算式(PI*radius*radius)計算過程中已自動 轉換為float(因為是變數中的最高階),但是卻把 結果儲存為int型別的area變數中,因此我們會得 到的圓面積是「201」整數。
這表示運算後的資料由高階float再轉換成低階的 int,會讓資料失去精確度!
那麼要如何改善這樣的情形?只要把area變數宣
告為float型別,問題就能迎刃而解。
修改範例:radius.cpp部份程式碼
執行程式
第8行:area變數宣告為float時,計算的結果就會
不一樣。
2-5-2 強迫型別轉換
我們也可以在運算式中加入指定的型別,讓運算式
依據指定方式來轉換。強迫型別轉換的語法:
範例:conver.cpp
我們利用一個簡易溫度轉換範例來說明強迫型別轉換的作法