sscanf的高級用法【轉】

(轉自:https://blog.csdn.net/noodies/article/details/4386570?depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromBaidu-3&utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromBaidu-3

printf或者sprintf一定是任何一個C程序員最常見到的函數,與sprintf的作用相反,sscanf通常被用來解析並轉換字符串,其格式定義靈活多變,可以實現很強大的字符串解析功能。

 

sscanf的原型很簡單,定義如下:

#include <stdio.h>
int sscanf(const char *str, const char *format, ...);

str:待解析的字符串

format:字符串格式描述,其後是一序列數目不定的指針參數,存儲解析後的數據

 

下面是一個簡單的例子:

int year, month, day;

int converted = sscanf("20080808", "%04d%02d%02d", &year, &month, &day);

printf("converted=%d, year=%d, month=%d, day=%d/n", converted, year, month, day);

輸出結果:

converted=3, year=2008, month=8, day=8

 

"%04d%02d%02d"是用來解析字符串的格式,%表示格式轉換的開始,d表示轉換爲一個整數,04作爲d的修飾,表示這是一個長度爲4位的整數,不足4位時以0補齊。

例子返回結果等於3,表示有3個數據成功轉換,轉換成功數目同時取決於被解析的字符串以及其轉換格式,如果我們把例子中的格式改爲"%04d%02d",那麼sscanf將只返回2,day的數值不會被sscanf更改。

 

這是一個浮點數轉換的例子:

double longitude, latitude;
int converted = sscanf("113.123456789 31.123456789", "%lf %lf", &longitude, &latitude);
printf("converted=%d, longitude=%.9lf, latitude=%lf/n", converted, longitude, latitude);

輸出結果:

converted=2, longitude=113.123456789, latitude=31.123457

sscanf的格式字符串中,f表示這是一個浮點數,其修飾詞l表示這是一個double的浮點數。

 

上面是兩個關於sscanf基本的例子,下面我們來演示sscanf的高級用法:

char str[32] = "";
sscanf("123456abcdedf", "%31[0-9]", str);
printf("str=%s/n", str);

輸出結果:

str=123456

上面的格式中,[0-9]表示這是一個僅包含0-9這幾個字符的字符串,前面使用數字31修飾詞表示這個字符串緩衝區的最大長度(這也是sscanf最爲人詬病的地方,很容易出現緩衝區溢出錯誤,實際上sscanf是可以避免出現緩衝區溢出的,只要在書寫任何字符串解析的格式時,注意加上其緩衝區尺寸的限制)。

 

又一個例子:

char str[32] = "";
sscanf("123456abcdedf", "%31[0-9a-z]", str);
printf("str=%s/n", str);

輸出結果:

str=123456abcdedf

在格式[]中增加了a-z的描述。

 

使用^的例子:

char str[32] = "";
sscanf("123456abcdedf", "%31[^a-z]", str);
printf("str=%s/n", str);

輸出結果:

str=123456

在[]中增加^表示相反的意思,上面的[^a-z]表示一個不包含任何a-z之間的字符串。

 

使用*的例子:

char str[32] = "";
int ret = sscanf("123456abcdedf", "%*[0-9]%31[a-z]", str);
printf("ret=%d, str=%s/n",ret, str);

輸出結果:

ret=1, str=abcdedf

加上*修飾表示一個被忽略的數據,同時也不需要爲它準備空間存放解析結果。如上面的例子中,我們就只使用了str一個參數存放%31[a-z]的解析結果,而sscanf也只返回1,表示只解析了一個數據。

 

掌握了[], ^, *如何使用後,我們會發現sscanf原來是一個如此強大的工具,很多我們原先認爲必須使用正則表達式的地方,很可能使用sscanf就可以實現。

 

 

下面是format的一些參考資料:

 

轉換類型:

%d:整數,需要一個類型爲int*的的參數存放轉換結果

%i:整數,如果字符串以0x或者0X開頭,則按16進制進行轉換,如果以0開頭,則按8進制進行轉換,否則按10進制轉換,需要一個類型爲int*的的參數存放轉換結果

%o:無符號的8進制數,需要一個類型爲unsigned int*的參數存放轉換結果

%u:無符號的整數,需要一個類型爲unsigned int*的參數存放轉換結果

%x:無符號的16進制數,需要一個類型爲unsigned int*的參數存放轉換結果

%X:等同於%x

%f:浮點數,需要一個類型爲float*的參數存放轉換結果

 

%c:單個字符,需要一個類型爲char*的參數存放轉換結果

%s:以空格或者換行符結尾的字符串,需要一個類型爲char*的參數存放轉換結果

%[]:僅包含在[]中的字符的字符串,如[0-9]表示一個全部是數字的字符串,[a-z]表示一個全部爲小寫字母的字符串,需要一個類型爲char*的參數存放轉換結果

%[^]:與上面相反,[^之後,]之前的所有字符都作爲字符串結束標誌,如[^0-9]表示一個不包含任何0-9的字符串,需要一個類型爲char*的參數存放轉換結果

 

轉換類型修飾符:

*:忽略標誌,如%*d表示忽略一個整數,%*s表示忽略一個字符串

h:short修飾符,如%hd表示這是一個short int的整數

l:long修飾符,如%ld表示這是一個long int的整數, %lf表示這是一個double的浮點數(%f表示一個float的浮點數)

L: <GCC> long long修飾符,如%Ld表示這是一個64位字節的整數, %Lf表示這是一個long double的浮點數

I64: <VisualC++> __int64修飾符,如%I64d表示這是一個64位字節的整數
 

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