| | |
Printing binary
Please support our C++ advertiser: Programming Forums - DaniWeb Sister Site
Thread Solved |
I was playing with a bunch of new things today and came up with this. Did I do anything wrong?
c++ Syntax (Toggle Plain Text)
/* binary class manipulator Print values or strings as binary by Kimberly Hamrick */ #include <iostream> // for C++ I/O #include <string> // for C++ strings using namespace std; namespace hamrick { template <typename T> class binary { public: explicit binary( const T value, const char *sep = " " ) : _value( value ), _sep( sep ) {} friend ostream& operator<<( ostream& os, const binary& b ) { return b._manip_value( os, b ); } private: const T _value; const char *_sep; ostream& _manip_value( ostream& os, const binary& b ) const { // Print each bit of the value // Separate bytes by b._sep for ( int bit = sizeof b._value * 8 - 1; bit >= 0; --bit ) { os<< ( ( b._value & ( 1 << bit ) ) != 0 ); if ( bit % 8 == 0 ) os<< b._sep; } return os; } // Hide the assignment operator because of warnings binary<T> operator=( const binary<T>& ); }; template <> class binary<string> { public: explicit binary( const string& value, const char *sep = " " ) : _value( value ), _sep( sep ) {} friend ostream& operator<<( ostream& os, const binary& b ) { return b._manip_string( os, b ); } private: const string _value; const char *_sep; ostream& _manip_string( ostream& os, const binary& b ) const { // Print each bit of each character // Separate characters by b._sep for ( const char *p = b._value.c_str(); *p != '\0'; ++p ) { for ( int bit = 7; bit >= 0; --bit ) os<< ( ( ( *p >> bit ) & 1 ) != 0 ); os<< b._sep; } return os; } // Hide the assignment operator because of warnings binary<string> operator=( const binary<string>& ); }; } int main() { cout<< hamrick::binary<int>( 1234 ) <<endl; cout<< hamrick::binary<string>( "ABCD" ) <<endl; for ( int a = 0; a < 256; a++ ) cout<< hamrick::binary<char>( a ) <<endl; return 0; }
Last edited by Hamrick; Jun 27th, 2007 at 6:20 pm.
we don't have the requirements for the program so can't tell you if its right or wrong.
>>Because I have no idea what I'm doing.
If you really coded the program you posted then you know more than what you give yourself credit for.
>>Because I have no idea what I'm doing.
If you really coded the program you posted then you know more than what you give yourself credit for.
Don't PM me with questions -- you might get a nasty PM in response. If you have a question then post it in one of the forums.
•
•
Join Date: Dec 2006
Posts: 1,089
Reputation:
Solved Threads: 164
a. it is probably wiser not to hold the seperator string (_sep) as a pointer; this might get us into trouble if a temporary was passed as the second constructor arg
b. the hard coded assumption that CHAR_BITS==8 should be done away with
c. we could reuse the functionality available in std::bitset<>
d. and we can enable assignment by making the member variables non-const
b. the hard coded assumption that CHAR_BITS==8 should be done away with
c. we could reuse the functionality available in std::bitset<>
d. and we can enable assignment by making the member variables non-const
C++ Syntax (Toggle Plain Text)
#include <iostream> // for C++ I/O #include <string> // for C++ strings #include <bitset> #include <limits> using namespace std; namespace hamrick { enum { char_bits = numeric_limits<unsigned char>::digits }; template <typename T> class binary { public: explicit binary( const T value, const char *sep = " " ) : _value( value ), _sep( sep ) {} friend ostream& operator<<( ostream& os, const binary& b ) { typedef bitset< sizeof(T)*char_bits > bs ; return os << bs( b._value ) << b._sep ; } private: T _value; string _sep; }; template <> class binary<string> { public: explicit binary( const string& value, const char *sep = " " ) : _value( value ), _sep( sep ) {} friend ostream& operator<<( ostream& os, const binary& b ) { for( size_t i=0 ; i < b._value.size() ; ++i ) os << bitset< char_bits >( b._value[i] ) << b._sep ; return os ; } private: string _value; string _sep; }; } int main() { cout<< hamrick::binary<int>( 1234 ) <<endl; cout<< hamrick::binary<string>( "ABCD" ) <<endl; for ( int a = 0; a < 256; a++ ) cout<< hamrick::binary<char>( a ) <<endl; return 0; }
Last edited by vijayan121; Jun 28th, 2007 at 12:04 am.
•
•
•
•
we don't have the requirements for the program so can't tell you if its right or wrong.

•
•
•
•
If you really coded the program you posted then you know more than what you give yourself credit for.

•
•
•
•
a. it is probably wiser not to hold the seperator string (_sep) as a pointer; this might get us into trouble if a temporary was passed as the second constructor arg
•
•
•
•
b. the hard coded assumption that CHAR_BITS==8 should be done away with
But you lost me with the enum and digits thing. Can you explain how that works?•
•
•
•
c. we could reuse the functionality available in std::bitset<>

•
•
•
•
d. and we can enable assignment by making the member variables non-const
•
•
Join Date: Dec 2006
Posts: 1,089
Reputation:
Solved Threads: 164
> it is probably wiser not to hold the seperator string (_sep) as a pointer; this might get us into trouble if a temporary was passed as the second constructor arg
>> But I thought because it's const that can't ever happen.
when the function returns, lifetime of does_not_exist_once_fn_returns is over, but the returned object will hold the pointer. also, as in this example a non-const can be converted implicitly to a const.
> the hard coded assumption that CHAR_BITS==8 should be done away with
>> Isn't a byte always 8 bits? And a nybble is 4 bits?
in common usage, yes. but not as per the C standard. to quote it:
byte: The unit of storage in the execution environment large enough to hold any member of the basic character set of the execution environment. ... A byte is composed of a contiguous sequence of bits, the number of which is implementation-defined.
-- ISO/IEC 9899:1990(E) right on page 2
and the C++ standard is compatible with the C standard for the memory model of POD types.
>> you lost me with the enum and digits thing
C and cplusplus provide library headers (<limits.h> in C, <limits> in C++) which allow us to write correct code inspite of implementation differences. for a numeric type T, std::numeric_limits<T>::radix gives the radix and std::numeric_limits<T>::digits gives the number of digits to base radix.
so, numeric_limits<unsigned char>::digits gives the number of digits (bits) in an unsigned char. if we want to be pedantic, we could assert that numeric_limits<unsigned char>::radix == 2 (, but we do not need to because of C compatibility requirements). it is also possible to use the manifest constant CHAR_BITS from <climits> in place of our enum char_bits. ah, the things we need to do because we program to real (not virtual) machines.
> we could reuse the functionality available in std::bitset<>
>> Now I'm completely lost.
std::bitset<N> represents a sequence of N bits. a bitset<> is output streamable (gives a sequence of 0/1) and can be converted to and from a string. it can also be constructed using a unsigned long. in a bitset<N>, bit 0 is the least significant bit and bit N-1 is the most significant bit; It doesn't depend on the endianness of the hardware platform. (that is one less detail we have to take care of.) another advantage we get with bitset<> is that someone trying to use the binary<T> generalisation, where T is not (or implicitly convertible to) a numeric type would get a compile time error.
> and we can enable assignment by making the member variables non-const
>> I thought it was better to make everything const except the stuff that can't be. So I've been wrong the whole time about that?
you certailnly are not wrong about that; infact that notion is something that would be your friend whenever you write code. but it would be easier (and more flexible) to treat a non-mutable binary<T> as a
const binary<T> rather than a binary<T> with const members. for example
but when in doubt, always favour adding a const qualifier (over dropping it).
>> But I thought because it's const that can't ever happen.
C++ Syntax (Toggle Plain Text)
binary<int> to_binary( int n ) { char does_not_exist_once_fn_returns[] = "\n" ; binary<int> ret( n, sep ) ; return ret ; }
> the hard coded assumption that CHAR_BITS==8 should be done away with
>> Isn't a byte always 8 bits? And a nybble is 4 bits?
in common usage, yes. but not as per the C standard. to quote it:
byte: The unit of storage in the execution environment large enough to hold any member of the basic character set of the execution environment. ... A byte is composed of a contiguous sequence of bits, the number of which is implementation-defined.
-- ISO/IEC 9899:1990(E) right on page 2
and the C++ standard is compatible with the C standard for the memory model of POD types.
>> you lost me with the enum and digits thing
C and cplusplus provide library headers (<limits.h> in C, <limits> in C++) which allow us to write correct code inspite of implementation differences. for a numeric type T, std::numeric_limits<T>::radix gives the radix and std::numeric_limits<T>::digits gives the number of digits to base radix.
so, numeric_limits<unsigned char>::digits gives the number of digits (bits) in an unsigned char. if we want to be pedantic, we could assert that numeric_limits<unsigned char>::radix == 2 (, but we do not need to because of C compatibility requirements). it is also possible to use the manifest constant CHAR_BITS from <climits> in place of our enum char_bits. ah, the things we need to do because we program to real (not virtual) machines.
> we could reuse the functionality available in std::bitset<>
>> Now I'm completely lost.
std::bitset<N> represents a sequence of N bits. a bitset<> is output streamable (gives a sequence of 0/1) and can be converted to and from a string. it can also be constructed using a unsigned long. in a bitset<N>, bit 0 is the least significant bit and bit N-1 is the most significant bit; It doesn't depend on the endianness of the hardware platform. (that is one less detail we have to take care of.) another advantage we get with bitset<> is that someone trying to use the binary<T> generalisation, where T is not (or implicitly convertible to) a numeric type would get a compile time error.
> and we can enable assignment by making the member variables non-const
>> I thought it was better to make everything const except the stuff that can't be. So I've been wrong the whole time about that?
you certailnly are not wrong about that; infact that notion is something that would be your friend whenever you write code. but it would be easier (and more flexible) to treat a non-mutable binary<T> as a
const binary<T> rather than a binary<T> with const members. for example
C++ Syntax (Toggle Plain Text)
struct person { const string name ; // name cannot be changed string address ; // address can change bool operator== ( const person& that ) const ; // both const qualifiers are required for const-correctness };
Last edited by vijayan121; Jun 28th, 2007 at 10:29 am.
•
•
•
•
C and cplusplus provide library headers (<limits.h> in C, <limits> in C++) which allow us to write correct code inspite of implementation differences. for a numeric type T, std::numeric_limits<T>::radix gives the radix and std::numeric_limits<T>::digits gives the number of digits to base radix.
so, numeric_limits<unsigned char>::digits gives the number of digits (bits) in an unsigned char. if we want to be pedantic, we could assert that numeric_limits<unsigned char>::radix == 2 (, but we do not need to because of C compatibility requirements). it is also possible to use the manifest constant CHAR_BITS from <climits> in place of our enum char_bits. ah, the things we need to do because we program to real (not virtual) machines.
•
•
•
•
It doesn't depend on the endianness of the hardware platform. (that is one less detail we have to take care of.)
•
•
•
•
another advantage we get with bitset<> is that someone trying to use the binary<T> generalisation, where T is not (or implicitly convertible to) a numeric type would get a compile time error.

•
•
•
•
but it would be easier (and more flexible) to treat a non-mutable binary<T> as a
const binary<T> rather than a binary<T> with const members. for example
•
•
Join Date: Dec 2006
Posts: 1,089
Reputation:
Solved Threads: 164
•
•
•
•
I kind of figured what it does, but I haven't used enum yet, and I don't understand how numeric_limits works.
enum { char_bits = numeric_limits<unsigned char>::digits };in normal code is equivalent to
const int char_bits = numeric_limits<unsigned char>::digits ;inside the body of a class, it is an just an easy way to define a constant (the value of which is known at compile time).
for numeric limits, see: http://www.dinkumware.com/manuals/?m...e=limits2.html
ie: "http://www.dinkumware.com/manuals/?m...e=limits2.html"
•
•
•
•
Endianness? What's that
•
•
•
•
But it doesn't let me use _sep to divide the bytes. It just prints a long string of 1's and 0's.
C++ Syntax (Toggle Plain Text)
template <typename T> class binary { public: explicit binary( const T value, const char *sep = " " ) : _value( value ), _sep( sep ) {} friend ostream& operator<<( ostream& os, const binary& b ) { bitset< sizeof(T)*char_bits > bs( b._value ) ; const string& str = bs.to_string() ; for( size_t i=0 ; i<sizeof(T) ; ++i ) os << str.substr( i*char_bits, char_bits ) << b._sep ; return os ; } private: T _value; string _sep; };
•
•
•
•
I don't understand what the example is doing. Why is that different from what I have?
friend ostream& operator<<( ostream& os, const binary& b )implies that as far as this function is concerned, b can not be modified; neither b._value or b._sep. in a const binary, both _value and _sep are const.
C++ Syntax (Toggle Plain Text)
struct S { const int c ; // never modifiable, even if S is modifiable int i ; // modifiable if S is modifiable, const otherwise mutable int m ; // always modifiable (never const even if S is const) S( int ii ) : c(ii) {} }; void foobar( S* ps, const S* pcs ) { // both ps->c and pcs->c are of type const int; both are non-modifiable // ps->i is non-const, pcs->i is const // both ps->m and pcs->m are non-const, both are modifiable }
i was using member variables like i in the above example.
(the daniweb C++ formatter does not believe that mutable is a C++ keyword)
Last edited by vijayan121; Jun 28th, 2007 at 12:33 pm.
![]() |
Similar Threads
Other Threads in the C++ Forum
- Previous Thread: which process reads the cin
- Next Thread: How do I initialize an array from infile?
Views: 1276 | Replies: 9
| Thread Tools | Search this Thread |
Tag cloud for C++
6 api application array arrays based beginner binary bmp c++ c/c++ calculator char char* class classes code compile compiler console conversion convert count data delete deploy dll download dynamiccharacterarray encryption error file format forms fstream function functions game givemetehcodez graph homeworkhelp iamthwee ifstream input int java lib lines list loop looping loops map math matrix memory newbie news number numbertoword output pointer problem program programming project python random read recursion recursive reference return rpg search simple sort sorting spoonfeeding string strings struct temperature template templates text text-file tree url variable vector video visual visualstudio void win32 windows winsock wordfrequency wxwidgets






