Checking if an input is within its range of limits in C++

喜你入骨 提交于 2019-12-13 15:31:44

问题


I need to create multiple functions that will check if an input is valid or not. Here are some of my codes:

bool IsValidRange(signed char s)
{
    bool isValid = true;
    if (!((s>=SCHAR_MIN)&&(s<=SCHAR_MAX)))
    {
        isValid = false;
    }
    return isValid;
}

bool IsValidRange(int s)
{
    bool isValid = true;
    if (!((s>=INT_MIN)&&(s<=INT_MAX)))
    {
        isValid = false;
    }
    return isValid;
}

I'm using the header limits.h for this. Am I doing this the right way? Please take note that I'm just a beginner. I hope you all will understand. Thank you!


回答1:


the template above will not work for the mixture of signed and unsigned types, in addition to floats.

template<typename RangeType, typename ValueType >
bool IsInRange( ValueType value ) 
{
    if( ! numeric_limits<RangeType>::is_integer )
    {
        return  (value > 0 ? value  : -value) <= numeric_limits<RangeType>::max(); 
    }

    if ( numeric_limits<RangeType>::is_signed == 
         numeric_limits<ValueType>::is_signed )
    {
        return value >= numeric_limits<RangeType>::min() &&
               value <= numeric_limits<RangeType>::max();
    }
    else if( numeric_limits<RangeType>::is_signed )
    {
        return value <= numeric_limits<RangeType>::max();
    }
    else
    {
        return value >= 0 && value <=  numeric_limits<RangeType>::max();
    }
}



回答2:


#include <limits>

template<typename ValueType, typename RangeType >
bool IsInRange( ValueType value ) {
    return (value >= numeric_limits<RangeType>::min()) &&
           (value <= numeric_limits<RangeType>::max());
}

This will work for integral data types except for floating point values. numeric_limits<T>::min() will return the minimum normalized positive value for floating point types. C++11 introduced numeric_limits<T>::lowest() to resolve the issue.




回答3:


First off, you don't need all those convolutions with booleans. Just return the expression directly:

return (s >= SCHAR_MIN) && (s <= SCHAR_MAX);

Second, you should realize that both your functions always yield true: by definition, a signed char is always in the range [SCHAR_MIN, SCHAR_MAX], and an int is always in the range [INT_MIN, INT_MAX].

But if you chose different bounds, this would indeed be the way to do it (taking into account my first remark).

As EdS. suggested, you could use a templated solution to reduce the number of functions/overloads you need:

template<class T>
bool check_range(T value, T min, T max) {
    return (value >= min) && (value <= max);
}



回答4:


This is an implementation based on the answer by RadioKat, but it suppresses compiler warnings like:

warning: pointless comparison of unsigned integer with zero
warning: integer conversion resulted in a change of sign

by using template meta programming:

#include <limits>

template< typename T_Range, typename T_Value, bool T_RangeSigned, bool T_ValueSigned >
struct InIntegerRange;

template< typename T_Range, typename T_Value >
struct InIntegerRange< T_Range, T_Value, false, false >
{
    bool operator()( T_Value const & x )
    {
        return x >= std::numeric_limits< T_Range >::min() &&
               x <= std::numeric_limits< T_Range >::max();
    }
};

template< typename T_Range, typename T_Value >
struct InIntegerRange< T_Range, T_Value, false, true >
{
    bool operator()( T_Value const & x )
    {
        return x >= 0 && x <= std::numeric_limits< T_Range >::max();
    }
};

template< typename T_Range, typename T_Value >
struct InIntegerRange< T_Range, T_Value, true, false >
{
    bool operator()( T_Value const & x )
    {
        return x <= std::numeric_limits< T_Range >::max(); /* x >= 0 is given */
    }
};

template< typename T_Range, typename T_Value >
struct InIntegerRange< T_Range, T_Value, true, true >
{
    bool operator()( T_Value const & x )
    {
        return x >= std::numeric_limits< T_Range >::min() &&
               x <= std::numeric_limits< T_Range >::max();
    }
};

template< typename T_Range, typename T_Value >
inline bool inRange( T_Value const & x )
{
    if( std::numeric_limits< T_Range >::is_integer )
    {
        return InIntegerRange< T_Range, T_Value,
                               std::numeric_limits< T_Range >::is_signed,
                               std::numeric_limits< T_Value >::is_signed >()( x );
    }
    else
    {
        return ( x > 0 ? x : -x ) <= std::numeric_limits< T_Range >::max() ||
               ( std::isnan(x) && std::numeric_limits< T_Range >::has_quiet_NaN ) ||
               ( std::isinf(x) && std::numeric_limits< T_Range >::has_infinity );
    }
}


来源:https://stackoverflow.com/questions/18625964/checking-if-an-input-is-within-its-range-of-limits-in-c

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!