sscanf()格式化字符串用法

1. 概述

sscanf()爲C語言標準庫函數,用於從指定字符串中讀入與指定格式相符的數據。函數原型聲明在stdio.h頭文件中:int sscanf(const char *str, const char *format, ...);

該函數根據參數format(格式化字符串)來轉換參數str指向的字符串,轉換後的結果存於對應的可變參數內。其返回值爲按照指定格式轉換符成功讀入且賦值的可變參數數目(若發生匹配錯誤而部分成功,該數目會小於指定的參數數目,甚至爲0)。若首次成功轉換或錯誤匹配發生前輸入已結束(如str爲空字符串),則返回EOF。發生讀取錯誤時也返回EOF,且設置錯誤碼errno(如format爲空指針時返回EOF並設置errno爲EINVAL)。可見,通過比較該函數的返回值與指定的可變參數數目,可判斷格式轉換是否成功。

format可爲一個或多個{% [width] [{h | l | L}]type | ' ' | '\t' | '\n' | 非%符號}格式轉換符。集合中{a|b|c}表示格式符a、b、c任選其一。以中括號括起來的格式符可選。%與type爲必選,所有格式符必須以%開頭。

 

2. 參數及格式符的含義

int sscanf(const char *str, const char *format, ...)

str -- 這是 C 字符串,是函數檢索數據的源。

format -- 這是 C 字符串,包含了以下各項中的一個或多個:空格字符、非空格字符 和 format 說明符。

 

format 說明符形式爲 [=%[width][modifiers]type=],具體講解如下:

 

參數

描述

* 這是一個可選的星號,表示數據是從流 stream 中讀取的,但是可以被忽視,即它不存儲在對應的參數中。
width 這指定了在當前讀取操作中讀取的最大字符數。
modifiers 爲對應的附加參數所指向的數據指定一個不同於整型(針對 d、i 和 n)、無符號整型(針對 o、u 和 x)或浮點型(針對 e、f 和 g)的大小: h :短整型(針對 d、i 和 n),或無符號短整型(針對 o、u 和 x) l :長整型(針對 d、i 和 n),或無符號長整型(針對 o、u 和 x),或雙精度型(針對 e、f 和 g) L :長雙精度型(針對 e、f 和 g)
type 一個字符,指定了要被讀取的數據類型以及數據讀取方式。具體參見下一個表格。

 

1) 賦值抑制符 '*' 表明按照隨後的轉換符指示來讀取輸入,但將其丟棄不予賦值(“跳過”)。抑制符無需相應的指針可變參數,該轉換也不計入函數返回的成功賦值次數。%*[width] [{h | l | L}]type 表示滿足該條件的字符被過濾掉,不會向目標參數中賦值。

2) width表示最大讀取寬度。當讀入字符數超過該值,或遇到不匹配的字符時,停止讀取。多數轉換丟棄起始的空白字符。這些被丟棄的字符及轉換結果添加的空結束符('\0')均不計入最大讀取寬度。

3) {h | l | L}爲類型修飾符。h指示輸入的數字數值以short int或unsigned short int類型存儲;hh指示輸入以signed char或unsigned char類型存儲。l(小寫L)指示輸入以long int、unsigned long int或double類型存儲,若與%c或%s結合則指示輸入以寬字符或寬字符串存儲;ll等同L。L指示輸入以long long類型存儲。

 

兩種特殊的格式符

1) []:字符集合。[]表示指定的字符集合匹配非空的字符序列;^則表示過濾。該操作不會跳過空白字符(空格、製表或換行符),因此可用於目標字符串不以空白字符分隔時。[]內可有一到多個非^字符(含連字符'-'),且無順序要求。%[a-z]表示匹配a到z之間的任意字符,%[aB-]匹配a、B、-中的任一字符;%[^a]則匹配非a的任意字符,即獲取第一個a之前的(不爲a的)所有字符。^可作用於多個條件,如^a-z=表示^a-z且^=(既非小寫字母亦非等號)。空字符集%[]和%[^]會導致不可預知的結果。

使用[]時接收輸入的參數必須是有足夠存儲空間的char、signed char或unsigned char數組。[]也是轉換符,故%[]後無s。

%[^]的含義和用法與正則表達式相同,故sscanf函數某種程度上提供了簡單的正則表達式功能。

 

2) n:至此已讀入值(未必賦值)的等價字符數,該數目必須以int類型存儲。如"10,22"經過"%d%*[^0-9]%n"格式轉換後,%n對應的參數值爲3(雖然','未參與賦值)。

'n'並非轉換符,儘管它可用'*'抑制。C標準聲稱,執行%n指令並不增加函數返回的賦值次數;但其勘誤表中的描述與之矛盾。建議不要假設%n對返回值的影響。

 

sscanf 類型說明符:

 

類型

合格的輸入

參數的類型

c 單個字符:讀取下一個字符。如果指定了一個不爲 1 的寬度 width,函數會讀取 width 個字符,並通過參數傳遞,把它們存儲在數組中連續位置。在末尾不會追加空字符。 char *
d 十進制整數:數字前面的 + 或 - 號是可選的。 int *
e,E,f,g,G 浮點數:包含了一個小數點、一個可選的前置符號 + 或 -、一個可選的後置字符 e 或 E,以及一個十進制數字。兩個有效的實例 -732.103 和 7.12e4 float *
o 八進制整數。 int *
s 字符串。這將讀取連續字符,直到遇到一個空格字符(空格字符可以是空白、換行和製表符)。 char *
u 無符號的十進制整數。 unsigned int *
x,X 十六進制整數。 int *

 

附加參數 -- 這個函數接受一系列的指針作爲附加參數,每一個指針都指向一個對象,對象類型由 format 字符串中相應的 % 標籤指定,參數與 % 標籤的順序相同。

 

針對檢索數據的 format 字符串中的每個 format 說明符,應指定一個附加參數。如果您想要把 sscanf 操作的結果存儲在一個普通的變量中,您應該在標識符前放置引用運算符 &,例如:

int n;
sscanf (str,"%d",&n);

 

3. 返回值

如果成功,該函數返回成功匹配和賦值的個數。如果到達文件末尾或發生讀錯誤,則返回 EOF。

 

4. 實例用法

 

1) 常見用法。

char buf[512] ;

sscanf("123456 ", "%s", buf);

printf("%s\n", buf);

結果爲:123456

 

2) 取指定長度的字符串。下例中,取最大長度爲4字節的字符串。

sscanf("123456 ", "%4s", buf);

printf("%s\n", buf);

結果爲:1234

 

3) 取到指定字符爲止的字符串。下例中,取遇到空格爲止的字符串。

sscanf("123456 abcdedf", "%[^ ]", buf);

printf("%s\n", buf);

結果爲:123456

 

4) 取僅包含指定字符集的字符串。下例中,取僅包含1到9和小寫字母的字符串。

sscanf("123456abcdedfBCDEF", "%[1-9a-z]", buf);

printf("%s\n", buf);

結果爲:123456abcdedf

 

5) 取到指定字符集爲止的字符串。下例中,取遇到大寫字母爲止的字符串。

sscanf("123456abcdedfBCDEF", "%[^A-Z]", buf);

printf("%s\n", buf);

結果爲:123456abcdedf

 

6) 給定一個字符串abc/etdev@123,獲取 / 和 @ 之間的字符串,先將 "abc/"過濾掉,再將非'@'的一串內容送到buf中

sscanf("abc/etdev@123", "%*[^/]/%[^@]", buf);

printf("%s\n", buf);

結果爲:etdev

 

7) 給定一個字符串“hello, world”,僅保留world。(注意:“,”之後有一空格)

sscanf(“hello, world”, "%*s%s", buf);

printf("%s\n", buf);

結果爲:world

%*s表示第一個匹配到的%s被過濾掉,即hello被過濾了,如果沒有空格則結果爲NULL。

 

8) 解析時間字符串如“YYYY/MM/DD,hh:mm:ss±zz”

char time[25] = “2019/01/01,12:30:10+00”;

int year, month, day, hour, minute, second;

sscanf(time, "%d/%d/%d,%d:%d:%d[^+-]", &year, &month, &day, &hour, &minute, &second);

//year=2019, month=1, day=1, hour=12, minute=30, second=10

printf("date time: %d-%02d-%02d %02d:%02d:%02d\r\n", year, month, day, hour, minute, second);

結果爲:2019-01-01 12:30:10


 

sscanf的功能很類似於正則表達式, 但卻沒有正則表達式功能強大, 所以比較複雜的字符串處理, 建議使用正則表達式。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章