sscanf,sscanf_s及其相关用法(字符串格式化为其他类型)
#include<stdio.h>
?定義函數 int sscanf (const char *str,const char * format,........);
函數說明?
?sscanf()會將參數str的字符串根據參數format字符串來轉換并格式化數據。格式轉換形式請參考scanf()。轉換后的結果存于對應的參數內。
返回值 成功則返回參數數目,失敗則返回-1,錯誤原因存于errno中。 返回0表示失敗??? 否則,表示正確格式化數據的個數??? 例如:sscanf(str,"%d%d%s", &i,&i2, &s);??? 如果三個變成都讀入成功會返回3。??? 如果只讀入了第一個整數到i則會返回1。證明無法從str讀入第二個整數。
? ? ? ? ? ? main()?
??????????? {?
??????????? int i;?
??????????? unsigned int j;?
??????????? char input[ ]=”10 0x1b aaaaaaaa bbbbbbbb”;?
??????????? char s[5];?
??????????? sscanf(input,”%d %x %5[a-z] %*s %f”,&i,&j,s,s);?
??????????? printf(“%d %d %s ”,i,j,s);?
??????????? }
? ? ? ? ? ? 執行 10 27 aaaaa
大家都知道sscanf是一個很好用的函數,利用它可以從字符串中取出整數、浮點數和字符串等等。它的使用方法簡單,特別對于整數和浮點數來說。但新手可能并不知道處理字符串時的一些高級用法,這里做個簡要說明吧。
1. 常見用法。
charstr[512]={0};
sscanf("123456","%s",str);
printf("str=%s",str);
2. 取指定長度的字符串。如在下例中,取最大長度為4字節的字符串。
sscanf("123456","%4s",str);
printf("str=%s",str);
3. 取到指定字符為止的字符串。如在下例中,取遇到空格為止字符串。
sscanf("123456abcdedf","%[^]",str);
printf("str=%s",str);
4. 取僅包含指定字符集的字符串。如在下例中,取僅包含1到9和小寫字母的字符串。
sscanf("123456abcdedfBCDEF","%[1-9a-z]",str);
printf("str=%s",str);
5. 取到指定字符集為止的字符串。如在下例中,取遇到大寫字母為止的字符串。
sscanf("123456abcdedfBCDEF","%[^A-Z]",str);
printf("str=%s",str);
/
可以用如下代碼將字符串形式的ip地址轉換為四個整數:
????? 注意sscanf_s,當讀入的類型是整數或其它長度可以確定的類型時,不能在類型后面跟上長度,但是對于字符串類型(char *)長度無法得知則必須在類型后面明確指出字符串的最大長度(即可以容納的空間)。舉例如下:
??????對于多個字符串讀入的情況,代碼如下:
sscanf 函數非常好用,居然我以前一直不知道這個函數。最近朋友用VS2008寫程序時用到這個函數的安全版本 sscanf_s ,卻出現異常問題,無法解析字符串不說,還會崩潰。
int sscanf_s(
?? const char *buffer,
?? const char *format?[,
??????argument?] ...
);
這是MSDN里面關于函數的定義,沒有繼續詳細查看后面的備注,以及實例的情況下。根本感覺不到sscanf 與 sscanf_s 的區別。以為仍然是像sscanf 一樣使用,以致出現奇怪問題。
Example: // crt_sscanf_s.c // This program uses sscanf_s to read data items // from a string named tokenstring, then displays them.#include <stdio.h> #include <stdlib.h>int main( void ) {char tokenstring[] = "15 12 14...";char s[81];char c;int i;float fp;// Input various data from tokenstring:// max 80 character string plus NULL terminatorsscanf_s( tokenstring, "%s", s, _countof(s) );sscanf_s( tokenstring, "%c", &c, sizeof(char) );sscanf_s( tokenstring, "%d", &i );sscanf_s( tokenstring, "%f", &fp );// Output the data readprintf_s( "String = %s\n", s );printf_s( "Character = %c\n", c );printf_s( "Integer: = %d\n", i );printf_s( "Real: = %f\n", fp ); } 直到看完整個文檔,看到這個實例,才發現原來還有貓膩!sscanf_s 取值的時候,需要在每個取值后面指定取值的最大大小。 在使用VS2005編譯一個程序時,出現了很多警告,說是用的函數是不安全的,應當使用安全版本,即函數名稱增加“_s”的版本。
?
?警告內容:
?warning C4996: 'sscanf': This function or variable may be unsafe. Consider using sscanf_s instead.?
?
據了解,“_s”版本函數是微軟后來對c++做得擴展,用來替代原先不安全的函數,例如:printf、scanf、strcpy、fopen等等。
詳細參考:
ms-help://MS.VSCC.v80/MS.MSDN.v80/MS.VisualStudio.v80.chs/dv_vccrt/html/d9568b08-9514-49cd-b3dc-2454ded195a3.htm
原來安全版本的函數,對參數和緩沖邊界做了檢查,增加了返回值和拋出異常。這樣增加了函數的安全性,減少了出錯的幾率。
同時這也意味著在使用這些函數時,有時你不得不輸入更多的關于緩沖區大小的參數,多敲幾下鍵盤能換來更少的麻煩,值得!
下面總結了sscanf的以及sscanf_s的常用方法,也體現了“_s”版本函數與原函數的特別之處:
1、sscanf和scanf的不同是輸入來源,前者是一個字符串,后者則是標準輸入設備
2、sscanf的使用,以解析時間字符串為例,將字符串“2009-01-02_11:12:13”解析為整型年月日時分秒
//定義
?char cc;
?tm tm_temp={0};
?string stime("2009-01-02_11:12:13");
//(1) 必須嚴格按照分隔符形式匹配填寫,若遇到不匹配項則終止解析
?
?sscanf(stime.c_str(), "%4d-%2d-%2d_%2d:%2d:%2d",
??&tm_temp.tm_year,?
??&tm_temp.tm_mon,?
??&tm_temp.tm_mday,?
??&tm_temp.tm_hour,?
??&tm_temp.tm_min,?
??&tm_temp.tm_sec
??);
??
//(2) 可以不按照分割符號形式填寫,字符數必須一致,例如可以正確解析“2009/01/02_11:12:13”
?
?sscanf(stime.c_str(), "%4d%c%2d%c%2d%c%2d%c%2d%c%2d",
??&tm_temp.tm_year, &cc,
??&tm_temp.tm_mon, &cc,
??&tm_temp.tm_mday, &cc,
??&tm_temp.tm_hour, &cc,
??&tm_temp.tm_min, &cc,
??&tm_temp.tm_sec
??);
?
//(3) 可以不按照分割符號形式填寫,字符數必須一致,同上,%1s可以等同于%c
?
?sscanf(stime.c_str(), "%4d%1s%2d%1s%2d%1s%2d%1s%2d%1s%2d",
??&tm_temp.tm_year, &cc,
??&tm_temp.tm_mon, &cc,
??&tm_temp.tm_mday, &cc,
??&tm_temp.tm_hour, &cc,
??&tm_temp.tm_min, &cc,
??&tm_temp.tm_sec
??);
//(4) 可以不按照分割符形式和數量填寫,類型必須一致,例如可以正確解析“2009/01/02___11:12:13”
//這里使用了sscanf的正則表達式,與通用的正則表示類似但不完全相同,%*c表示忽略連續多個字符
?sscanf(stime.c_str(), "%4d%*c%2d%*c%2d%*c%2d%*c%2d%*c%2d",
??&tm_temp.tm_year,?
??&tm_temp.tm_mon,?
??&tm_temp.tm_mday,?
??&tm_temp.tm_hour,?
??&tm_temp.tm_min,?
??&tm_temp.tm_sec
??);
??
3、sscanf_s的使用
?//定義
?char cc[2];
?tm tm_temp={0};
?string stime("2009-01-02_11:12:13");
//(1) 與sscanf第一種方法相同,可以使用"%4d-%2d-%2d_%2d:%2d:%2d"格式匹配解析
?
?sscanf_s(stime.c_str(), "%4d-%2d-%2d_%2d:%2d:%2d",
???&tm_temp.tm_year,?
???&tm_temp.tm_mon,?
???&tm_temp.tm_mday,?
???&tm_temp.tm_hour,?
???&tm_temp.tm_min,?
???&tm_temp.tm_sec
???);
??
//(2) 使用%c格式對數據解析時,必須對相應的緩沖區增加長度參數,否則將會出錯
?sscanf_s(stime.c_str(), "%4d%c%2d%c%2d%c%2d%c%2d%c%2d",
??&tm_temp.tm_year, &cc, 1,
??&tm_temp.tm_mon, &cc, 1,
??&tm_temp.tm_mday, &cc, 1,
??&tm_temp.tm_hour, &cc, 1,
??&tm_temp.tm_min, &cc, 1,
??&tm_temp.tm_sec
??);
??
//(3) 使用%s格式對數據解析時,緩沖長度必須大于字符串長度,否則不予解析
?sscanf_s(stime.c_str(), "%4d%1s%2d%1s%2d%1s%2d%1s%2d%1s%2d",
???&tm_temp.tm_year, &cc, 2,
???&tm_temp.tm_mon, &cc, 2,
???&tm_temp.tm_mday, &cc, 2,
???&tm_temp.tm_hour, &cc, 2,
???&tm_temp.tm_min, &cc, 2,
???&tm_temp.tm_sec
???);
//(4) 與sscanf一樣,sscanf_s同樣支持正則表達式
?sscanf_s(stime.c_str(), "%4d%*c%2d%*c%2d%*c%2d%*c%2d%*c%2d",
??&tm_temp.tm_year,?
??&tm_temp.tm_mon,?
??&tm_temp.tm_mday,?
??&tm_temp.tm_hour,?
??&tm_temp.tm_min,?
??&tm_temp.tm_sec
??);
??
通過以上對比sscanf與sscanf_s的使用,可以看出后者對緩沖區安全有了更多的考慮,從而避免了許多不經意的煩惱。
大家都知道sscanf是一個很好用的函數,利用它可以從字符串中取出整數、浮點數和字符串等等。它的使用方法簡單,特別對于整數和浮點數來說。但新手可 能并不知道處理字符串時的一些高級用法,這里做個簡要說明吧。
1. 常見用法。
| 以下是引用片段: char?str[512]?=?;? sscanf("123456?",?"%s",?str);? printf("str=%sn",?str); |
2. 取指定長度的字符串。如在下例中,取最大長度為4字節的字符串。
| 以下是引用片段: sscanf("123456?",?"%4s",?str);? printf("str=%sn",?str); |
3. 取到指定字符為止的字符串。如在下例中,取遇到空格為止字符串。
| 以下是引用片段: sscanf("123456?abcdedf",?"%[^?]",?str);? printf("str=%sn",?str); |
4. 取僅包含指定字符集的字符串。如在下例中,取僅包含1到9和小寫字母的字符串。
| 以下是引用片段: sscanf("123456abcdedfBCDEF",?"%[1-9a-z]",?str);? printf("str=%sn",?str); |
5. 取到指定字符集為止的字符串。如在下例中,取遇到大寫字母為止的字符串。
以下是引用片段:sscanf("123456abcdedfBCDEF",?"%[^A-Z]",?str);?
printf("str=%sn",?str);
總結
以上是生活随笔為你收集整理的sscanf,sscanf_s及其相关用法(字符串格式化为其他类型)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: IOCP配合AcceptEx的例子
- 下一篇: 关于TCP下SOCKET的一些测试