1. 程式人生 > 其它 >[轉]嵌入式C語言——sscanf函式使用技巧 - qkshan - 部落格園

[轉]嵌入式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",&current_date.year, &current_date.month, &current_date.day)

按照程式設計師的思路,提取出來的結果應該是:year = 2012, month=2, day = 28,但是實際結果卻是year=0, month = 2, day=28

原因就在於:%u提取的month是32位無符號整型,函式會把目的地址當作一個32位整形的地址,因此就杯具了,DATE_T結構體佔用4位元組,裡面&current_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部落格文章一鍵轉載外掛