Error[8]: Undefined offset: 35, File: /www/wwwroot/outofmemory.cn/tmp/plugin_ss_superseo_model_superseo.php, Line: 121
File: /www/wwwroot/outofmemory.cn/tmp/plugin_ss_superseo_model_superseo.php, Line: 473, decode(

概述介绍    sscanf()为C语言标准库函数,用于从指定字符串中读入与指定格式相符的数据。函数原型声明在stdio.h头文件中:

介绍

     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 intunsigned short int类型存储;hh指示输入以signed charunsigned char类型存储。l(小写L)指示输入以long intunsigned long intdouble类型存储,若与%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 charunsigned 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] = '
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",DWPort);
'; *DWDstUdpPort = strtoul(&pucfarendIpInfo[ucUdpUrlLen+1],NulL,10); return retCode;}

     使用sscanf格式化则更为简单:

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); }

    【例4】提取数字

总结 

     上述实现稍加改造,即可用于处理某种字符分隔的数字串。

[+++]

     综上,对于简单的字符串分析,采用sscanf函数处理比较简洁。若字符串比较复杂,则可借助相应的正则表达式库。需要注意,sscanf格式化的目的是“截取”,而正则表达式的目的是“匹配”,不能完全等同。

     以上就是本文的全部内容改了,希望对大家的学习能有所帮助,如果疑问的话欢迎大家留言讨论。

总结

以上是内存溢出为你收集整理的C语言中sscanf()函数的字符串格式化用法全部内容,希望文章能够帮你解决C语言中sscanf()函数的字符串格式化用法所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

)
File: /www/wwwroot/outofmemory.cn/tmp/route_read.php, Line: 126, InsideLink()
File: /www/wwwroot/outofmemory.cn/tmp/index.inc.php, Line: 166, include(/www/wwwroot/outofmemory.cn/tmp/route_read.php)
File: /www/wwwroot/outofmemory.cn/index.php, Line: 30, include(/www/wwwroot/outofmemory.cn/tmp/index.inc.php)
C语言中sscanf()函数的字符串格式化用法_C_内存溢出

C语言中sscanf()函数的字符串格式化用法

C语言中sscanf()函数的字符串格式化用法,第1张

概述介绍    sscanf()为C语言标准库函数,用于从指定字符串中读入与指定格式相符的数据。函数原型声明在stdio.h头文件中:

介绍

     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 intunsigned short int类型存储;hh指示输入以signed charunsigned char类型存储。l(小写L)指示输入以long intunsigned long intdouble类型存储,若与%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 charunsigned 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] = '
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",DWPort);
'; *DWDstUdpPort = strtoul(&pucfarendIpInfo[ucUdpUrlLen+1],NulL,10); return retCode;}

     使用sscanf格式化则更为简单:

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); }

    【例4】提取数字

总结 

     上述实现稍加改造,即可用于处理某种字符分隔的数字串。

     综上,对于简单的字符串分析,采用sscanf函数处理比较简洁。若字符串比较复杂,则可借助相应的正则表达式库。需要注意,sscanf格式化的目的是“截取”,而正则表达式的目的是“匹配”,不能完全等同。

     以上就是本文的全部内容改了,希望对大家的学习能有所帮助,如果疑问的话欢迎大家留言讨论。

总结

以上是内存溢出为你收集整理的C语言中sscanf()函数的字符串格式化用法全部内容,希望文章能够帮你解决C语言中sscanf()函数的字符串格式化用法所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/langs/1246366.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-06-07
下一篇 2022-06-07

发表评论

登录后才能评论

评论列表(0条)

保存