Re: Why don't string support binary?
On Jun 10, 1:48 am, Immortal Nephi <Immortal_Ne...@hotmail.com> wrote:
I am curious. Why don't iostream libary support binary conversion?
Historical reasons, I suppose. In C, printf and scanf didn't
support binary, so nobody bothered defining it for ostream and
istream either. In both cases, an extension to support it would
be legal; the fact that no implementor has bothered suggests
that there isn't much demand for it. Or rather that those that
want or need it don't have very much commercial clout.
Let's say for example. You want to use "cout << hex << xx << endl"
What about "cout << binary << xx << endl"? No such binary exist.
Take a look at my code below. First example is the best option, but I
prefer second example. Do you have other ways that binary will be
supported?
string convBase(unsigned long v, long base)
{
string digits = "0123456789abcdef";
string result;
if((base < 2) || (base > 16)) {
result = "Error: base out of range.";
}
else {
do {
result = digits[v % base] + result;
v /= base;
}
while(v);
}
return result;
}
int main()
{
// First Example
unsigned long x = 0xABCD;
cout << "???: " << convBase(x,4) << endl;
cout << "Hex: " << convBase(x,16) << endl;
cout << "Decimal: " << convBase(x,10) << endl;
cout << "Octal: " << convBase(x,8) << endl;
cout << "Binary: " << convBase(x,2) << endl;
cout << "Test: " << convBase(x,32) << endl;
// Second Example
int i = 0x0203;
std::string s;
std::ostringstream out;
out << hex << i;
s = out.str();
cout << "-->" << s << "\n" << out.str() << endl;
return 0;
}
I don't quite see how the second example supports binary.
I'd probably do something like:
template< typename UInt > // constraint: UInt is
class BaseN // unsigned integral type
{
public:
explicit BaseN( UInt value, int base )
: myValue( value )
, myBase( base )
{
assert( base > 1 && base <= 36 ) ;
}
void print( std::ostream& dest ) const ;
friend std::ostream&operator<<( std::ostream& dest,
BaseN const& value )
{
value.print( dest ) ;
return dest ;
}
private:
UInt myValue ;
unsigned myBase ;
} ;
template< typename UInt >
void
BaseN< UInt >::print(
std::ostream& dest ) const
{
char buffer[ std::numeric_limits< UInt
::digits + 1 ] ;
char* p = buffer + sizeof( buffer ) ;
UInt tmp = myValue ;
char const* digits
= ( (dest.flags() & std::ios::uppercase) != 0
? "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
: "0123456789abcdefghijklmnopqrstuvwxyz" ) ;
*--p = '\0' ;
do {
*--p = digits[ tmp % myBase ] ;
tmp /= myBase ;
} while ( tmp != 0 ) ;
dest << p ;
}
template< typename UInt >
BaseN< UInt >
baseN( UInt value, int base )
{
return BaseN< UInt >( value, base ) ;
}
This would allow things like:
std::cout << baseN( someValue, 2 )
for a somevalue of any unsigned integral type, with any base
between 2 and 36.
Alternatively, it should be possible to define a manipulator
which sets a base and returns a wrapper to the stream which
intercepted integral conversions to convert using that base, so
that you could write:
std::cout << base( 2 ) << someValue ;
This is a bit tricker, however, and I've never found it worth
the extra effort.
--
James Kanze (GABI Software) email:james.kanze@gmail.com
Conseils en informatique orient=E9e objet/
Beratung in objektorientierter Datenverarbeitung
9 place S=E9mard, 78210 St.-Cyr-l'=C9cole, France, +33 (0)1 30 23 00 34