ANSI-C: maximum number of characters printing a decimal int

前端 未结 8 1738
醉梦人生
醉梦人生 2021-02-19 10:17

I\'d like to know if it is an easy way of determining the maximum number of characters to print a decimal int.

I know contains

8条回答
  •  旧时难觅i
    2021-02-19 10:35

    I don't know if it is any trick to do what you want in plain ANSI-C, but in C++ you can easily use template metaprogramming to do:

    #include    
    #include    
    #include    
    
    template< typename T, unsigned long N = INT_MAX >
    class   MaxLen
    {
    public:
        enum
        {
            StringLen = MaxLen< T, N / 10 >::StringLen + 1
        };
    };
    
    template< typename T >
    class   MaxLen< T, 0 >
    {
    public:
        enum
        {
            StringLen = 1
        };
    };
    

    And you can call it from your pure-C code creating an additional C++ function like this:

    extern "C"
    int int_str_max( )
    {
        return  MaxLen< int >::StringLen;
    }
    

    This has a ZERO execution time overhead and calculates the exact space needed.


    You can test the above templates with something like:

    int main( )
    {
    std::cout << "Max: " << std::numeric_limits< short >::max( ) << std::endl;
    std::cout << "Digits: " << std::numeric_limits< short >::digits10 << std::endl;
    std::cout << "A \"short\" is " << sizeof( short ) << " bytes." << std::endl
        << "A string large enough to fit any \"short\" is "
        << MaxLen< short, SHRT_MAX >::StringLen << " bytes wide." << std::endl;
    
    std::cout << "Max: " << std::numeric_limits< int >::max( ) << std::endl;
    std::cout << "Digits: " << std::numeric_limits< int >::digits10 << std::endl;
    std::cout << "An \"int\" is " << sizeof( int ) << " bytes." << std::endl
        << "A string large enough to fit any \"int\" is "
        << MaxLen< int >::StringLen << " bytes wide." << std::endl;
    
    std::cout << "Max: " << std::numeric_limits< long >::max( ) << std::endl;
    std::cout << "Digits: " << std::numeric_limits< long >::digits10 << std::endl;
    std::cout << "A \"long\" is " << sizeof( long ) << " bytes." << std::endl
        << "A string large enough to fit any \"long\" is "
        << MaxLen< long, LONG_MAX >::StringLen << " bytes wide." << std::endl;
    
        return  0;
    }
    

    The output is:

    Max: 32767
    Digits: 4
    A "short" is 2 bytes.
    A string large enough to fit any "short" is 6 bytes wide.
    Max: 2147483647
    Digits: 9
    An "int" is 4 bytes.
    A string large enough to fit any "int" is 11 bytes wide.
    Max: 9223372036854775807
    Digits: 18
    A "long" is 8 bytes.
    A string large enough to fit any "long" is 20 bytes wide.
    
    • Note the slightly different values from std::numeric_limits< T >::digits10 and MaxLen< T, N >::StringLen, as the former does not take into account digits if if can't reach '9'. Of course you can use it and simply add two if you don't care wasting a single byte in some cases.

    EDIT:

    Some may have found weird including . If you can count with C++11, you won't need it, and will earn an additional simplicity:

    #include    
    #include    
    
    template< typename T, unsigned long N = std::numeric_limits< T >::max( ) >
    class   MaxLen
    {
    public:
        enum
        {
            StringLen = MaxLen< T, N / 10 >::StringLen + 1
        };
    };
    
    template< typename T >
    class   MaxLen< T, 0 >
    {
    public:
        enum
        {
            StringLen = 1
        };
    };
    

    Now you can use

    MaxLen< short >::StringLen
    

    instead of

    MaxLen< short, SHRT_MAX >::StringLen
    

    Good, isn't?

提交回复
热议问题