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
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.
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?