1

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

char buffer[256];
unsigned long holder;
fgets(buffer,256,stdin);
holder = strtoul (buffer,NULL,16);

我的问题是,当我输入FFFFFFFFF(9 F's)而不是FFFFFFFF(8 F's)时,持有人仍然会接受4294967295,即使它超过了。另一件事是,当我将十六进制和符号结合起来时a!!!!!fgets仍然考虑十六进制 A。

你能给我一个关于如何做到这一点的想法吗?如果您知道除此代码之外的任何其他想法,请告诉我。谢谢!

4

3 回答 3

1

如果您使用的是“旧的 C 样式字符串”,那么您可以通过将 a 传递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()函数会引发异常,因此 C++ 风格的解决方案类似于:

try
{
    holder = std::stoul(buffer);
}
catch(...)
{
    ... deal with error ... 
}
于 2013-07-23T15:12:28.050 回答
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);

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

如果无法执行转换并且转换后的值将超出结果类型的范围,您还可以选择使用stoulwhich throw 以下异常。std::invalid_argumentstd::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()它无法处理整个字符串并且您有问题。

于 2013-07-23T15:12:41.177 回答
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!!!"
于 2013-07-23T15:32:31.850 回答