#include<stdio.h>html
定義函數 int sscanf (const char *str,const char * format,........);c++
函數說明
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);
}ide
執行 10 27 aaaaa函數
你們都知道sscanf是一個很好用的函數,利用它能夠從字符串中取出整數、浮點數和字符串等等。它的使用方法簡單,特別對於整數和浮點數來講。但新手可能並不知道處理字符串時的一些高級用法,這裏作個簡要說明吧。spa
1. 常見用法。3d
charstr[512]={0};
sscanf("123456","%s",str);
printf("str=%s",str);code
2. 取指定長度的字符串。如在下例中,取最大長度爲4字節的字符串。orm
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地址轉換爲四個整數:
char * inputIp
int ip[4];
sscanf_s(inputIp, "%d.%d.%d.%d", &ip[0], &ip[1],&ip[2],&ip[3]);
注意sscanf_s,當讀入的類型是整數或其它長度能夠肯定的類型時,不能在類型後面跟上長度,可是對於字符串類型(char *)長度沒法得知則必須在類型後面明確指出字符串的最大長度(便可以容納的空間)。舉例以下:
// 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 terminator
sscanf_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 read
printf_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(inputString, "%s.%s.%s.%s", s1, s1.length, s2, s2.length, s3, s3.length, s4, s4.length);
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 terminator sscanf_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 read printf_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」版本函數與原函數的特別之處:
一、sscanf和scanf的不一樣是輸入來源,前者是一個字符串,後者則是標準輸入設備
二、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
);
三、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);