資料型態、運算子與表示式

40  Download (0)

Full text

(1)

講師: 李根逸 (Ken-Yi Lee), E-mail: feis.tw@gmail.com

資料型態、運算子與表示式

【第⼆二講】

!49

(2)

課程⼤大綱

!50

資料型態 [P.51]

C/C++ 內建的常⾒見資料型態 [P.52]

使⽤用 sizeof 看⼤大⼩小 [P.53]

變數宣告 [P.54]

不同資料型態間的差異 [P.55]

整數 (short int, int, long int) 的可表⽰示範圍 [P.56]

浮點數 (float/double) 的表⽰示法 [P.58]

printf 與 scanf 的格式字串 [P.59]

字⾯面常數的型態 [P.61]

不同型態間的轉換 (隱性/顯性轉型) [P.62]

字元 (char) 的表⽰示法 [P.65]

各種常⾒見運算⼦子:

算數運算⼦子: +-*/% [P.69], 指定運算⼦子: = [P.70]

關係與等號運算⼦子: <, >, <=, >=, ==, != [P.72]

邏輯運算⼦子 [P.73]

運算⼦子優先順序 [P.74]

(3)

資料型態 (Data type)

在⾼高階語⾔言中,為了能夠⽅方便有效 (省時省空間) 的 撰寫程式碼並做出各種複雜的運算,我們需要使⽤用多 種資料型態

例如 : 整數, ⼩小數和⽂文字處理等 ...

電腦內部是使⽤用位元 (Bit) 這個基本單位來表⽰示資料 並儲存於記憶單元 (記憶體) 或輔助記憶單元 (硬碟) 中。

每個位元只可以表⽰示 0 或 1 兩種值

任何資料型態的資料都可以轉換成由⼀一串位元來表⽰示

換句話說,資料型態就是要告訴電腦要怎麼去解釋某⼀一 串位元資料,我們可以規定如何對不同的型態做運算

!51

(4)

C 常⾒見的內建資料型態

資料型態 名稱 ⼤大⼩小

(bytes)

範例

短整數

(Short Integer)

short int 2 32

整數

(Integer)

int 4 32

⻑⾧長整數

(Long Integer)

long int 4 32

字元

(Character)

char 1 ‘3’

單精度浮點數 


(Single Precision Floating Point)

float 4 3.2

雙精度浮點數 


(Double Precision Floating Point)

double 8 3.2

void (無) (無)

!52

⼤大⼩小是《實作相依》

《實作相依》:意指語⾔言標準內容並沒有強制的規定,

在使⽤用不同編譯器或設定的情況下,可能會不⼀一樣

(5)

使⽤用 sizeof 看⼤大⼩小

語⾔言標準內對資料型態沒有嚴格定義⼤大⼩小,隨著編譯 器與設定的不同⽽而可能不同。我們只知道在同樣的編 譯器與設定中,同樣資料型態的⼤大⼩小是固定的。

例如 int 不⼀一定要是 4 個位元組⼤大,只是我們現在⼀一 般的電腦架構與作業系統通常是。⽽而在 32-bit 編譯器 內, long int 的⼤大⼩小可能是 4 個位元組, 但在 64- bit 編譯器中, long int 的⼤大⼩小可能是 8 個位元組

sizeof 是⼀一個特殊的運算⼦子,會得到某變數或資料 型態在該平台編譯後佔有記憶體的⼤大⼩小。我們表⽰示記 憶體⼤大⼩小所使⽤用的單位是位元組 (byte) ,⽽而⼀一個位 元組 (byte) 通常等於⼋八個位元 (bit)

開啟範例檔 sizeof.cpp 並執⾏行看看

!53

(6)

變數宣告

變數名稱在使⽤用前,需要先進⾏行宣告讓編譯器知道:

資料型態 變數名稱;


資料型態 變數名稱 = 初始值;






保留字 (keywords):

C 語⾔言中下列名稱 (保留字) 無法作為變數名稱

auto,break,case,char,const,continue,default, do,double,else,enum,extern,float,for,goto,if, int,long,register,return,short,signed,sizeof, static,struct,switch,typedef,union,unsigned, void,volatile,while

int num;

int num = 0;

名稱通常為英⽂文字⺟母⼤大⼩小 寫、數字和底線構成,數 字不能開頭,⼤大⼩小寫不同 也代表不同的名稱

num

(int)


?

2293620 
 (記憶體位址)

!54

在宣告時給予初始值這動作我們稱為初始化

(7)

表⽰示的資料意涵不同:

整數 (int) 與字元 (char)

表⽰示的原理不同:

整數 (int) 與浮點數 (float)

可表⽰示的範圍⼤大⼩小不同:

短整數 (short int) 與⻑⾧長整數 (long int)

可表⽰示的精確度⼤大⼩小不同:

單精度浮點數 (float) 與倍精度浮點數 (double)

有無正負數 (有號與無號)

有號整數 (int) 與無號整數 (unsigned int)

不同資料型態間的差異

與⼤大⼩小有關

!55

(8)

整數型態的可表⽰示範圍

資料型態可表⽰示的範圍與他佔記憶體的『⼤大⼩小』有關

每個位元可以表⽰示兩種值 (0 或 1) 每個位元組如果有 8 個位元 :

每個位元組可以表⽰示

2

8 =

256

種值

在可表⽰示正負數 (即有號 [signed]) 的情況下,可表⽰示的整數範圍 會是從 -128 到 127 (共 256 個數字)

當無號 [unsigned] 時,可表⽰示的整數範圍是從 0 到 255

如果⼀一個資料型態有 4 個位元組,則可以表⽰示 :

2

8x4 =

2

32 =

4,294,967,296

種值

4 個位元組⼤大的 int 可表⽰示範圍是從

−2,147,483,648

2,147,483,647 (約九位數有效數字)

4 個位元組⼤大的 unsigned int 的可表⽰示範圍就是從

0

4,294,967,295 (約九位數有效數字)

!56

運算結果超出可表⽰示範圍 稱為『溢位』,在溢位的 情況下,值會變多少⼤大部 分情況是《未定義⾏行為》

不要因為 範圍可以

⼤大⼀一點就

⽤用無號數

(9)

【補充】 int 的位元表⽰示法

!57

⼗十進位表⽰示法 ⼆二進位表⽰示法

1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 00 0 0 0 0 0 0 0 0 0 0 0 1 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 00 0 0 0 0 0 0 0 0 0 0 1 0 5 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 00 0 0 0 0 0 0 0 0 0 1 0 1 255 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 00 0 0 0 0 1 1 1 1 1 1 1 1 256 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 00 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 00 0 0 0 0 0 0 0 0 0 0 0 0 2147483647 0 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 11 1 1 1 1 1 1 1 1 1 1 1 1 -1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 11 1 1 1 1 1 1 1 1 1 1 1 1 -2 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 11 1 1 1 1 1 1 1 1 1 1 1 0 -255 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 11 1 1 1 1 0 0 0 0 0 0 0 1 -2147483648 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 00 0 0 0 0 0 0 0 0 0 0 0 0 負數⽤用 2 的

補數表⽰示法: 
 將正數表⽰示 法的 0 和 1 互換後再加 1

32 bits (4 bytes)

如何表⽰示整數是《實作相依》⾏行為,這裡只是列出⼀一般的作法作為參考

(10)

浮點數表⽰示法

浮點數 (floating point) 是⽤用來將實數數位化表⽰示 的⼀一種表⽰示法

我們現在所⽤用的是由 IEEE 制定的浮點數表⽰示標準

簡單來看,浮點數的表⽰示法將位元分成三個區塊

符號位元 (1 Bit), 指數部分, ⼩小數部分

0 0 0 1 1 1 1 0 0 0 0 1 1 0 1 1

0 0 0 1 1 1 1 0 0 0 0 1 1 0 1 1

+ 3 1563

+ 0.1563 10 3

(指數)

(符號) (有效數字) [影響精確度]

(實際上格式⽐比較複雜,這裡只是個概念的說明。細節可參考 http://goo.gl/imXGf)

7707

!58

float 有效數字約6位,double 約15位

(11)

printf 與 scanf 的格式字串

資料型態 名稱 格式符

短整數 (Short Integer)

short int %hd

整數 (Integer)

int %d

⻑⾧長整數 (Long Integer)

long int %ld

字元 (Character)

char %c

單精度浮點數 


(Single Precision Floating Point)

float %f

雙精度浮點數 


(Double Precision Floating Point)

double %f, %lf

!59

printf scanf

(12)

【範例】使⽤用浮點數

請修改程式讓使⽤用者分別輸⼊入三個整數後,算出三個 整數的和、平均值、乘積並顯⽰示給使⽤用者看 (四捨五

⼊入到⼩小數點後三位 )

注意: 平均值可能具有⼩小數⽽而且使⽤用者可能輸⼊入的數值 帶有⼩小數

變數宣告時須改為⽤用 float 宣告

scanf 和 printf 須使⽤用 %f 來讀⼊入或輸出 float printf 的格式字串可以加上數字表⽰示位數

%.3f 表⽰示印出浮點數並四捨五⼊入到⼩小數點後第三位

!60

【範例】 calc.cpp

(13)

字⾯面常數的型態

字⾯面 資料型態 名稱

3 整數

(Integer)

long int int


3u 無號整數

(Unsigned Integer)

unsigned int

3l ⻑⾧長整數

(Long Integer)

long int

3. 雙精度浮點數

(Double Precision Floating Point)

double

3.f 單精度浮點數

(Single Precision Floating point)

float

‘3’ 字元

(Character)

char

!61

【補充】在能表⽰示的 情況下整數選前者

【範例】 constant.cpp

(14)

不同型態間的轉換

編譯器為了讓你的運算式合理,可能會試著幫你做型 態的⾃自動轉換 (隱性轉型)。

不同基本資料型態間的⾃自動轉換 (隱性轉型) 通常以

『可表⽰示範圍⼤大』的為準

例如 :

4 / 3 時,計算結果的資料型態會是 int

4 / 3. 時,4 是 int ⽽而 3. 是 double。計算時會先將 4 轉換成 double 後再除以 3.,計算結果資料型態是 double。

你也可以⽤用強制的⽅方式進⾏行型態轉換 (顯性轉型):

例如:

4 會先被強制轉換為 double 型態 (即 4. ),再試著去除以 3,此時 3 也被動的隱性轉型成 double 型態 (即 3.)。計算結果的資料型態 會是 double

4 / 3 與 4 / 3.

(double) 4 / 3

!62

(15)

【範例】隱性轉型與格式

請開啟範例檔,並猜測執⾏行結果 提⽰示與解釋:

A = B 是指將 B 的值給 A,此時如果 B 的型態與 A 不 同則可能會造成無法編譯或發⽣生隱性轉型將 B 轉為 A 的型態

轉型時,浮點數轉為整數是無條件捨去,通常值會變得不精確

要⼩小⼼心的是,使⽤用 printf 或 scanf 時,輸⼊入的引數並 不會⾃自動的轉型

例如: printf(“%d”, 3.);

會因為 3. 是 double 卻當成 int 印⽽而失敗,產⽣生不易預期的結果 printf 跟 scanf 這算是特例中的特例,但是我們常常使⽤用到。

!63

【範例】 casting.cpp

(16)

【範例】⼤大數計算

試寫⼀一程式輸⼊入兩個五位數整數後輸出他們的乘積

int 的資料型態⼀一般情況下約可表⽰示 log(231) ~ 9 位有 效整數

【補充】使⽤用範圍更⼤大的整數型態

C++99 (新版 C++ 標準) 和 C99 (新版 C 標準) 中有

⼀一個 long long int 的資料型態⾄至少可表⽰示約 log(263)

~ 19 位有效整數

Dev C++ 中,請在 printf 內使⽤用 %I64d 來列印 long long int 型態數值

GCC 編譯器中,long long int 是⼀一個語⾔言擴充功能

!64

【範例】 bignum.cpp

(17)

‘A’+1=?

(char) (int)

‘A’-1=?

(char) (int)

‘A’+’1’=?

(char)(char)

(???)

(???)

(???)

在輸⼊入、儲存和運算時,char 都是使

⽤用整數(ASCII值)格式,只有在輸出 (顯⽰示或列印) 的時候會依照該 ASCII 值所對應的⽂文字套⽤用字型後輸出

【範例】 char.cpp 字元 (char) 是⼀一種整數型態

(18)

【範例】⼤大⼩小寫轉換

試寫⼀一程式輸⼊入⼀一⼤大寫英⽂文字元,顯⽰示相對應的⼩小寫 英⽂文字元

提⽰示:

!66

範例輸⼊入⼀一 :


A

範例輸出⼀一 :


a

範例輸⼊入⼆二 :


B

範例輸出⼆二 :


b

範例輸⼊入三 :


Z

範例輸出三 :


z

char input = ?; 


char output = input - ‘A’ + ‘a’;

【範例】 tolower.cpp

(19)

【補充】關於字元

就前⾯面的解釋我們了解字元的處理⽅方式是利⽤用建表編 號的⽅方法來達成。但在 C/C++ 語⾔言標準中並沒有 強制規定字元所使⽤用的編號表格 (只規定要能表⽰示其 95 個字元),像是⼀一般電腦⽤用的是 ASCII 或是 ISO/IEC 646 的編碼標準都是可能的。

⼀一個字元 (char) 原則上由⼀一個位元組構成,但是⼀一個 位元組並不⼀一定是有 8 位元 (某些古⽼老或特別的電腦結 構)

⽽而也因為未嚴格規定編碼表格, char 資料型態不⼀一 定等價於 signed char 或 unsigned char,此為

《實作相依⾏行為》。

!67

(20)

使⽤用型態的選擇

那麼我們到底應該選擇怎樣的資料型態呢?

!

!

!

!

!

對於初學者只要熟悉使⽤用這些資料型態就夠了

其他型態的⽤用途?

最佳化記憶體的使⽤用或效率

⽤用途 資料類型 格式符

整數 (⼀一般情況) int %d

浮點數 (有⼩小數或位數過⼤大) double %f %lf

字元 char %c

printf scanf

!68

(21)

算術運算⼦子 : +-*/%

算術運算⼦子運算的結果與運算元的值跟型態有關

運算⼦子是有優先順序的 (*/% 優先於 +- ) 算術運算⼦子優先順序相同時,在左邊的先

每次執⾏行⼀一個運算⼦子時就會產⽣生⼀一個中間結果,我們 稱為『暫時變數』,我們要了解這暫時變數的『值』

與『型態』:

A = 3 * ( 2 + 1 ) + 7 / 2 + 9 * 3.;

A = 3 * 3 + 7 / 2 + 9 * 3.;

A = 9 + 7 / 2 + 9 * 3.;

A = 9 + 3 + 9 * 3.;

A = 9 + 3 + 27. ; A = 12 + 27. ; A = 39. ;

!69

(22)

【範例】賦值運算⼦子 : =

= 為賦值運算⼦子

賦值運算⼦子會將右⽅方的值給左⽅方的變數

賦值運算⼦子的左⽅方⼀一定要放置某個變數。

賦值運算⼦子的運算結果就是左⽅方變數最後的值跟型態

運算優先順序

賦值運算⼦子 (=) 的運算優先順序是全部裡⾯面最低的⽽而 且運算順序是由右⾄至左 (特別!)

int A,C;


double B, D;


A = 3;


3 = A;


A = C = 3;


A = B = C = D = 3 + 7 / 2.;

!70

【範例】 assign.cpp 這結果會是什麼?

(23)

!

!

!

!

!

在⼀一般 C 語⾔言標準 (C89/C90) 中,我們使⽤用 int 型態來儲存是⾮非真假對錯:

0 表⽰示假的、錯誤和不成⽴立的意思 1 表⽰示真的、正確和成⽴立的意思 2 表⽰示真的、正確和成⽴立的意思 -1 表⽰示真的、正確和成⽴立的意思

是⾮非真假

!71

運算結果 意

不是 0 真的 正確 成⽴立

0 假的 錯誤 不成⽴立

【補充】在 C++ 中,也可以⽤用 bool 資料類型來表⽰示

(24)

C 語⾔言標準中,關係與等號運算⼦子的運算結果有 不是 0 (成⽴立) 和 0 (不成⽴立) 兩種可能:

關係與等號運算⼦子

運算意義 運算符號

⼤大於 >

⼩小於 <

⼤大於等於 (不⼩小於) >=

⼩小於等於 (不⼤大於) <=

等於 ==

不等於 !=

!72

4 > 3 4 < 3 4 == 3 4 != 3

4 > 3 > 2

【補充】在 C++ 中,運算結果是 true 與 false 兩種可能

(25)

邏輯運算⼦子

C 語⾔言標準中,邏輯運算⼦子的運算結果有不是 0 (成⽴立) 與是 0 (不成⽴立) 兩種可能:

運算意義 運算符號 iso646.h

C++

⽽而且 (and) &&

and

或者 (or) ||

or

⾮非 (not) !

not

!73

4 > 3 && 4 < 3 4 > 3 || 4 < 3

3 > 2 && 1 > 2 1 || 0

4 > 3 && 3 > 2

!(3 > 2)

!3

(26)

運算⼦子優先順序表

運算符號 平⼿手時運算順序

( )

由左⾄至右

!

由左⾄至右

* / %

由左⾄至右

+ -

由左⾄至右

< > <= >=

由左⾄至右

== !=

由左⾄至右

=

由右⾄至左

&& 由左⾄至右

|| 由左⾄至右

優先

不優先

!74

(27)

【補充】邏輯運算⼦子的特殊性

|| 與 && 運算⼦子都保證左邊運算元被算出後,才會 開始算右邊運算元的值。

其他運算⼦子不是喔!之前我們只保證運算⼦子的運算順序

|| 左邊運算元算出為⾮非 0 時,就不會去算右邊運 算元的值。反之當 && 左邊運算元算出為 0 時,就 不會去算右邊運算元的值。

為什麼可以這樣?

!75

(28)

if 關鍵字

if( 表⽰示式 ) { ... }

如果 表⽰示式 為真就 ...

什麼是真或假?

⾮非0 或 0、成⽴立或不成⽴立

if (80 >= 60) { 


printf(“PASSED !\n”);


}


if (80 < 60) { 


printf(“FAILED !\n”);


}

int grade = 80;


if (grade >= 60) { 


printf(“PASSED !\n”);


}


if (grade < 60) { 


printf(“FAILED !\n”);


}

!76

(29)

【範例】⽐比較兩數⼤大⼩小

試寫⼀一程式讓使⽤用者輸⼊入兩個數字後顯⽰示其中⽐比較⼤大 的給使⽤用者看 :


提⽰示 : (程式⽚片段)

請輸⼊入第⼀一個整數 : 3
 請輸⼊入第⼆二個整數 : 4


⽐比較⼤大的整數是 : 4

int max;


if (num1 >= num2) {
 max = num1;


}
 if (num1 < num2) {
 max = num2;


}


printf(“⽐比較⼤大的整數是 %d\n”, max);


!77

【範例】 cmp.cpp

(30)

【練習】簡易版猜數字

試寫⼀一個程式,在程式內部預設⼀一個整數作為猜數字 遊戲的答案。當使⽤用者執⾏行程式後,需要輸⼊入⼀一個整 數,如果該整數與程式預設的答案不同,請顯⽰示是⽐比 較⼤大或者⽐比較⼩小;如果該整數與程式預設的答案相同,

請恭喜使⽤用者:

!

!

!

!

【思考】要如何讓使⽤用者可以⼀一直猜到答案正確?

請輸⼊入你的猜測 : 4
 答對了!

!78

請輸⼊入你的猜測 : 5
 太⼤大了!

請輸⼊入你的猜測 : 3
 太⼩小了!

(31)

【補充】逐位元運算⼦子

!79

運算意義 運算符號

逐位元 AND &

逐位元 OR |

逐位元 XOR ^

逐位元 NOT ~

逐位元左移 <<

逐位元右移 >>

(32)

習題 [1]

[E0201] 試寫⼀一程式,印出下⾯面這個變數值 :

double x = 3000000000000000.5;

[E0202]* 試寫⼀一程式,印出下⾯面式⼦子的計算結果 :

3000000000000000.5+0.05

[E0203] 試寫⼀一程式,輸⼊入英哩換算後印出公⾥里 (四捨五⼊入⾄至⼩小數點後⼀一位) [公⾥里 = 英哩 * 1.6]

[E0204] 試寫⼀一程式印出 129263*54628 的結果

與 [E0110] 相同

[E0205]* 試寫⼀一程式算出 1292635428 三次⽅方 的值 (2159872744519190546127922752)

!80

(33)

習題 [2]

[E0206] 試寫⼀一程式,輸⼊入⼀一有號整數,顯⽰示該整 數是正整數 (>=0) 或負整數 (< 0)

[E0207] 試寫⼀一程式,輸⼊入⼀一字元,顯⽰示該字元是 數⼦子 (0-9)、英⽂文字元 (a-zA-Z) 或其他符號

字元 (char) 請在 scanf 內⽤用 %c 讀⼊入,在 printf 內

⽤用 %c 印出

[E0208] 試寫⼀一程式,輸⼊入⼀一個英⽂文⼩小寫字元,將 字元轉換為⼤大寫印出

[E0209] 試寫⼀一程式,輸⼊入⼀一個英⽂文字元,將字元 的⼤大寫印出 (不限制輸⼊入的字元為⼤大寫或⼩小寫)

!81

(34)

習題 [3]

[E0210] 試寫⼀一程式,輸⼊入兩個整數,將兩個整數 由⼩小到⼤大印出。 


!

[E0211] 試寫⼀一程式,讓使⽤用者輸⼊入⼀一⼋八位整數然 後將數字直排顯⽰示。

範例輸⼊入⼀一: 3 6 範例輸出⼀一: 3 6 範例輸⼊入⼆二: 6 3 範例輸出⼆二: 3 6

!82

請輸⼊入⼀一個⼋八位數整數: 38603456


3
 8


6
 0


3
 4


5
 6

(35)

習題 [4]

[E0213] 試寫⼀一程式,讓使⽤用者輸⼊入⾝身分證字號的 前九碼後顯⽰示該⾝身分證字號的第⼗十碼 (驗證碼)

我們的檢查碼計算⽅方式 : (A: 10, B:11, C:12, ..., Z:36)

!

!

!

!

總和 = 1x1 + 0x9 + 1x8 + 2x7 + 3x6 + 4x5 + 5x4 + 6x3 + 7x2 + 8x1 = 121

121%10 = 1, (10-1)%10 = 9

A 1 2 3 4 5 6 7 8

1 0 1 2 3 4 5 6 7 8 x1 x9 x8 x7 x6 x5 x4 x3 x2 x1

%c%d

!83

(36)

!84

(37)

!85

(38)

!86

(39)

!87

(40)

!88

Figure

Updating...

References

Related subjects :