如何在C ++中将字符串转换为unsigned long?

时间:2013-07-23 14:52:29

标签: c++ stdin long-integer unsigned fgets

我需要编程方面的帮助。程序必须接受一个最终将转为unsigned long的字符串。但是这里有捕获,必须有一个错误捕获器,当你输入十六进制组合和像a!!!!!!这样的符号时会产生错误,而unsigned long变量必须能够接受并存储大于{{1}的输入这是4294967295。我试过这段代码:

FFFFFFFF

我的问题是,当我输入char buffer[256]; unsigned long holder; fgets(buffer,256,stdin); holder = strtoul (buffer,NULL,16); (9 F')代替FFFFFFFFF(8 F')时,持有人仍然会接受FFFFFFFF,即使它超过了4294967295。另一件事是,当我结合十六进制和a!!!!!之类的符号时,fgets仍然会考虑十六进制A.

你能告诉我一个如何做到这一点的想法吗?如果您对此代码以外的任何其他想法有所了解,请告诉我们。谢谢!

3 个答案:

答案 0 :(得分:1)

如果您使用的是“旧C stule字符串”,则可以通过将char *传递给strtoul调用来添加额外的检查,以查看“所有字符都已被删除”。

换句话说:

 char *end_ptr = NULL;
 ....
 errno = 0;
 holder = strtoul(buffer, &end_ptr, 16);

end_ptr将指向一个超过接受输入的字符,因此如果输入“a !!!!!”,它将指向'!'。

 if (end_ptr != '\0')  // Should point at "end of string marker". 
 {
     ... do something to indicate error. 
 }

要检测溢出,您必须依赖errno

if (errno != 0)
{
    ... deal with errors here . 
}

显然,你可以这样做:

if (errno != 0 || *end_ptr != '\0')
{
    .... deal with errors. 
}

使用C ++ std:stoul()函数会抛出异常,例如:

试    {        holder = std :: stoul(缓冲区);    }    抓住(...)    {        ......处理错误......    }

将是C ++风格的解决方案。

答案 1 :(得分:1)

因此,如果您查看strtoul的此文档,您会在Return Value部分看到此内容:

  

如果转换后的值超出相应的返回类型范围,则会发生范围错误,并返回ULONG_MAX或ULLONG_MAX。

因此,对于超出范围的检查,您需要与此类似的代码:

if ( ( holder == ULONG_MAX || holder == ULLONG_MAX ) && errno == ERANGE)

对于查看同一文档的a!!!!案例,您将看到:

  

这些函数将str_end指向的指针设置为指向解释的最后一个字符后面的字符。如果str_end为NULL,则忽略它。

您目前正在传递NULL,但如果您传入参数:

char *p;
holder = strtoul (buffer,&p,16);

您现在可以检查*p是否为NULL终止符,如果是,则处理所有字符,否则您知道自己有问题。

您还可以选择使用stoul,如果无法执行转换,则会抛出以下异常std::invalid_argument;如果转换后的值超出结果范围,则会std::out_of_range类型。

例如,您可以执行以下操作:

std::string str1(n) ;
size_t pos ;

try
{
   holder = std::stoul( str1, &pos, 16 ) ;
}
catch( std::invalid_argument e )
{
    std::cout << "Invalid argument" << std::endl ;
}
catch ( std::out_of_range  e )
{
    std::cout << "Out of range" << std::endl ;
}

pos将是处理的最后一个字符的索引,在您的情况下,pos != str1.length()然后它无法处理整个字符串并且您有问题。

答案 2 :(得分:0)

正如其他海报所说 - 如果你拥有它,请使用stoul

如果不这样做,您可以执行以下操作:

std::istringstream strm( buffer );

unsigned long holder = 1;
strm >> std::hex >> holder;

if( strm.fail() )
         // out-of-range

if( ! strm.eof() )
         // didn't read all available characters - catches "A!!!"