C說話中sscanf()函數的字符串格局化用法。本站提示廣大學習愛好者:(C說話中sscanf()函數的字符串格局化用法)文章只能為提供參考,不一定能成為您想要的結果。以下是C說話中sscanf()函數的字符串格局化用法正文
引見
sscanf()為C說話尺度庫函數,用於從指定字符串中讀入與指定格局符合的數據。函數原型聲明在stdio.h頭文件中:
int sscanf(const char *str, const char *format, ...);
該函數依據參數format
(格局化字符串)來轉換參數str指向的字符串,轉換後的成果存於對應的可變參數內。其前往值為依照指定格局轉換符勝利讀入且賦值的可變參數數量(若產生婚配毛病而部門勝利,該數量會小於指定的參數數量,乃至為0)。若初次勝利轉換或毛病婚配產生前輸出已停止(如str為空字符串),則前往EOF。產生讀取毛病時也前往EOF,且設置毛病碼errno(如format
為空指針時前往EOF並設置errno為EINVAL)。可見,經由過程比擬該函數的前往值與指定的可變參數數量,可斷定格局轉換能否勝利。
format
可為一個或多個{%[*] [width] [{h | l | L}]type | ' ' | '\t' | '\n' | 非%符號}
格局轉換符。聚集中{a|b|c}
表現格局符a、b、c任選其一。以中括號括起來的格局符可選。%與type為必選,一切格局符必需以%開首。
以下扼要解釋各格局符的寄義:
1) 賦值克制符'*'注解依照隨後的轉換符指導來讀取輸出,但將其拋棄不予賦值(“跳過”)。克制符無需響應的指針可變參數,該轉換也不計入函數前往的勝利賦值次數。%*[width] [{h | l | L}]type
表現知足該前提的字符被過濾失落,不會向目的參數中賦值。
2) width
表現最年夜讀取寬度。當讀入字符數跨越該值,或碰到不婚配的字符時,停滯讀取。多半轉換拋棄肇端的空白字符。這些被拋棄的字符及轉換成果添加的空停止符('\0')均不計入最年夜讀取寬度。
3) {h | l | L}
為類型潤飾符。h指導輸出的數字數值以short int
或unsigned short int
類型存儲;hh
指導輸出以signed char
或unsigned char
類型存儲。l(小寫L)指導輸出以long int
、unsigned long int
或double
類型存儲,若與%c或%s聯合則指導輸出以寬字符或寬字符串存儲;ll同等L。L指導輸出以long long
類型存儲。
4) type
為類型轉換符,如%s、%d。
另外,還有兩種特別的格局符:
1) []:字符聚集。[]表現指定的字符聚集婚配非空的字符序列;^則表現過濾。該操作不會跳過空白字符(空格、制表或換行符),是以可用於目的字符串不以空白字符分隔時。[]內可有一到多個非^字符(含連字符'-'),且無次序請求。%[a-z]表現婚配a到z之間的隨意率性字符,%[aB-]婚配a、B、-中的任一字符;%[^a]則婚配非a的隨意率性字符,即獲得第一個a之前的(不為a的)一切字符。^可感化於多個前提,如^a-z=表現^a-z且^=(既非小寫字母亦非等號)。空字符集%[]和%[^]會招致弗成預知的成果。
應用[]時吸收輸出的參數必需是有足夠存儲空間的char、signed char
或unsigned char
數組。[]也是轉換符,故%[]後無s。
%[^]的寄義和用法與正則表達式雷同,故sscanf
函數某種水平上供給了簡略的正則表達式功效。
2) n:至此已讀入值(未必賦值)的等價字符數,該數量必需以int類型存儲。如"10,22"經由"%d%*[^0-9]%n"格局轉換後,%n對應的參數值為3(固然','未介入賦值)。
'n'並不是轉換符,雖然它可用'*'克制。C尺度宣稱,履行%n指令其實不增長函數前往的賦值次數;但其刊誤表中的描寫與之抵觸。建議不要假定%n對前往值的影響。
下表羅列sscanf函數罕見的格局化用法:
另外,還有以下幾種用法:
【例1】讀入一行字符串
因字符串能夠含空白字符,故不克不及直接應用%s;而gets
函數存在溢出風險,不推舉應用。此時,可以使用sscanf
函數,格局化字符串設為"%[^\n]%*c"。%*c用於跳過換行符\n,以便再次讀入下一行。
【例2】提取"Name = Yuan"中的"Name"
若行首有空白字符,可用"%*[ \t]%[^= \t]"
格局串;
若不肯定行首有沒有空白字符,可先跳過空白字符:
char szName[] = "Name = Yuan"; char szResBuf[32] = {0}; sscanf(szName+strspn(szName," \t"), "%[^= \t]", szResBuf);
【例3】分化URL
通俗完成以下所示:
/***************************************************************************** * 函數稱號:OaSplitPwFarEndIpInfo * 功效描寫:將遠端IP信息分化為目標IP地址和端標語 * 留意事項:遠端IP信息應形如'udp://192.168.100.221:5000' *****************************************************************************/ static FUNC_STATUS OaSplitPwFarEndIpInfo(INT8U *pucFarEndIpInfo, INT32U *dwDstUdpPort, INT8U *pucDstIpAddr) { FUNC_STATUS retCode = S_OK; INT8U strUdpHead[] = "udp://"; INT8U ucUdpUrlLen = strlen(strUdpHead); INT8U ucIndex = 0; CHECK_TRIPLE_POINTER(pucFarEndIpInfo, dwDstUdpPort, pucDstIpAddr, S_NULL_POINTER); if(strncasecmp(pucFarEndIpInfo, strUdpHead, ucUdpUrlLen) != 0) { OmciLog(LOG_CES,"[%s]Cannot Parse FarEndIpInfo(%s)!\n\r", __FUNCTION__, pucFarEndIpInfo); return S_ERROR; } INT8U ucMaxUrlLen = ucUdpUrlLen + STR_IPV4_MAX_LEN; //防止未設置裝備擺設端口時墮入逝世輪回(infinite loop) for(ucIndex = 0; (pucFarEndIpInfo[ucUdpUrlLen] != ':') && (ucUdpUrlLen < ucMaxUrlLen); ucIndex++) { pucDstIpAddr[ucIndex] = pucFarEndIpInfo[ucUdpUrlLen++]; } pucDstIpAddr[ucIndex] = '\0'; *dwDstUdpPort = strtoul(&pucFarEndIpInfo[ucUdpUrlLen+1], NULL, 10); return retCode; }
應用sscanf格局化則更加簡略:
char szUrl[] = "udp://192.168.100.221:5000"; char szProt[4] = {0}, szIp[32] = {0}; unsigned int dwPort = 0; sscanf(szUrl, "%[^://]%*c%*c%*c%[^:]%*c%d", szProt, szIp, &dwPort); printf("szProt=%s, szIp=%s, dwPort=%d\n", szProt, szIp, dwPort);
【例4】提取數字
char szDig[]="10,22m,Z86,,880;555:666."; int dwIdx = 0, dwVal = 0, dwSize = 0; while(1 == sscanf(szDig+dwIdx, "%d%*[^0-9]%n", &dwVal, &dwSize)) { dwIdx += dwSize; printf("dwIdx=%d, dwSize=%d, dwVal=%d\n", dwIdx, dwSize, dwVal); }
上述完成略加改革,便可用於處置某種字符分隔的數字串。
總結
綜上,關於簡略的字符串剖析,采取sscanf函數處置比擬簡練。若字符串比擬龐雜,則可借助響應的正則表達式庫。須要留意,sscanf格局化的目標是“截取”,而正則表達式的目標是“婚配”,不克不及完整同等。
以上就是本文的全體內容改了,願望對年夜家的進修能有所贊助,假如疑問的話迎接年夜家留言評論辯論。