[轉]嵌入式C語言——sscanf函式使用技巧 - qkshan - 部落格園
嵌入式系統中有很多場所需要解析字串,如解析GPS的RMC幀,解析使用者通過串列埠輸入的監控命令等。一般的做法是先接受一幀字元資料,然後用sscanf函式提取相應欄位。
函式原型
int sscanf( const char *buffer, const char *format [, argument ] ... );
sscanf屬於scanf函式家族一員,從輸入源——字串中讀取字元並根據format給出的格式程式碼對它們進行轉換,省略號代表可變長度的指標列表。
format字串引數中的格式程式碼可以由4部分組成:% [*] [width] [h|l|L] 格式碼
如sscanf("...", "%4hd", &short_val)中%4hd表示從字串中提取寬度限制為4個數字的短整型。
小試身手
如接受到使用者輸入的一個監控命令,讀取0x0012地址的值:
rcv_buf = "$READ_CPU:0x0012#"
從rcv_buf裡面提取使用者需要讀取的值:
fetch_num = sscanf(rcv_buf, "$READ_CPU:%x", &read_address);
如果執行成功,該函式返回值fetch_num等於1,read_address==0x12,提取失敗的話fetch_num==0
*sscanf函式可以提取字串%s,單個字元%c,整型%d,%x,可以指定提取的整型的寬度,指定提取的浮點數的小數位數等等
使用陷阱
使用該函式尤其要注意的是:第3部分的指標引數的型別如上述的read_address的型別一定要和第2部分format格式程式碼中的引數的%x相匹配,在提取多個值時,一不小心,後面提取的值會把前面的全部覆蓋掉。舉個例子:
typedef struct{ char month; char day; short year;}DATE_T;DATE_T current_date = {0};fetch_num = sscanf("$TIME:20120228", "$TIME:%4u%2u%2u",¤t_date.year, ¤t_date.month, ¤t_date.day)
按照程式設計師的思路,提取出來的結果應該是:year = 2012, month=2, day = 28,但是實際結果卻是year=0, month = 2, day=28
原因就在於:%u提取的month是32位無符號整型,函式會把目的地址當作一個32位整形的地址,因此就杯具了,DATE_T結構體佔用4位元組,裡面¤t_date.month實際是指向第1個位元組的地址,如果被當作指向unsigned int的地址,把月份month=0x0000 0002的值拷貝過去,前面提取的佔用高2位元組的year就會被覆蓋掉,然後本來提取的year的值變成了0x0000
如何避免
*sscanf裡的地址所在的引數型別保持和第2部分的format格式化部分一致
typedef struct{ unsigned int month; unsigned int day; unsigned int year;}DATE_T;
總結
sscanf函式避免了手工操作字串之類重複發明輪子的行為,尤其注意該函式不會驗證指標引數的型別是否對應format格式程式碼中的正確型別。
---------------------
作者:qkshan
來源:CNBLOGS
原文:https://www.cnblogs.com/codeinsight/archive/2012/12/08/sscanf.html
版權宣告:本文為作者原創文章,轉載請附上博文連結!
內容解析By:CSDN,CNBLOG部落格文章一鍵轉載外掛