六、循環
🎈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中 整數的輸入和輸出只有兩種形式:int和long 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中 浮點數分成兩種 分別是float和double
它們的區別是大小、範圍、有效數字不一樣:
-
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
但在強制類型轉換的時 需注意值的範圍導致的安全性問題
強制類型轉換的優先級高於四則運算