字元與字串
一、字元與 ASCII 碼
一個英文字母、數字或其他的符號,我們稱它為字元。要表示一個字元,我們可以用一對單引號 ' 把該字元夾起來,例如:
char c='a';
而要在 scanf 及 printf 讀入及印出一個字元則是使用 %c。除此之外,在 C 語言中也有一些特殊字元,通常以反斜線 \ 開頭:
'\0' 空字元,用於字串的結束
'\n' New Line,換行符號
'\r' Carriage Return,回歸鍵(即 Enter 鍵)
'\t' Tab,跳格
'\b' Backspace,倒退鍵
'\a' Bell,嗶一聲
'\\' 反斜線 \
'\'' 單引號 '
'\"' 雙引號 "
事實上,字元在電腦中是以一個八位元的整數來儲存(即 1 Byte),而這個符號與數字的對應關係我們稱為 ASCII 碼 (American Standard Code for Information Interchange),例如:
|
數字 |
符號 |
數字 |
符號 |
數字 |
符號 |
|
48 |
0 |
65 |
A |
97 |
a |
|
49 |
1 |
66 |
B |
98 |
b |
|
50 |
2 |
67 |
C |
99 |
c |
|
51 |
3 |
68 |
D |
100 |
d |
|
52 |
4 |
69 |
E |
101 |
e |
|
... |
... |
... |
... |
... |
... |
也就是說,其實字元也是一個數字,因此也可以拿來做加減乘除等四則運算。例如
char c='a';
c=c+3;
printf("%c", c);
上面的例子會印出字元 d。至於下面的程式可以印出 A 到 Z 及它們的 ASCII 碼值:
#include <stdio.h>
void main()
{
char c;
for(c='A'; c<='Z'; c++)
printf("%c %d\n", c, c);
}
二、字串
接下來,我們討論到字串,字串就是一段文字,我們可以用一對雙引號 " 把該段文字夾起來。而要在 scanf 及 printf 讀入及印出一個字串則是使用 %s。由於 C 語言中並沒有字串的變數型態,而是用字元的陣列來儲存一個字串,例如:
char s[20], t[20]="TCGS";
scanf("%s", s);
printf("%s", s);
上面的例子宣告了 s 是一個字串,長度為 20 個字元。我們在宣告字串的時候要注意它的長度,以免位數不夠造成程式錯誤。事實上,每個字串後面都有一個 '\0' 的字元,也就是說,上面的 "TCGS" 字串,事實上總共用了 5 Bytes,這一點要特別注意。另外,由於 s 本身就是這個字元陣列的位址,所以在 scanf 裡我們不需要加上 & 符號。
不過,用 scanf 讀取字串時,遇到空白字元便會結束,例如輸入 "Hello! TCGS!",則讀進來的字串只有 "Hello!" 而已。為了避免這個情況,我們再介紹兩個函數 gets 、puts (也是定義在 stdio.h),gets 的功能是讀入字串,而 puts 則是印出字串:
gets(s);
puts(s);
上面要注意的是,如果是使用 gets,會連換行一起讀進來,也就是字串後面會多一個 '\n' 字元。也由於 C 語言中的字串是字元的陣列,所以如果我們要知道第 N 個字元,就是用 s[N-1] 的方式取得。不過,如果我們要做字串的比對、字串串接、字串長度等功能,沒有運算子可以使用,故必須使用函數來處理。和字串相關的函數都是定義在 string.h 中,常用的字串函數如下:
strcpy(s1, s2) 將 s2 的內容複製到 s1
strcmp(s1, s2) 比較 s1、s2 的內容,如果相等傳回 0
strcat(s1, s2) 將 s2 串接到 s1 後面
strstr(s1, s2) 傳回 s2 字串在 s1字串中第一次出現的位置
strlen(s1) 傳回 s1 的長度(不含 '\0' 字元)
strrev(s1) 將 s1 字串倒置
三、編碼問題
在第二次世界大戰中,德軍的通訊編碼被美國破解,以致於機密被美國竊聽而慘敗。德軍的編碼規則(假)如下:將訊息每個字母往後推兩位再傳出去,例如 A→C、B→D,而後面的 Y→A、Z→B,所有的訊息都是大寫字母。而收到訊息的則是將每個字母往前推兩位,例如 C→A、D→B,而前面的 A→Y、B→Z。假設你是美軍的情報軍,要快速編碼及解碼德軍的訊息,希望完成一個程式,第一個字元為 + 代表要編碼,第一個字元為 - 代表要解碼,程式執行如下(粉紅色為輸入、淺藍色為輸出):
+FIRE
HKTG
-UVQR
STOP
整個程式如下:
#include <stdio.h>
#include <string.h>
void main()
{
char s[80];
int i;
scanf("%s", s);
if(s[0]=='+')
for(i=1; i<strlen(s); i++) {
s[i]+=2;
if(s[i]>'Z') s[i]-=26;
}
if(s[0]=='-')
for(i=1; i<strlen(s); i++) {
s[i]-=2;
if(s[i]<'A') s[i]+=26;
}
printf("%s\n", s+1);
}
PS.上例中,s+1 代表從 s[1] 開始的字串。