登录  
 加关注
查看详情
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

秒大刀 博客

好好学习 天天向上

 
 
 

日志

 
 
 
 

C/C++字符串转数字  

2009-03-21 15:36:12|  分类: C/C++ |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |

    实际中经常要用到字符串转数字,C++用std::istream的operator>>可以实现,但C语言中改怎么做呢?自己写解析函数一般应该不是什么好的选择。C运行时库提供了以下两个API可以使用:

int atoi(const char *str);
long strtol(const char *nptr, char **endptr, int base);

     atoi接受的语法是[whitespace] [sign] [digits]] ,扫描参数str字符串,跳过前面的空格字符,直到遇上数字或正负符号才开始做转换,而再遇到非数字或字符串结束时才结束转换,并将结果返回。详细信息参见MSDN

    strtol接受的语法是[whitespace] [{+ | –}] [0 [{ x | X }]] [digits],将参数nptr字符串根据参数base来转换成长整型数。参数base范围从2至36,或0。参数base代表采用的进制方式,如 base值为10则采用10进制,若base值为16则采用16进制等。当base值为0时则是采用10进制做转换,但遇到如'0x'前置字符则会使用 16进制做转换。一开始strtol()会扫描参数nptr字符串,跳过前面的空格字符,直到遇上数字或正负符号才开始做转换,再遇到非数字或字符串结束时结束转换,并将结果返回。若参数endptr不为NULL,则会将遇到不合条件而终止的nptr中的字符指针由endptr返回。详细信息参见MSDN

    由此可以看出:strtol比atoi具有更大的灵活性。

    下面是我自己包装的一个安全解析方法:

inline bool TryParseInt32(const char* str, int* ret, char** end = NULL)
{
char* p = NULL;
if(str == NULL || ret == NULL)
goto L_ErrorEnd;
int n = strtol(str, &p, 0);
if(n == LONG_MAX || n == LONG_MIN)
{
if(errno == ERANGE)
goto L_ErrorEnd;
}
else if(n == 0)
{
if(p == str)
goto L_ErrorEnd;
}
if(end != NULL)
*end = p;
*ret = n;
return true;
L_ErrorEnd:
if(end != NULL)
*end = const_cast<char*>(str);
if(ret != NULL)
*ret = 0;
return false;
}
inline int ParseInt32(const char* str, int defaultValue = 0)
{
int n;
if(TryParseInt32(str, &n))
return n;
else
return defaultValue;
}

     用上面提供的TryParseInt32和ParseInt32方法可以安全可控的实现字符串向数字的转换。

     采用上面的TryParseInt32方法,可以写出对ARGB的32bit颜色解析方法如下:

bool TryParseARGB(const std::string& str, unsigned int* result)
{
if(result == NULL)
return false;
std::string s(str);
static const std::string WHITE_SPACE(" \t\r\n\f\v");
s.erase(s.find_last_not_of(WHITE_SPACE) + 1); // trim end
s.erase(0, s.find_first_not_of(WHITE_SPACE)); // trim begin
if(s.empty())
{
if(result != NULL)
*result = 0;
return false;
}
std::string::pointer p = NULL;
int n = 0;
if(TryParseInt32(s.c_str(), &n, &p))
{
if(*p == ',')
{
std::string::pointer p1 = NULL;
int n1 = 0;
if(TryParseInt32(p + 1, &n1, &p1))
{
if(*p1 == ',')
{
std::string::pointer p2 = NULL;
int n2 = 0;
if(TryParseInt32(p1 + 1, &n2, &p2))
{
if(*p2 == ',')
{
std::string::pointer p3 = NULL;
int n3 = 0;
if(TryParseInt32(p2 + 1, &n3, &p3))
{
if(*p3 == '\0')
{
if(n >= 0 && n <= 255
&& n1 >= 0 && n1 <= 255
&& n2 >= 0 && n2 <= 255
&& n3 >= 0 && n3 <= 255)
{
*result = (n << 24) | (n1 << 16) | (n2 << 8) | n3;
return true;
}
}
}
}
else if(*p2 == '\0')
{
if(n >= 0 && n <= 255
&& n1 >= 0 && n1 <= 255
&& n2 >= 0 && n2 <= 255)
{
*result = (0xff << 24) | (n << 16) | (n1 << 8) | n2;
return true;
}
}
}
}
}
}
else if(*p == '\0')
{
*result = n;
return true;
}
}
if(result != NULL)
*result = 0;
return false;
}
inline unsigned int ParseARGB(const std::string& str, unsigned int defaultValue)
{
unsigned int ret;
if(TryParseARGB(str, &ret))
return ret;
else
return defaultValue;
}

     该ARGB的颜色解析方法支持的格式为:

white := [ \t\r\n\f\v]
decnum := white*[1-9][0-9]*
octnum := white*0[0-7]*
hexnum := white*[xX][0-9a-zA-Z]+
num := decnum|octnum|hexnum
rgb := num,num,num
argb := num,num,num,num
COLOR := ^num|rgb|argb white*$

  评论这张
 
阅读(9553)| 评论(0)

历史上的今天

在LOFTER的更多文章

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2018