雖然在基本資料型態中我們有簡單提到字元,但我們其實還有很多東西沒有講到,所以這個章節我們就來更深入的了解一下字元!
所謂的字元就是指一個字,通常為符號、字母、數字還有換行字元等等,好比說 a、1、+、\n。
基本用法#
在 C++ 中,字元的型態是 char,宣告方式如下,不過要記得所有的字元都要用單引號 ' 包住:
char c = 'a';
cout << c << endl; // a
注意
請不要使用雙引號 " 來包住字元,因為這樣會變成字串,而不是字元:
char c = "a"; // 這樣是錯誤的
關於字串的部分,我們會在之後的章節詳細介紹。
ASCII 編碼#
在繼續學習字元之前,我們得先了解一下 ASCII 編碼。
ASCII 是一種字元編碼方式,它將字元和數字一一對應起來,用來在電腦中儲存字元。每一個字元都有自己的 ASCII 碼,比如說 a 就是 97,b 就是 98,0 就是 48,A 就是 65,等等。常見字元的 ASCII 編碼如下:
| 種類 | 內容 | 編碼 |
|---|---|---|
| 數字 | 0~9 | 48~57 |
| 大寫字母 | A~Z | 65~90 |
| 小寫字母 | a~z | 97~122 |
| 空白 | 32 |
ASCII 與字元#
實際上字元在記憶體中其實是一個整數(ASCII 編碼),只是在輸出時會轉換成對應的字元。所以如果你想要知道字元的 ASCII 碼,可以把它強制轉型成 int 再輸出:
char a = 'a';
cout << (int)a; // 97
或者如果你需要的話,也可以把整數換成字元:
int a = 97;
cout << (char)a; // a
不過既然是整數,當然也可以進行運算:
char a = 'a';
char b = 'b';
cout << a + b << endl; // 195
cout << a + 1 << endl; // 98
cout << (char)(a + 1) << endl; // b
還可以這樣賦值:
char a = 97;
cout << a << endl; // a
字元與整數之間的轉換#
前面我們提到,字元在記憶體中其實是一個代表 ASCII 碼的整數,所以當然可以被當作整數來用。不過要注意的是,字元和整數相加的時候,會被當作 ASCII 碼來運算,而不是「數字」。舉例來說:
char one = '1';
char two = '2';
cout << one + two << endl; // 99
那如果想要把字元轉成「數字」呢?這邊有一個小技巧,就是減去字元 '0',這樣就可以得到對應的數字了。這是因為 ASCII 碼中數字 '0' 到 '9' 是連續的,所以只要減去 '0' 就可以得到對應的數字,也就是他們的差值:
char one = '1';
char two = '2';
int one_num = one - '0';
cout << one_num << endl; // 1
int two_num = two - '0';
cout << two_num << endl; // 2
cout << one_num + two_num << endl; // 3
cout << two_num * 5 << endl; // 10
反過來,如果想要把數字轉成字元,只要加上 '0' 就可以了:
int a = 1;
int b = 2;
char a_char = a + '0';
cout << a_char << endl; // 1
char b_char = b + '0';
cout << b_char << endl; // 2
cout << a_char + b_char << endl; // 99
字元的比較#
字元之間的比較和整數一樣,可以用 ==、!=、<、>、<=、>= 來比較。不過要注意的是,字元之間的比較是根據 ASCII 碼來比較的,舉例來說:
char a = 'a';
char b = 'b';
char c = 'c';
cout << (a < b) << endl; // true
cout << (a < c) << endl; // true
cout << (a > c) << endl; // false
和判斷字元有點相關的函式們#
isalpha 這個函式是拿來判斷字元是否為字母,不是的話就回傳 0,否則就是一個非零整數。
char a;
cin >> a;
if (isalpha(a)) cout << "Yes";
else cout << "No";
isdigit 跟上面有點像,只是這次是判斷字元是不是數字,也是回傳 0 或非零整數。
char a;
cin >> a;
if (isdigit(a)) cout << "Yes";
else cout << "No";
isalnum 則是判斷字元是不是字母或數字,也是回傳 0 或非零整數。
char a;
cin >> a;
if (isalnum(a)) cout << "Yes";
else cout << "No";
islower 和 isupper 則是判斷字元是不是小寫或大寫字母,也是回傳 0 或非零整數。
char a;
cin >> a;
if (islower(a)) cout << "Yes";
else cout << "No";
char a;
cin >> a;
if (isupper(a)) cout << "Yes";
else cout << "No";
注意
再次強調,這邊有一點必須非常注意,isalpha、isdigit、isalnum、islower、isupper 以上這些函式回傳的是 int,而不是 bool,而且可能的回傳值不只有 0 和 1,有些人可能會直覺的這麼寫:
if (isalpha(a) == 1) cout << "Yes";
else cout << "No";
但這樣寫是錯誤的,isalpha 的回傳值可能會因為不同字元、不同編譯器或者版本而有所不同,所以請絕對不要這樣寫!
來看看這份程式碼:
for (auto c = 'a'; c <= 'z'; c++) {
cout << isalnum(c) << " ";
}
for (auto c = 'A'; c <= 'Z'; c++) {
cout << isalnum(c) << " ";
}
for (auto c = '0'; c <= '9'; c++) {
cout << isalnum(c) << " ";
}
以下是使用 GNU G++20 13.2 (64 bit, winlibs) 編譯器測試上面這段程式碼的結果:
2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 2 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 4 4 4 4 4 4 4 4 4 4
可以看到 isalnum 回傳的值絕對不只有 0 和 1,所以請記得不要把 isalpha、isdigit、isalnum、islower、isupper 拿來跟 1 比較!
下面這兩種寫法才是正確的:
if (isalpha(a)) cout << "Yes";
else cout << "No";
if (isalpha(a) != 0) cout << "Yes";
else cout << "No";
