sscanf函式和正規表示式

2021-08-03 21:47:34 字數 2731 閱讀 2203

此文所有的實驗都是基於下面的程式: 

char str[10]; 

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

執行完後str的值為 

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

我們把str的每個字元都初始化為驚嘆號,當str的值發生變化時,使用printf列印str的值,對比先前的驚嘆號,這樣就可以方便的觀察str發生了怎樣的變化。下面我們做幾個小實驗,看看使用sscanf和正規表示式格式化輸入後,str有什麼變化。 

實驗1: 

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

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

實驗2: 

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

看到沒有,正規表示式的百分號後面多了乙個3,這告訴sscanf只拷貝3個字元給str,然後把第4個字元設為null字元。 

實驗3: 

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

從這個實驗開始我們會使用正規表示式,括號裡面的a-z就是乙個正規表示式,它可以表示從a到z的任意字元, 

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

實驗4: 

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

對於所有字元,只要不是小寫字母,都滿足"^a-z"正規表示式,符號^表示邏輯非。前3個字元都不是小寫字元,所以將其拷貝給str,但最後3個字元也不是小寫字母,為什麼不拷貝給str呢?這是因為當碰到不滿足條件的字元後,sscanf就會停止執行,不再掃瞄之後的字元。 

實驗5: 

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

這個實驗的本意是:先把大寫字母拷貝給str,然後把小寫字母拷貝給str,但很不幸,程式執行的時候會發生段錯誤,因為當sscanf掃瞄到字元a時,違反了條件"%[a-z]",sscanf就停止執行,不再掃瞄之後的字元,所以第二個條件也就沒有任何意義,這個實驗說明:不能使用%號兩次或兩次以上 

實驗6: 

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

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

實驗7: 

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

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

實驗8: 

sscanf("aaaaaabc=","%*[a-z]%*[a-z]%[^a-z=]",str); ---------str的值為 "bc\0!!!!!!!" 

這是乙個綜合實驗,但這個實驗的目的不是幫我們複習前面所學的知識,而是展示兩個值得注意的地方: 

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

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

實驗9: 

int k; 

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

首先,%*[^0-9]過濾前面非數字的字元,然後用%i把數字字元轉換成int型的整數,拷貝到變數k,注意引數必須使用k的位址。 

仍段**下來: 

#if 0

1,sscanf():從乙個字串中讀進與指定格式相符的資料.

2,sscanf與scanf類似,都是用於輸入的,只是後者以螢幕(stdin)為輸入源,前者以固定字串為輸入源。

3,關於正規表示式:

(1)%[..],當字元屬於方括號裡表示式表示的字符集時繼續讀取,否則停止.方括號裡的和正規表示式差不多,^是"排除..."的意思

(2)%*[..],直接跳過方括號裡的字符集並繼續讀取

#endif

#include using namespace std;

int main()

{ char str[10];

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

cout<

sscanf函式和正規表示式

此文所有的實驗都是基於下面的程式 char str 10 for int i 0 i 10 i str i 執行完後str的值為 str 我們把str的每個字元都初始化為驚嘆號,當str的值發生變化時,使用printf列印str的值,對比先前的驚嘆號,這樣就可以方便的觀察str發生了怎樣的變化。下面...

sscanf函式和正規表示式

此文所有的實驗都是基於下面的程式 char str 10 for int i 0 i 10 i str i 執行完後str的值為 str 我們把str的每個字元都初始化為驚嘆號,當str的值發生變化時,使用printf列印str的值,對比先前的驚嘆號,這樣就可以方便的觀察str發生了怎樣的變化。下面...

sscanf函式和正規表示式

此文所有的實驗都是基於下面的程式 char str 10 for int i 0 i 10 i str i 執行完後str的值為 str 我們把str的每個字元都初始化為驚嘆號,當str的值發生變化時,使用printf列印str的值,對比先前的驚嘆號,這樣就可以方便的觀察str發生了怎樣的變化。下面...