日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

sscanf函数和正则表达式

發(fā)布時間:2023/12/9 编程问答 38 豆豆
生活随笔 收集整理的這篇文章主要介紹了 sscanf函数和正则表达式 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

From: http://hi.baidu.com/cr0_3/blog/item/c98f6ad0d54d9a0d3af3cfa2.html


看了幾篇介紹sscanf函數(shù),真是發(fā)現(xiàn)自己好多東西沒理解透。

第一篇:

此文所有的實驗都是基于下面的程序:

char str[10];

for (int i = 0; i < 10; i++) str[i] = '!';

執(zhí)行完后str的值為

str = "!!!!!!!!!!"

我們把str的每個字符都初始化為驚嘆號,當(dāng)str的值發(fā)生變化時,使用printf打印str的值,對比先前的驚嘆號,這樣就可以方便的觀察str發(fā)生了怎樣的變化。下面我們做幾個小實驗,看看使用sscanf和正則表達(dá)式格式化輸入后,str有什么變化。

實驗1:

sscanf( "123456" , "%s" , str) ; ---------str的值為 "123456\0!!!"

這個實驗很簡單,把源字符串"123456"拷貝到str的前6個字符,并且把str的第7個字符設(shè)為null字符,也就是\0

實驗2:

sscanf( "123456" , "%3s" , str) ; ---------str的值為 "123\0!!!!!!"

看到?jīng)]有,正則表達(dá)式的百分號后面多了一個3,這告訴sscanf只拷貝3個字符給str,然后把第4個字符設(shè)為null字符。

實驗3:

sscanf( "aaaAAA" , "%[a-z]" , str) ; ---------str的值為 "aaa\0!!!!!!"

從這個實驗開始我們會使用正則表達(dá)式,括號里面的a-z就是一個正則表達(dá)式,它可以表示從a到z的任意字符,

在繼續(xù)討論之前,我們先來看看百分號表示什么意思,%表示選擇 ,%后面的是條件,比如實驗1的"%s",s是一個條件,表示任意字符,"%s"的意思是:只要輸入的東西是一個字符,就把它拷貝給str。實驗2的"%3s"又多了一個條件:只拷貝3個字符。實驗3的“%[a-z]”的條件稍微嚴(yán)格一些,輸入的東西不但是字符,還得是一個小寫字母的字符,所以實驗3只拷貝了小寫字母"aaa"給str,別忘了加上null字符。

實驗4:

sscanf( "AAAaaaBBB" , "%[^a-z]" , str) ; ---------str的值為 "AAA\0!!!!!!"

對于所有字符,只要不是小寫字母,都滿足"^a-z"正則表達(dá)式,符號^表示邏輯非。前3個字符都不是小寫字符,所以將其拷貝給str,但最后3個字符也不是小寫字母,為什么不拷貝給str呢?這是因為當(dāng)碰到不滿足條件的字符后,sscanf就會停止執(zhí)行,不再掃描之后的字符。

實驗5:


sscanf( "AAAaaaBBB" , "%[A-Z]%[a-z]" , str) ; ---------段錯誤

這個實驗的本意是:先把大寫字母拷貝給str,然后把小寫字母拷貝給str,但很不幸,程序運(yùn)行的時候會發(fā)生段錯誤,因為當(dāng)sscanf掃描到字符a時,違反了條件"%[A-Z]",sscanf就停止執(zhí)行,不再掃描之后的字符,所以第二個條件也就沒有任何意義,這個實驗說明:不能使用%號兩次或兩次以上

實驗6:


sscanf( "AAAaaaBBB" , "%*[A-Z]%[a-z]" , str) ; ---------str的值為 "aaa\0!!!!!!"

這個實驗出現(xiàn)了一個新的符號:%*,與%相反,%*表示過濾 滿足條件的字符,在這個實驗中,%*[A-Z]過濾了所有大寫字母,然后再使用%[a-z]把之后的小寫字母拷貝給str。如果只有%*,沒有%的話,sscanf不會拷貝任何字符到str,這時sscanf的作用僅僅是過濾字符串。

實驗7:

sscanf( "AAAaaaBBB" , "%[a-z]" , str) ; ---------str的值為 "!!!!!!!!!!"

做完前面幾個實驗后,我們都知道sscanf拷貝完成后,還會在str的后面加上一個null字符,但如果沒有一個字符滿足條件,sscanf不會在str的后面加null字符,str的值依然是10個驚嘆號。這個實驗也說明了,如果不使用%*過濾掉前面不需要的字符,你永遠(yuǎn)別想取得中間的字符。


實驗8:

sscanf( "AAAaaaBC=" , "%*[A-Z]%*[a-z]%[^a-z=]" , str) ; ---------str的值為 "BC\0!!!!!!!"

這是一個綜合實驗,但這個實驗的目的不是幫我們復(fù)習(xí)前面所學(xué)的知識,而是展示兩個值得注意的地方:

注意1:%只能使用一次,但%*可以使用多次,比如在這個實驗里面,先用%*[A-Z]過濾大寫字母,然后用%*[a-z]過濾小寫字母。

注意2:^后面可以帶多個條件,且這些條件都受^的作用,比如^a-z=表示^a-z且^=(既不是小寫字母,也不是等于號)。

實驗9:

int k;


sscanf( "AAA123BBB456" , "%*[^0-9]%i" , &k) ; ---------k的值為123

首先,%*[^0-9]過濾前面非數(shù)字的字符,然后用%i把數(shù)字字符轉(zhuǎn)換成int型的整數(shù),拷貝到變量k,注意參數(shù)必須使用k的地址。


本文來自CSDN博客,轉(zhuǎn)載請標(biāo)明出處:http://blog.csdn.net/kenby/archive/2009/04/05/4051018.aspx

第二篇:

今天翻google reader的時候看到這樣一篇文章,介紹的是sscanf的高級用法。直到今天我才知道sscanf是可以直接用正則表達(dá)式的,慚愧。

在msdn中sscanf的聲明如下

int sscanf( const char *buffer, const char *format [, argument ] ... );

雙字節(jié)版本的是這樣的

int swscanf( const wchar_t *buffer, const wchar_t *format [, argument ] ... );

第一個參數(shù)是源字符串,這沒什么好講。第三個及以后的參數(shù)是可變參數(shù)列表,用于接收解析出來之后的值,可變參數(shù)列表不是本文的重點(diǎn),暫且不提。最有玄機(jī)的是第二個參數(shù),也就是所謂的format。我們知道prinft,sprintf,scanf,sscanf這四個函數(shù)(以及相應(yīng)的雙字節(jié)版本)都接收一個名為format的字符串作為參數(shù),以便對輸入輸出做格式化,比如

sscanf(“12”, "%d", &in)

可以把字符串"12"(念做一二)格式化成10進(jìn)制數(shù)12(念做十二),并賦值給in,而

sscanf(“12”, "%s", str)

可以把字符串"12"格式化成字符串12,并拷貝到str指向的內(nèi)存區(qū)域。如此種種。如果你仔細(xì)看過c語言手冊,那么你一定對次非常熟悉,并喜歡在中間夾雜點(diǎn)啊三啊啥的組成諸如%.4ld之類的format贏取初學(xué)者(或者老板)的贊揚(yáng)。但是你可真不一定了解,format里是可以直接用正則表達(dá)式的,比如

sscanf("123334abcd123", "%[0-9]*", str);

執(zhí)行完后str的內(nèi)容是字符串"123334"。[0-9]*是一個非常簡單的正則表達(dá)式,意思是匹配數(shù)字任意次。關(guān)于正則表達(dá)式的更多內(nèi)容請參看這個。

我們在寫程序時經(jīng)常會碰到需要解析字符串的情況,而正則表達(dá)式則是解決此類問題的利器。如果我們能善用c標(biāo)準(zhǔn)庫函數(shù)就能使用的正則表達(dá)式,一定可以做到事半而功倍。

------------

附正則表達(dá)式完整列表

字元

描述

\

將下一個字元標(biāo)記為一個特殊字元、或一個原義字元、或一個向後引用、或一個八進(jìn)位轉(zhuǎn)義符。例如,「n」匹配字元「n」。「\n」匹配一個換行符。序列「\\」匹配「\」而「\(」則匹配「(」。

^

匹配輸入字元串的開始位置。如果設(shè)置了RegExp對象的Multiline屬性,^也匹配「\n」或「\r」之後的位置。

$

匹配輸入字元串的結(jié)束位置。如果設(shè)置了RegExp對象的Multiline屬性,$也匹配「\n」或「\r」之前的位置。

*

匹配前面的子表達(dá)式零次或多次。例如,zo*能匹配「z」以及「zoo」。*等價于{0,}。

+

匹配前面的子表達(dá)式一次或多次。例如,「zo+」能匹配「zo」以及「zoo」,但不能匹配「z」。+等價于{1,}。

?

匹配前面的子表達(dá)式零次或一次。例如,「do(es)?」可以匹配「do」或「does」中的「do」。?等價于{0,1}。

{n}

n是一個非負(fù)整數(shù)。匹配確定的n次。例如,「o{2}」不能匹配「Bob」中的「o」,但是能匹配「food」中的兩個o。

{n,}

n是一個非負(fù)整數(shù)。至少匹配n次。例如,「o{2,}」不能匹配「Bob」中的「o」,但能匹配「foooood」中的所有o。「o{1,}」等價于「o+」。「o{0,}」則等價于「o*」。

{n,m}

m和n均為非負(fù)整數(shù),其中n<=m。最少匹配n次且最多匹配m次。例如,「o{1,3}」將匹配「fooooood」中的前三個o。「o{0,1}」等價于「o?」。請注意在逗號和兩個數(shù)之間不能有空格。

?

當(dāng)該字元緊跟在任何一個其他限制符(*,+,?,{n},{n,},{n,m})後面時,匹配模式是非貪婪的。非貪婪模式盡可能少的匹配所搜索的字元串,而默認(rèn)的貪婪模式則盡可能多的匹配所搜索的字元串。例如,對於字元串「oooo」,「o+?」將匹配單個「o」,而「o+」將匹配所有「o」。

.

匹配除「\n」之外的任何單個字元。要匹配包括「\n」在內(nèi)的任何字元,請使用像「[.\n]」的模式。

(pattern)

匹配pattern並獲取這一匹配。所獲取的匹配可以從產(chǎn)生的Matches集合得到,在VBScript中使用SubMatches集合,在JScript中則使用$0…$9屬性。要匹配圓括號字元,請使用「\(」或「\)」。

(?:pattern)

匹配pattern但不獲取匹配結(jié)果,也就是說這是一個非獲取匹配,不進(jìn)行存儲供以後使用。這在使用「或」字元(|)來組合一個模式的各個部分是很有用。例如,「industr(?:y|ies)就是一個比」industry|industries'更簡略的表達(dá)式。

(?=pattern)

正向預(yù)查,在任何匹配pattern的字元串開始處匹配查找字元串。這是一個非獲取匹配,也就是說,該匹配不需要獲取供以後使用。例如, 「Windows(?=95|98|NT|2000)」能匹配「Windows2000」中的「Windows」,但不能匹配「Windows3.1」中 的「Windows」。預(yù)查不消耗字元,也就是說,在一個匹配發(fā)生後,在最後一次匹配之後立即開始下一次匹配的搜索,而不是從包含預(yù)查的字元之後開始。

(?!pattern)

負(fù)向預(yù)查,在任何不匹配pattern的字元串開始處匹配查找字元串。這是一個非獲取匹配,也就是說,該匹配不需要獲取供以後使用。例如 「Windows(?!95|98|NT|2000)」能匹配「Windows3.1」中的「Windows」,但不能匹配「Windows2000」中 的「Windows」。預(yù)查不消耗字元,也就是說,在一個匹配發(fā)生後,在最後一次匹配之後立即開始下一次匹配的搜索,而不是從包含預(yù)查的字元之後開始

x|y

匹配x或y。例如,「z|food」能匹配「z」或「food」。「(z|f)ood」則匹配「zood」或「food」。

[xyz]

字符集合。匹配所包含的任意一個字元。例如,「[abc]」可以匹配「plain」中的「a」。

[^xyz]

負(fù)值字符集合。匹配未包含的任意字元。例如,「[^abc]」可以匹配「plain」中的「p」。

[a-z]

字元範(fàn)圍。匹配指定範(fàn)圍內(nèi)的任意字元。例如,「[a-z]」可以匹配「a」到「z」範(fàn)圍內(nèi)的任意小寫字母字元。

[^a-z]

負(fù)值字元範(fàn)圍。匹配任何不在指定範(fàn)圍內(nèi)的任意字元。例如,「[^a-z]」可以匹配任何不在「a」到「z」範(fàn)圍內(nèi)的任意字元。

\b

匹配一個單詞邊界,也就是指單詞和空格間的位置。例如,「er\b」可以匹配「never」中的「er」,但不能匹配「verb」中的「er」。

\B

匹配非單詞邊界。「er\B」能匹配「verb」中的「er」,但不能匹配「never」中的「er」。

\cx

匹配由x指明的控制字元。例如,\cM匹配一個Control-M或回車符。x的值必須為A-Z或a-z之一。否則,將c視為一個原義的「c」字元。

\d

匹配一個數(shù)字字元。等價于[0-9]。

\D

匹配一個非數(shù)字字元。等價于[^0-9]。

\f

匹配一個換頁符。等價于\x0c和\cL。

\n

匹配一個換行符。等價于\x0a和\cJ。

\r

匹配一個回車符。等價于\x0d和\cM。

\s

匹配任何空白字元,包括空格、製表符、換頁符等等。等價于[\f\n\r\t\v]。

\S

匹配任何非空白字元。等價于[^\f\n\r\t\v]。

\t

匹配一個製表符。等價于\x09和\cI。

\v

匹配一個垂直製表符。等價于\x0b和\cK。

\w

匹配包括下劃線的任何單詞字元。等價于「[A-Za-z0-9_]」。

\W

匹配任何非單詞字元。等價于「[^A-Za-z0-9_]」。

\xn

匹配n,其中n為十六進(jìn)位轉(zhuǎn)義值。十六進(jìn)位轉(zhuǎn)義值必須為確定的兩個數(shù)字長。例如,「\x41」匹配「A」。「\x041」則等價于「\x04」&「1」。正則表達(dá)式中可以使用ASCII編碼。.

\num

匹配num,其中num是一個正整數(shù)。對所獲取的匹配的引用。例如,「(.)\1」匹配兩個連續(xù)的相同字元。

\n

標(biāo)識一個八進(jìn)位轉(zhuǎn)義值或一個向後引用。如果\n之前至少n個獲取的子表達(dá)式,則n為向後引用。否則,如果n為八進(jìn)位數(shù)字(0-7),則n為一個八進(jìn)位轉(zhuǎn)義值。

\nm

標(biāo)識一個八進(jìn)位轉(zhuǎn)義值或一個向後引用。如果\nm之前至少有nm個獲得子表達(dá)式,則nm為向後引用。如果\nm之前至少有n個獲取,則n為一個後跟文字m的向後引用。如果前面的條件都不滿足,若n和m均為八進(jìn)位數(shù)字(0-7),則\nm將匹配八進(jìn)位轉(zhuǎn)義值nm。

\nml

如果n為八進(jìn)位數(shù)字(0-3),且m和l均為八進(jìn)位數(shù)字(0-7),則匹配八進(jìn)位轉(zhuǎn)義值nml。

\un

匹配n,其中n是一個用四個十六進(jìn)位數(shù)字表示的Unicode字元。例如,\u00A9匹配版權(quán)符號(?)。

http://www.cnblogs.com/gussing/archive/2009/02/02/1382342.html


創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎勵來咯,堅持創(chuàng)作打卡瓜分現(xiàn)金大獎

總結(jié)

以上是生活随笔為你收集整理的sscanf函数和正则表达式的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。