14.1 字串常值(String Literals) - JunWu - 屏東大學
文章推薦指數: 80 %
所謂的字串(string)是指一些字元的集合,例如“Hello”這個用雙引號框起來的字元集合就是一個字串。
在C語言中,這種用雙引號框起來的字串又稱為字串常值(string ...
跳至內容
JunWu的教學網頁國立屏東大學資訊工程學系CSIE,NPTU
使用者工具
登入
網站工具
搜尋
工具輸出PDF檔案多媒體管理器網站地圖登入>
多媒體管理器網站地圖
足跡:•string
c:string
目錄表
14.字串
14.1字串常值(StringLiterals)
14.2字串變數
14.3字串的輸出
14.4字串的輸入
14.4.1scanf()函式
14.4.2gets()與fgets()函式
14.4.3逐一讀入字元來取得字串內容
14.5字串與函式呼叫
14.6字串處理函式
14.7字串陣列
14.8命令列引數
國立屏東大學資訊工程學系程式設計(二)
14.字串
14.1字串常值(StringLiterals)
所謂的字串(string)是指一些字元的集合,例如“Hello”這個用雙引號框起來的字元集合就是一個字串。
在C語言中,這種用雙引號框起來的字串又稱為字串常值(stringliterals),我們已經在printf()函式中時常使用到。
每個在程式中的字串常值,將會在編譯時自動配置到某個記憶體位址,這個記憶體位址為一塊連續的記憶體空間,包含多個字元儲存於其中,並以一個特殊的字元『\0』代表字串的結尾。
通常『\0』又被稱為是nullcharacter(空字元)。
請參考figure 1,其中顯示了一個包含有“Hello”字串的記憶體空間,並以\0做為字串的結束。
Fig.1:在記憶體中的字串常值
當然,你也可以簡單得以figure 2來思考這個在記憶體中的字串常值。
Fig.2:在記憶體中的字串常值
下面這個程式,以指標來檢視儲存在記憶體中的字串常值,請將它加以編譯並執行看看其結果為何。
#include
其中在printf()函式中,出現過三次“Hello”字串常值。
原則上,在程式碼中,每出現一次字串常值,編譯器就會自動為其配置一個適當的記憶體空間,可是若是完全相同的字串內容,編譯器也會有智慧地不再重覆地配置空間。
此外,在字串常值中的字元,除ASCII的可見字元外,亦可以有逸出序列字元(escapesequences),包含:『\n』為換行、『\t』為tab、『\b』為倒退等,詳細請參考table 1。
EscapeSequence意義
\aAlert(bell)
\bBackspace
\fformfeed
\nnewline
\rcarriagereturn
\tHorizontaltab
\vVerticaltab
\\
backslash
\??
\''
\“”
Tab.1:EscapeSequence
請參考以下的程式:
#include
#include
在本節的最後,我們提供一個有趣的函式,輸入撲克牌的點數,它會傳回一個字元來表示該點數:
charpointChar(intp)
{
return"A23456789TJQK"[p-1];
}
14.2字串變數
其實,關於這點你應該已經在前一個小節的說明中發現了,在C語言中,我們有兩種方式來宣告並處理字串變數:其一為陣列,其二為指標。
若我們要宣告一個可儲存或操作含有10個字元的字串變數str,那麼我們會使用下面的宣告:
charstr[11];
這是因為考慮到字串必須以『\0』結尾。
通常,我們會利用下面的方法來宣告一個字串:
#defineSTR_LEN80
charstr[STR_LEN+1];
我們可以在宣告字串變數的同時,給定其初始值,例如:
charstr[6]="Hello";
就如同figure 2一樣,C語言的編譯器會自動在其後增加一個『\0』做為結束的標記。
上述的宣告等同於下列的程式碼:
charstr[6]={'H','e','l','l','o','\0'};
但是,如果我們的陣列宣告過大,所給的初始值不夠時又會如何呢?C語言的編譯器會在其不足處皆補上『\0』,因此,以下兩行程式碼是等價的:
charstr[7]="Hello";
charstr[7]={'H','e','l','l','o','\0','\0'};
如果你還記得我們曾說過,當陣列的初始值過少時,C語言的編譯器會幫我們補0,那麼你就會瞭解為何字串變數的宣告初始值不足時會被補『\0』了(因為『\0』的整數值為0)。
如果情況反過來,初始值超過陣列的大小那又會如何?在這種情況下,C無法幫我們在字串結束處補上『\0』,因此有可能在未來的操作上出現問題,請參考下面的程式:
#include
有些版本的C語言編譯器會幫我們處理好這個問題,但有的不會,最好的解決方法是不要犯這種錯誤,或是改用以下的宣告方法,讓C語言的編譯器自動幫我們處理好陣列的大小問題:
charstr[]="Hello";
我們也可以用指標的方式,來進行字串變數的宣告,例如:
char*str="Hello";
會產生一個字串變數p,但它是以指標的方式來處理。
請參考下面的程式:
#include
由於字串常值是不可更改內容的,因此未來strP='w';的操作會在執行時發生錯誤。
14.3字串的輸出
在C語言裡,你可以使用printf()與puts()來進行字串的輸出。
其中printf()函式必須搭配%s的formatspecifier來輸出字串,並可使用%x.ys來進一步指定輸出的格式,請參考以下的程式:
#include
puts(str);
14.4字串的輸入
14.4.1scanf()函式
當我們宣告了字串變數後,除了用給定初始值的方式產生字串的內容外,也可以用scanf()函式取得字串的內容。
scanf()用以讀取字串的formatspecifier是%s,下面的程式碼顯示了用scanf()取得使用者的姓名,並將之輸出:
#defineLEN10
charname[LEN+1];
printf("Pleaseinputyourname:");
scanf("%s",name);
printf("Yournameis%s.\n",name);
在scanf()函式的格式字串中,'['是一個特殊的formatspecifier,用以指定一個字元集合,稱為scanset,所輸入的字串其必須由scanset內的字元所組成。
例如我們可以定義一個scanset為[abc],那麼只有由a,b,c這三個字元所組成的字串才能被接受。
請參考下面的程式碼:
scanf("%[atc]",str);//取回由a,t,c所組成的字串
scanf("%3[atc]",str);//取回由a,t,c所組成的字串,並限制字串長度不超過3
您也可以指定不由特定字元集所組成的字串,只要在scanset的開頭加上'^',即可,例如:
scanf("%[^atc]",str);//取回不包含a,t,c的字串
如果想限制為從a到z的字母,是否只能寫成%[abcdefghijklmnopqrstuvwxyz]?其實我們可以使用連字號'-'來解決,例如%[a-z]、%[a-zA-Z]、%[^a-z]、%[0-3]、%[a-e]、%[^0-9]等。
因此,這個程式的執行可能會有以下的結果:
[04:34user@wshome]./a.out
Pleaseinputyourname:JunWu
YournameisJun.
注意到了嗎?name字串的內容,其實是{'J','u','n','\0'}。
為了解決此問題,可以改用gets()函式,它可以持續讀取使用者的輸入直到遇到換行為止,例如:
#defineLEN10
charname[LEN+1];
printf("Pleaseinputyourname:");
gets(name);
printf("Yournameis%s.\n",name);
其執行結果為:
[04:34user@wshome]./a.out
Pleaseinputyourname:JunWu
YournameisJunWu
.
這裡又產了兩個新的問題:
在輸入字串內容前的空白也視為字串內容,以及
最後的換行(enter)也會被放在字串內。
另外,還有一個更嚴重的問題,因為gets()函式,會持續讀取直到遇到換行為止,因此,若使用者輸入內容過多,會造成系統用以讀取標準輸入的緩衝區(buffer)溢出(overflow)的問題,在執行時這會造成許多問題。
因此,新版的C語言(C11)已經將gets()函式取消,或是你會在編譯時看到『warning:the`gets'functionisdangerousandshouldnotbeused.』的警告。
要解決這個問題,可以改用fgets()函式,其原型為:
char*fgets(char*str,intn,FILE*file);
此函式是設計用以從檔案file中,讀取不超過n個字元的字串,存放到str中。
我們可以將第三個引數改成stdin(標準輸入管道),就可以將其用在取得使用者來自標準輸入的字串了,請參考下面的程式:
#include
在此,我們先介紹另一種簡單但有效的方法,就是使用scanset來解決:
charstr[LEN+1];
scanf("%[^\n]",str);
14.4.3逐一讀入字元來取得字串內容
當然,你也可以配合迴圈,將字串以字元的方式逐一的輸入,請參考下面的程式:
#include
更明確來說,這個引數所傳入的是一個字串所在的記憶體位址,在main()函式中呼叫時,我們以countSpace(str)將str這個字串的位址傳入即可。
其中的const保證了所傳入的值不可被更改。
我們也可以使用指標的方式,來設計相同的程式,請參考下例:
#include
我們在本節列舉部份常用的字串處理函式:
char*strcpy(char*s1,constchar*s2);
將字串s2的內容複製到字串s1中,且複製完成的新字串也會傳回。
#include
size_tstrlen(constchar*s);傳回字串s的長度(不包含nullcharacter)。
char*strcat(char*s1,constchar*s2);將字串s2的內容串接於s1之後。
intstrcmp(constchar*s1,constchar*s2);比較字串s1與s2的內容,傳回值取決於s1與s2的內容:
傳回0,若s1與s2相同
傳回>0的值,若s1>s2
傳回<0的值,若s1
例如“abc”小於“abd”,或“abc”小於“bcd”。
s1的內容與s2相同,但s1的長度小於s2,例如“abc”小於“abcd”。
至於每個字元的比較基準則是以ACSII編碼為依據:
數字小於字母
大寫字母小於小寫字母
空白小於字母與數字
關於更多的字串處理函式,可以參考其它相關書籍或網站,例如張凱慶先生的程式語言教學誌
另外,還有一些函式可用以將字串轉換為其它型態的數值,例如「atoi()函式」可以將字串轉成整數,
#include
14.7字串陣列
我們也可以設計一個陣列來存放多個字串,例如:
#include
我們也可以用指標的陣列來存放這些字串:
#include
main()雖然是所謂的程式進入點,但它也是一個函式,也可以有引數。
不過由於main()函式是由我們在作業系統的命令列透過執行程式而啟動,因此其引數就稱為命令列引數。
例如,我們在linux系統中,可以執行下列的指令:
ls
ls-l
ls*.c-l
在上述例子中,「ls」為我們欲執行的指令(也就是一個可執行的程式),「-1」、「*.c」等就是命令列引數。
我們自己所撰寫的程式,也可以讓main()函式接收這些引數,並進行後續的程式處理。
若要使用命令列引數,main()函式的原型如下:
intmain(intargc,char*argv[])
其中argc為引數的個數,argv為引數的指標陣列。
請試著寫出一個程式,將其所接收的命令列引數輸出。
c/string.txt·上一次變更:2019/07/0215:01(外部編輯)
頁面工具
輸出PDF檔案回到頁頂
延伸文章資訊
- 1C 速查手冊- 11.3 字串處理string.h - 程式語言教學誌
本篇文章介紹C 標準程式庫的string.h 。
- 214.1 字串常值(String Literals) - JunWu - 屏東大學
所謂的字串(string)是指一些字元的集合,例如“Hello”這個用雙引號框起來的字元集合就是一個字串。在C語言中,這種用雙引號框起來的字串又稱為字串常值(string ...
- 3C 語言筆記— 字串(Strings). 字串其實就是字元的集合
<string.h> 應用; 字串轉換成數字. 1. 字串的宣告. 字串在C ...
- 4字元陣列與字串 - OpenHome.cc
C 是個歷史悠久的語言,早期用 char 儲存的文字僅需單一位元組,例如ASCII 的文字,使用 char 代表字元是沒問題,因為ASCII 既定義了字元集,也定義了字元編碼,在表示 ...
- 5C (string) ( ) C
C (string) ... 根據C語言中陣列的宣告與使用得知,宣告為int aa[10]的陣列就表示可以存放10個元素的 ... C語言中提供的字串複製的函式strcpy()(定. 義於str...