全面學習C語言【二】:循環(while、do-while、for)、類型(整數int、unsigned、浮點數float、字符char、布爾bool)、類型轉換

六、循環

🎈while循環

C的while循環和Java是一樣的

while(x>0)
{
	printf("1");
}

🎈do-while循環

C的do-while循環也和Java是一樣的
在進入循環的時候不做檢查 在執行完一輪循環體的代碼之後再來檢查循環的條件是否滿足
若滿足 則繼續下一輪的循環
若不滿足 則結束循環

do
{
	printf("0");
}
while(x>0);

🎈for循環

C的for循環和Java是一樣的 只不過在ANSI C中 初始值需在for循環的外部定義 否則會報錯

int i;
for (i=1;i<10;i++)
{
	printf("1");
}

七、類型

🎈類型的分類

  • 整數
    • char
    • short
    • int
    • long
    • long long(C99獨有)
  • 浮點數
    • float
    • double
    • long double(C99獨有)
  • 邏輯
    • bool(C99獨有)
  • 指針
  • 自定義類型

🎈整數

🚩所佔字節數

注:1字節=8比特(bit)

  • char - 1字節
  • short - 2字節
  • int - 4字節(取決於寄存器CPU是32還是64 通常意義是1個字)
  • long - 8字節(有可能是4字節 取決於寄存器CPU是32還是64 通常意義是1個字)
  • long long(C99獨有) - 8字節

🧲爲縮減篇幅 關於負數在計算機內部的二進制表示和補碼之類的知識點 請參看我的另一篇博客:C語言中負數在計算機內部的二進制表示方式(以補碼錶示負數、整數的範圍及所佔字節數)

🚩unsigned關鍵字

char a=255;
printf("%d",a);

在C中 char的255默認是-1

在定義的時候添加unsigned 則可使該整數不以補碼的形式表示
即 默認是以1開頭來表示負數的 但加上了unsigned 1開頭也表示正數了
如此 該整數沒有負數部分 只有0和正數部分
這樣 該數所能表達的範圍 在正數部分就擴大了 但與此同時 沒有了負數部分

例如:

unsigned char a=255;

這樣 輸出的就是255

一個字面量若要表示自己爲unsigned 可在後面加上u或U
例如:

255U // 此時表示的不是十進制的-1 而是255了

🚩整數越界

整數是以純二進制的方式進行運算的

例如:

11111111+1 = 100000000=0
01111111+1 = 10000000 = -128
10000000-1 = 01111111 = 127

對於char來說 正負數有兩個範圍 正數是從0~127 負數是從-128~-1
這兩個範圍是連着的 因此 會-1+1=0 0…127 127+1=-128 -127…-1 如此循環

但對於unsigned的char來說 255+1則會變成0 因爲unsigned的char的最大範圍只有255
同樣 0-1的結果是255
可以看作是一個圓環 正數和負數是連着的

🚩整數類型的輸入和輸出

在C中 整數的輸入和輸出只有兩種形式:intlong long

所有小於int的類型(char short int) 都使用%d進行輸入輸出
所有大於int的類型(long和long long)都使用%ld進行輸入輸出

unsigned的類型使用%u進行輸入輸出
unsigned的long long使用%lu進行輸入輸出

不管在計算機內部是以幾進制的形式表達的 輸出的時候只在乎%後面的輸出格式 它只會根據指定的格式輸出
讀入的時候也是同理

以0開始的數字字面量是八進制
以0x開始的數字字面量是十六進制
八進制整數使用%o進行輸出(若要輸出大寫 則%O)
十六進制整數使用%x進行輸出(若要輸出大寫 則%X)
八進制和十六進制只是如何將數字轉換爲字符串 與計算機內部如何表示無關 計算機內部永遠是二進制的

若讀入的時候爲%o 則代表以八進制來讀入
十六進制也是同理

🚩總結:

通常整數使用int即可
unsigned與否 只是輸出時候的不同 在計算機內部計算時是一樣的

🎈浮點數

在C中 浮點數分成兩種 分別是floatdouble

它們的區別是大小、範圍、有效數字不一樣:

  • float字長32位 即佔據4個字節
    double字長64位 即佔據8個字節

  • float的範圍是±(1.20×10^-(38) ~ 3.40×10^38)、0、±inf(無窮大/小)、nan
    double的範圍是±(2.2×10^-(308) ~ 1.79×10^308)、0、±inf(無窮大/小)、nan

  • float的有效數字是7 在7位之後即不準確了
    double的有效數字是15 在15位之後即不準確了

🚩輸入和輸出

float在輸入的時候是%f(相當於是float)
double在輸入的時候是%lf(相當於是long float)

float在輸出的時候是%f%e/%E
double在輸出的時候也是%f%e/%E
%e/%E指的是使用科學記數法來表示
例如:

double lf=1234.56789;
printf("%e\n",lf); // 1.234568e+003

科學記數法是使用形如-1.23E+12的格式來表示小數 使用科學記數法表示的數中間不能有空格

🚩輸出精度

double lf=1.23E-10;
printf("%f",lf); // 0.000000

可以在%和f之間加上.n以指定要輸出小數點後幾位數(n即爲要輸出的位數)
例如:

double lf=1.23E-10;
printf("%.13f",lf); // 0.0000000001230

此時的輸出是四捨五入
例如:

double lf=-0.0048;
printf("%.2f\n",lf); // -0.00
printf("%.3f\n",lf); // -0.005
printf("%.4f\n",lf); // -0.0048

🚩浮點數的範圍

當printf輸出超過範圍的浮點數時 會輸出±inf/#INF00 表示無窮大/小
而 當printf輸出不存在的浮點數時 會輸出nan/#IND00

printf("%f\n",12.0/0.0); // 1.#INF00
printf("%f\n",-12.0/0.0); // -1.#INF00
printf("%f\n",0.0/0.0); // -1.#IND00

浮點運算是沒有精度的 因此 浮點數的計算會有極小的誤差

帶有小數點的字面量默認是double 而不是float
若需要表示爲float 則需要使用f或F作爲後綴

浮點數的不能用==來判斷 若要判斷浮點數 則將兩個浮點數相減 取絕對值 然後和該浮點數類型所能表達的精度進行比較
比如:fabs(f1-f2)<le-8

但若要對浮點數進行運算 比如1.23塊錢 那麼可以使用分作爲單位(即123分) 然後用整數來運算 即可規避誤差了

🚩總結:

通常浮點數使用double即可
現代的CPU能夠直接對double類型的浮點數做硬件運算 其性能不比float差
而 在64位的計算機上(現在大部分計算機都是64位了) 數據存儲的速度也不比float慢

🎈字符

char可以用於表示正數
但同時 也可以表示字符(character)

可以用單引號來表示字符字面量 比如'a''123'
''也是一個字符 只不過是空字符

使用%c來輸入和輸出字符

char c1=1;
char c2='1';

printf("%d\n",c1); // 1
printf("%d\n",c2); // 49
printf("%c\n",c2); // 1

整數類型的1 和 字符類型的1 轉換爲整數後輸出的值是不一樣的

若以字符的形式讀入:

char c;
scanf("%c",&c); // 輸入1

printf("%d\n",c); // 49
printf("%c\n",c); // 1

若以整數的形式讀入:

char c;
scanf("%d",&c); // 輸入49

printf("%d\n",c); // 49
printf("%c\n",c); // 1

在計算機的內部 每個字符都有一個數值與之對應 這套編碼就是ASCII碼
在ASCII碼錶中 49和’1’是相等的 因此 在char類型裏 可以互相轉換

printf("%d",49=='1'); // 1

🚩混合輸入

在輸入的時候 有空格和沒有空格是不一樣的
比如:

scanf("%d %c",&i,&c);

這種情況 中間帶有空格 那麼在輸入整數類型和字符類型的時候 會在讀完整數之後過濾掉整數後面的空格 然後讀取字符

輸入123a 讀取到的是i=123,c=‘a’
輸入123 a 讀取到的是i=123,c=’a’
輸入123   a 讀取到的還是i=123,c=’a’

但是 若中間不帶空格 比如:

scanf("%d%c",&i,&c);
輸入123a 讀取到的是i=123,c=’a’
輸入123 a 讀取到的卻是i=123,c=’ ’
輸入123   a 讀取到的還是i=123,c=’ ’

這種情況 在輸入整數類型和字符類型的時候 會在讀完整數之後直接讀後面的了 那麼 在遇到空格後會將空格當作要讀的字符讀入

🚩字符計算

字符同樣可以直接進行計算
字符加減數字 會得到ASCII碼錶中 該數相對應的字符

char c1='b';
char c2='b';
c1++;
printf("%c\n",c1); // 'c'
c2--;
printf("%c\n",c2); // 'a'

字符之間相互加減 會得到它們在ASCII碼錶中的距離(即字符對應的數值的和差)

int i1='c'-'a';
printf("%d\n",i1); // 2
int i2='a'-'c';
printf("%d\n",i2); // -2

由於字母在ASCII碼錶中是按順序排列的
因此 有個小技巧:‘a’-'A’可以得到大小寫字母的排列位置的距離 然後c-('a'-'A')即可將大寫字母轉換爲小寫字母
同理 c+('a'-'A')可將小寫字母轉換爲大寫字母

char c1='b';
printf("%c\n",c1-('a'-'A')); // ‘B’
char c2='B';
printf("%c\n",c2+('a'-'A')); // ‘b’

🚩逃逸字符

逃逸字符用於表示無法打印出來的控制字符或特殊字符
逃逸字符由反斜槓\開頭 後跟另一個字符
逃逸字符是由這兩個字符組合而成的

字符 意義
\b 回退一格
\t 到下一個表格位
\n 換行
\r 回車
\" 雙引號
\‘ 單引號
\ 反斜槓本身

🎈邏輯 / boolean

C語言原來是沒有布爾類型的 而是用0和1來判斷
從C99開始有了bool類型 但必須先#include <stdbool.h>

#include <stdio.h>
#include <stdbool.h>

int main()
{
	bool b1=2>1;
	bool b2=true;
	
	printf("%d\n",b1); // 1
	printf("%d\n",b2); // 1
}

由於C中默認是沒有boolean類型的 因此輸出的時候只好用整數來輸出
同樣 輸出後是0或1的數值 而不是true或false

🎈類型轉換

當運算符的兩邊出現了不一致的類型時 會自動轉換成較大的類型
這個大的意思 就是所能表達的數的範圍更大

char -> short -> int -> long -> long long

int -> float -> double

C語言會自動進行類型轉換 無需手動操作

🚩自動類型轉換

對於printf 任何小於int的類型都會被自動轉換爲int
float會被自動轉換爲double

但scanf不會進行自動類型轉換 因此 在輸入的時候 若要輸入short類型的數 則需要使用%hd

🚩強制類型轉換

強制類型轉換 就是將一個類型強制轉換爲另一個類型(通常是大類型轉換爲小類型)
格式:(類型)值
比如:

(int)1.2
(short)12

但在強制類型轉換的時 需注意值的範圍導致的安全性問題

強制類型轉換的優先級高於四則運算


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章