最近開始喜歡上這個函數 sscanf.
int sscanf(constchar*buffer, constchar*format [, argument ] ... );
在stdlib中,scanf和printf有好多版本:
fscanf和fprintf是分別從流中格式化輸入輸出的。
scanf和printf是從標準裝置中格式化輸入輸出的。
sscanf和sprintf則是向字元緩衝區中格式化輸入輸出的。
這些函數除了重新導向的源和目的不同外,最為核心和強大的都是format的支援。
下面以sscanf為例,小結一下各個參數的強大功能。
一、常見格式說明符:
%d |
十進位整數. |
%o |
八進位整數 0. |
%x |
十六進位整數 0x. |
%D |
一個十進位整數,如果以0開始,則為八進位,如果以0x開始,則為十六進位. |
%f |
浮點數. |
%c |
單個字元. |
%s |
一個字串。如果%s後面跟一個%d,則%s只會匹配所有非數位字元. 如果後面跟一個%[],則%s會匹配所有的沒有在%[]中出現的字元. 如果後面跟一般字元串text,則%s會匹配所有的字元,直到text的第一次出現. |
%Ns |
如上,匹配一個長度為N的字串. |
%[characters] |
一個字串包含任意characters列表中的字元. 一個減號可以用來表示範圍。例如%[a-d]表示包含任意a、b、c的字串(前閉後開的區間). 一個 ^ 符號表示否定、去除的意思。例如%[^abc]表示除了a,b,c的任一字元. 這些符號可以組合使用. |
%{format%} |
儘可能多地重複匹配這個格式,匹配結果是一個數組的數組。例如%{%d%} 匹配0個或多個整數. |
%% |
表示一個百分比符號%字元.類似於逸出字元. |
如果有星號(*)被放到了百分比符號%和格式說明符之間,如%*d, 則函數只會匹配這個格式說明符,會忽略第一個匹配說明符之前的字元。
sscanf函數返回成功匹配的字元占所有字元的百分比的一個整數(範圍從0到100).
如果一個匹配不成功,那麼sscanf會立即返回,沒有成功匹配的參數值不會改變。
二、執行個體
1、網上流傳很廣的周星星(具體是誰,我也不知道,姑且這麼稱呼)的一段代碼
#include <stdio.h>
int main()
{
const char* s = "iios/12DDWDFF@122";
char buf[20];
sscanf( s, "%*[^/]/%[^@]", buf );
printf( "%s\n", buf );
return 0;
}
結果為:12DDWDFF
其中
%*[^/],匹配了從開始到第一個'/'字元字元出現以前的字串,由於有'*',則將這部分忽略掉。
/,匹配該反斜線'/'
%[^@],匹配到第一個'@'之前的所有字串,即12DDWDFF
2、最近正在做的一個類似編譯後端的程式中的一個例子。
要解析諸如 mov A,R0之類的彙編指令序列
#include <stdio.h>
int main()
{
char* line ="MOV A,@R0\n";
char temp[2][10];
sscanf( line, "%*[^ ] %[^,]", temp[0] ); //運算元 A
sscanf( line, "%*[^,],%[^\n]", temp[1] ); //運算元 @R0
return 0;
}
本例中temp[0]匹配了A,temp[1]匹配了@R0
sscanf( line, "%*[^ ] %[^,]", temp[0] );
首先根據%*[^ ],可以忽略前面的"MOV",接著是一個空格,最後匹配到’,‘為止。
sscanf( line, "%*[^,],%[^\n]", temp[1] ); //運算元 @R0
首先根據%*[^,],匹配並忽略','之前的所以字元,然後再匹配直到行末尾。