C语言中sscanf()函数的字符串格式化用法
介绍 sscanf()为C语言标准库函数,用于从指定字符串中读入与指定格式相符的数据。函数原型声明在stdio.h头文件中: int sscanf(const char *str,const char *format,...); 该函数根据参数 以下简要说明各格式符的含义: 1) 赋值抑制符'*'表明按照随后的转换符指示来读取输入,但将其丢弃不予赋值(“跳过”)。抑制符无需相应的指针可变参数,该转换也不计入函数返回的成功赋值次数 2) 3) 4) 此外,还有两种特殊的格式符: 1) []:字符集合。[]表示指定的字符集合匹配非空的字符序列;^则表示过滤。该操作不会跳过空白字符(空格、制表或换行符),因此可用于目标字符串不以空白字符分隔时。[]内可有一到多个非^字符(含连字符'-'),且无顺序要求。%[a-z]表示匹配a到z之间的任意字符,%[aB-]匹配a、B、-中的任一字符;%[^a]则匹配非a的任意字符,即获取第一个a之前的(不为a的)所有字符。^可作用于多个条件,如^a-z=表示^a-z且^=(既非小写字母亦非等号)。空字符集%[]和%[^]会导致不可预知的结果。 使用[]时接收输入的参数必须是有足够存储空间的 %[^]的含义和用法与正则表达式相同,故 2) n:至此已读入值(未必赋值)的等价字符数,该数目必须以int类型存储。如"10,22"经过"%d%*[^0-9]%n"格式转换后,%n对应的参数值为3(虽然','未参与赋值)。 'n'并非转换符,尽管它可用'*'抑制。C标准声称,执行%n指令并不增加函数返回的赋值次数;但其勘误表中的描述与之矛盾。建议不要假设%n对返回值的影响。
下表列举sscanf函数常见的格式化用法:
此外,还有如下几种用法: 【例1】读入一行字符串 因字符串可能含空白字符,故不能直接使用%s;而 【例2】提取"Name = Yuan"中的"Name" 若行首有空白字符,可用 若不确定行首有无空白字符,可先跳过空白字符: 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)!nr",__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] = ' '; *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=%dn",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=%dn",dwIdx,dwSize,dwVal); } 上述实现稍加改造,即可用于处理某种字符分隔的数字串。 总结 综上,对于简单的字符串分析,采用sscanf函数处理比较简洁。若字符串比较复杂,则可借助相应的正则表达式库。需要注意,sscanf格式化的目的是“截取”,而正则表达式的目的是“匹配”,不能完全等同。 以上就是本文的全部内容改了,希望对大家的学习能有所帮助,如果疑问的话欢迎大家留言讨论。 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |