#include<stdio.h>
定義函數(shù) int sscanf (const char *str,const char * format,........);
sscanf()會(huì)將參數(shù)str的字符串根據(jù)參數(shù)format字符串來(lái)轉(zhuǎn)換并格式化數(shù)據(jù)。格式轉(zhuǎn)換形式請(qǐng)參考scanf()。轉(zhuǎn)換后的結(jié)果存于對(duì)應(yīng)的參數(shù)內(nèi)。
scanf以及sscanf實(shí)際上是支持部分正則表達(dá)式的,sscanf提供的這個(gè)擴(kuò)展功能其實(shí)并不能真正稱(chēng)為正則表達(dá)式,因?yàn)樗臅?shū)寫(xiě)還是離不開(kāi)%,而且也很局限。sscanf的這個(gè)擴(kuò)展功能支持[]表示支付范圍,{}表示重復(fù)次數(shù),^表示取非,*表示跳過(guò)。
說(shuō)明:  sscanf與scanf類(lèi)似,都是用于輸入的,只是后者以屏幕(stdin)為輸入源,前者以固定字符串為輸入源。  其中的format可以是一個(gè)或多個(gè) {%[*] [width] [{h | l | I64 | L}]type | ' ' | '/t' | '/n' | 非%符號(hào)}  注:  1、 * 亦可用于格式中, (即 %*d 和 %*s) 加了星號(hào) (*) 表示跳過(guò)此數(shù)據(jù)不讀入. (也就是不把此數(shù)據(jù)讀入?yún)?shù)中)  2、{a|b|c}表示a,b,c中選一,[d],表示可以有d也可以沒(méi)有d。  3、width表示讀取寬度。  4、{h | l | I64 | L}:參數(shù)的size,通常h表示單字節(jié)size,I表示2字節(jié) size,L表示4字節(jié)size(double例外),l64表示8字節(jié)size。  5、type :這就很多了,就是%s,%d之類(lèi)。  6、特別的:%*[width] [{h | l | I64 | L}]type 表示滿(mǎn)足該條件的被過(guò)濾掉,不會(huì)向目標(biāo)參數(shù)中寫(xiě)入值  支持集合操作:  %[a-z] 表示匹配a到z中任意字符,貪婪性(盡可能多的匹配)  %[aB'] 匹配a、B、'中一員,貪婪性  %[^a] 匹配非a的任意字符,貪婪性舉例:char url[] = "dv://192.168.1.253:65001/1/1"sscanf(url,"%[^://]%*c%*c%*c%[^:]%*c%d%*c%d%*c%d",PRotocol,ip,port,chn,type);解釋一下
先取得一個(gè)最長(zhǎng)的字符串,但不包括字串://,于是protocol="dv/0";
然后跳過(guò)三個(gè)字符(%*c),其實(shí)就是跳過(guò)://
接著取一個(gè)字符串不包括字符串:,于是ip=192.168.1.253,這里簡(jiǎn)化處理了,IP就當(dāng)個(gè)字符串來(lái)弄,而且不做檢查
然后跳過(guò)冒號(hào)取端口到port,再跳過(guò)/取通道號(hào)到chn,再跳過(guò)/取碼流類(lèi)型到type。
      是不是覺(jué)得還不過(guò)癮?我也覺(jué)得,接著舉例。
sscanf("Phil/nChang","%[^/n]%*c%s",first_name,last_name);
解釋?zhuān)禾^(guò)一個(gè)換行符,取first_name和last_name
實(shí)驗(yàn)1:
sscanf( "123456" , "%s" , str) ; ---------str的值為 "123456/0!!!"
這個(gè)實(shí)驗(yàn)很簡(jiǎn)單,把源字符串"123456"拷貝到str的前6個(gè)字符,并且把str的第7個(gè)字符設(shè)為null字符,也就是/0
實(shí)驗(yàn)2:
sscanf( "123456" , "%3s" , str) ; ---------str的值為 "123/0!!!!!!"
看到?jīng)]有,正則表達(dá)式的百分號(hào)后面多了一個(gè)3,這告訴sscanf只拷貝3個(gè)字符給str,然后把第4個(gè)字符設(shè)為null字符。
實(shí)驗(yàn)3:
sscanf( "aaaAAA" , "%[a-z]" , str) ; ---------str的值為 "aaa/0!!!!!!"
從這個(gè)實(shí)驗(yàn)開(kāi)始我們會(huì)使用正則表達(dá)式,括號(hào)里面的a-z就是一個(gè)正則表達(dá)式,它可以表示從a到z的任意字符,
在 繼續(xù)討論之前,我們先來(lái)看看百分號(hào)表示什么意思,%表示選擇 ,%后面的是條件,比如實(shí)驗(yàn)1的"%s",s是一個(gè)條件,表示任意字符,"%s"的意思是:只 要輸入的東西是一個(gè)字符,就把它拷貝給str。實(shí)驗(yàn)2的"%3s"又多了一個(gè)條件:只拷貝3個(gè)字符。實(shí)驗(yàn)3的“%[a-z]”的條件稍微嚴(yán)格一些,輸入的 東西不但是字符,還得是一個(gè)小寫(xiě)字母的字符,所以實(shí)驗(yàn)3只拷貝了小寫(xiě)字母"aaa"給str,別忘了加上null字符。
實(shí)驗(yàn)4:
sscanf( "AAAaaaBBB" , "%[^a-z]" , str) ; ---------str的值為 "AAA/0!!!!!!"
對(duì) 于所有字符,只要不是小寫(xiě)字母,都滿(mǎn)足"^a-z"正則表達(dá)式,符號(hào)^表示邏輯非。前3個(gè)字符都不是小寫(xiě)字符,所以將其拷貝給str,但最后3個(gè)字符也不 是小寫(xiě)字母,為什么不拷貝給str呢?這是因?yàn)楫?dāng)碰到不滿(mǎn)足條件的字符后,sscanf就會(huì)停止執(zhí)行,不再掃描之后的字符。
實(shí)驗(yàn)5:
sscanf( "AAAaaaBBB" , "%[A-Z]%[a-z]" , str) ; ---------段錯(cuò)誤
這 個(gè)實(shí)驗(yàn)的本意是:先把大寫(xiě)字母拷貝給str,然后把小寫(xiě)字母拷貝給str,但很不幸,程序運(yùn)行的時(shí)候會(huì)發(fā)生段錯(cuò)誤,因?yàn)楫?dāng)sscanf掃描到字符a時(shí),違 反了條件"%[A-Z]",sscanf就停止執(zhí)行,不再掃描之后的字符,所以第二個(gè)條件也就沒(méi)有任何意義,這個(gè)實(shí)驗(yàn)說(shuō)明:不能使用%號(hào)兩次或兩次以上
實(shí)驗(yàn)6:
sscanf( "AAAaaaBBB" , "%*[A-Z]%[a-z]" , str) ; ---------str的值為 "aaa/0!!!!!!"
這 個(gè)實(shí)驗(yàn)出現(xiàn)了一個(gè)新的符號(hào):%*,與%相反,%*表示過(guò)濾 滿(mǎn)足條件的字符,在這個(gè)實(shí)驗(yàn)中,%*[A-Z]過(guò)濾了所有大寫(xiě)字母,然后再使用%[a-z]把之 后的小寫(xiě)字母拷貝給str。如果只有%*,沒(méi)有%的話(huà),sscanf不會(huì)拷貝任何字符到str,這時(shí)sscanf的作用僅僅是過(guò)濾字符串。
實(shí)驗(yàn)7:
sscanf( "AAAaaaBBB" , "%[a-z]" , str) ; ---------str的值為 "!!!!!!!!!!"
做完前面幾個(gè)實(shí)驗(yàn)后,我們都知道sscanf拷貝完成后,還會(huì)在str的后面加上一個(gè)null字符,但如果沒(méi)有一個(gè)字符滿(mǎn)足條件,sscanf不會(huì)在str的后面加null字符,str的值依然是10個(gè)驚嘆號(hào)。這個(gè)實(shí)驗(yàn)也說(shuō)明了,如果不使用%*過(guò)濾掉前面不需要的字符,你永遠(yuǎn)別想取得中間的字符。 
實(shí)驗(yàn)8:
sscanf( "AAAaaaBC=" , "%*[A-Z]%*[a-z]%[^a-z=]" , str) ; ---------str的值為 "BC/0!!!!!!!"
這是一個(gè)綜合實(shí)驗(yàn),但這個(gè)實(shí)驗(yàn)的目的不是幫我們復(fù)習(xí)前面所學(xué)的知識(shí),而是展示兩個(gè)值得注意的地方:
注意1:%只能使用一次,但%*可以使用多次,比如在這個(gè)實(shí)驗(yàn)里面,先用%*[A-Z]過(guò)濾大寫(xiě)字母,然后用%*[a-z]過(guò)濾小寫(xiě)字母。
注意2:^后面可以帶多個(gè)條件,且這些條件都受^的作用,比如^a-z=表示^a-z且^=(既不是小寫(xiě)字母,也不是等于號(hào))。
實(shí)驗(yàn)9:
int k;
sscanf( "AAA123BBB456" , "%*[^0-9]%i" , &k) ; ---------k的值為123
首先,%*[^0-9]過(guò)濾前面非數(shù)字的字符,然后用%i把數(shù)字字符轉(zhuǎn)換成int型的整數(shù),拷貝到變量k,注意參數(shù)必須使用k的地址。
例子:   1. 常見(jiàn)用法。   char buf[512] = ;   sscanf("123456 ", "%s", buf);   printf("%s/n", buf);   結(jié)果為:123456   2. 取指定長(zhǎng)度的字符串。如在下例中,取最大長(zhǎng)度為4字節(jié)的字符串。   sscanf("123456 ", "%4s", buf);   printf("%s/n", buf);   結(jié)果為:1234   3. 取到指定字符為止的字符串。如在下例中,取遇到空格為止字符串。   sscanf("123456 abcdedf", "%[^ ]", buf);   printf("%s/n", buf);   結(jié)果為:123456   4. 取僅包含指定字符集的字符串。如在下例中,取僅包含1到9和小寫(xiě)字母的字符串。   sscanf("123456abcdedfBCDEF", "%[1-9a-z]", buf);   printf("%s/n", buf);   結(jié)果為:123456abcdedf   5. 取到指定字符集為止的字符串。如在下例中,取遇到大寫(xiě)字母為止的字符串。   sscanf("123456abcdedfBCDEF", "%[^A-Z]", buf);   printf("%s/n", buf);   結(jié)果為:123456abcdedf   6、給定一個(gè)字符串iios/12DDWDFF@122,獲取 / 和 @ 之間的字符串,先將 "iios/"過(guò)濾掉,再將非'@'的一串內(nèi)容送到buf中   sscanf("iios/12DDWDFF@122", "%*[^/]/%[^@]", buf);   printf("%s/n", buf);   結(jié)果為:12DDWDFF   7、給定一個(gè)字符串““hello, world”,僅保留world。(注意:“,”之后有一空格)   sscanf(“hello, world”, "%*s%s", buf);   printf("%s/n", buf);   結(jié)果為:world   %*s表示第一個(gè)匹配到的%s被過(guò)濾掉,即hello被過(guò)濾了   如果沒(méi)有空格則結(jié)果為NULL。   sscanf的功能很類(lèi)似于正則表達(dá)式, 但卻沒(méi)有正則表達(dá)式強(qiáng)大,所以如果對(duì)于比較復(fù)雜的字符串處理,建議使用正則表達(dá)式.   //-------------------------------------------------------   sscanf,表示從字符串中格式化輸入   上面表示從str中,輸入數(shù)字給x,就是32700   久以前,我以為c沒(méi)有自己的split string函數(shù),后來(lái)我發(fā)現(xiàn)了sscanf;一直以來(lái),我以為sscanf只能以空格來(lái)界定字符串,現(xiàn)在我發(fā)現(xiàn)我錯(cuò)了。   sscanf是一個(gè)運(yùn)行時(shí)函數(shù),原形很簡(jiǎn)單:   int sscanf(   const char *buffer,   const char *format [,   argument ] ...   );   它強(qiáng)大的功能體現(xiàn)在對(duì)format的支持上。   我以前用它來(lái)分隔類(lèi)似這樣的字符串2006:03:18:   int a, b, c;   sscanf("2006:03:18", "%d:%d:%d", a, b, c);   以及2006:03:18 - 2006:04:18:   char sztime1[16] = "", sztime2[16] = "";   sscanf("2006:03:18 - 2006:04:18", "%s - %s", sztime1, sztime2);   但是后來(lái),我需要處理2006:03:18-2006:04:18   僅僅是取消了‘-’兩邊的空格,卻打破了%s對(duì)字符串的界定。   我需要重新設(shè)計(jì)一個(gè)函數(shù)來(lái)處理這樣的情況?這并不復(fù)雜,但是,為了使所有的代碼都有統(tǒng)一的風(fēng)格,我需要改動(dòng)很多地方,把已有的sscanf替換成我自己的分割函數(shù)。我以為我肯定需要這樣做,并伴隨著對(duì)sscanf的強(qiáng)烈不滿(mǎn)而入睡;一覺(jué)醒來(lái),發(fā)現(xiàn)其實(shí)不必。   format-type中有%[]這樣的type field。如果讀取的字符串,不是以空格來(lái)分隔的話(huà),就可以使用%[]。   %[]類(lèi)似于一個(gè)正則表達(dá)式。[a-z]表示讀取a-z的所有字符,[^a-z]表示讀取除a-z以外的所有字符。   所以那個(gè)問(wèn)題也就迎刃而解了:   sscanf("2006:03:18 - 2006:04:18", "%[0-9,:] - %[0-9,:]", sztime1, sztime2); 
新聞熱點(diǎn)
疑難解答
圖片精選
網(wǎng)友關(guān)注