Printing binary

Please support our C++ advertiser: Programming Forums - DaniWeb Sister Site
Thread Solved

Join Date: Jun 2007
Posts: 322
Reputation: Hamrick will become famous soon enough Hamrick will become famous soon enough 
Solved Threads: 33
Hamrick's Avatar
Hamrick Hamrick is offline Offline
Posting Whiz

Printing binary

 
1
  #1
Jun 27th, 2007
I was playing with a bunch of new things today and came up with this. Did I do anything wrong?
  1. /*
  2.   binary class manipulator
  3.  
  4.   Print values or strings as binary
  5.   by Kimberly Hamrick
  6. */
  7. #include <iostream> // for C++ I/O
  8. #include <string> // for C++ strings
  9.  
  10. using namespace std;
  11.  
  12. namespace hamrick {
  13. template <typename T>
  14. class binary {
  15. public:
  16. explicit binary( const T value, const char *sep = " " )
  17. : _value( value ), _sep( sep ) {}
  18.  
  19. friend ostream& operator<<( ostream& os, const binary& b ) {
  20. return b._manip_value( os, b );
  21. }
  22. private:
  23. const T _value;
  24. const char *_sep;
  25.  
  26. ostream& _manip_value( ostream& os, const binary& b ) const {
  27. // Print each bit of the value
  28. // Separate bytes by b._sep
  29. for ( int bit = sizeof b._value * 8 - 1; bit >= 0; --bit ) {
  30. os<< ( ( b._value & ( 1 << bit ) ) != 0 );
  31. if ( bit % 8 == 0 ) os<< b._sep;
  32. }
  33.  
  34. return os;
  35. }
  36.  
  37. // Hide the assignment operator because of warnings
  38. binary<T> operator=( const binary<T>& );
  39. };
  40.  
  41. template <>
  42. class binary<string> {
  43. public:
  44. explicit binary( const string& value, const char *sep = " " )
  45. : _value( value ), _sep( sep ) {}
  46.  
  47. friend ostream& operator<<( ostream& os, const binary& b ) {
  48. return b._manip_string( os, b );
  49. }
  50. private:
  51. const string _value;
  52. const char *_sep;
  53.  
  54. ostream& _manip_string( ostream& os, const binary& b ) const {
  55. // Print each bit of each character
  56. // Separate characters by b._sep
  57. for ( const char *p = b._value.c_str(); *p != '\0'; ++p ) {
  58. for ( int bit = 7; bit >= 0; --bit )
  59. os<< ( ( ( *p >> bit ) & 1 ) != 0 );
  60. os<< b._sep;
  61. }
  62.  
  63. return os;
  64. }
  65.  
  66. // Hide the assignment operator because of warnings
  67. binary<string> operator=( const binary<string>& );
  68. };
  69. }
  70.  
  71. int main() {
  72. cout<< hamrick::binary<int>( 1234 ) <<endl;
  73. cout<< hamrick::binary<string>( "ABCD" ) <<endl;
  74.  
  75. for ( int a = 0; a < 256; a++ )
  76. cout<< hamrick::binary<char>( a ) <<endl;
  77.  
  78. return 0;
  79. }
Last edited by Hamrick; Jun 27th, 2007 at 6:20 pm.
Reply With Quote Quick reply to this message  
Join Date: Aug 2005
Posts: 15,662
Reputation: Ancient Dragon has a reputation beyond repute Ancient Dragon has a reputation beyond repute Ancient Dragon has a reputation beyond repute Ancient Dragon has a reputation beyond repute Ancient Dragon has a reputation beyond repute Ancient Dragon has a reputation beyond repute Ancient Dragon has a reputation beyond repute Ancient Dragon has a reputation beyond repute Ancient Dragon has a reputation beyond repute Ancient Dragon has a reputation beyond repute Ancient Dragon has a reputation beyond repute 
Solved Threads: 1502
Team Colleague
Featured Poster
Ancient Dragon's Avatar
Ancient Dragon Ancient Dragon is offline Offline
Still Learning

Re: Printing binary

 
0
  #2
Jun 27th, 2007
>>Did I do anything wrong?
Don't know -- why do you ask?
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.
Reply With Quote Quick reply to this message  
Join Date: Jun 2007
Posts: 322
Reputation: Hamrick will become famous soon enough Hamrick will become famous soon enough 
Solved Threads: 33
Hamrick's Avatar
Hamrick Hamrick is offline Offline
Posting Whiz

Re: Printing binary

 
0
  #3
Jun 27th, 2007
Because I have no idea what I'm doing. It works and does what I want but when that happens I'm always told it's wrong.
Reply With Quote Quick reply to this message  
Join Date: Aug 2005
Posts: 15,662
Reputation: Ancient Dragon has a reputation beyond repute Ancient Dragon has a reputation beyond repute Ancient Dragon has a reputation beyond repute Ancient Dragon has a reputation beyond repute Ancient Dragon has a reputation beyond repute Ancient Dragon has a reputation beyond repute Ancient Dragon has a reputation beyond repute Ancient Dragon has a reputation beyond repute Ancient Dragon has a reputation beyond repute Ancient Dragon has a reputation beyond repute Ancient Dragon has a reputation beyond repute 
Solved Threads: 1502
Team Colleague
Featured Poster
Ancient Dragon's Avatar
Ancient Dragon Ancient Dragon is offline Offline
Still Learning

Re: Printing binary

 
0
  #4
Jun 27th, 2007
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.
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.
Reply With Quote Quick reply to this message  
Join Date: Dec 2006
Posts: 1,089
Reputation: vijayan121 is a name known to all vijayan121 is a name known to all vijayan121 is a name known to all vijayan121 is a name known to all vijayan121 is a name known to all vijayan121 is a name known to all 
Solved Threads: 164
vijayan121 vijayan121 is offline Offline
Veteran Poster

Re: Printing binary

 
0
  #5
Jun 27th, 2007
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
  1. #include <iostream> // for C++ I/O
  2. #include <string> // for C++ strings
  3. #include <bitset>
  4. #include <limits>
  5. using namespace std;
  6.  
  7. namespace hamrick
  8. {
  9. enum { char_bits = numeric_limits<unsigned char>::digits };
  10. template <typename T> class binary
  11. {
  12. public:
  13. explicit binary( const T value, const char *sep = " " )
  14. : _value( value ), _sep( sep ) {}
  15.  
  16. friend ostream& operator<<( ostream& os, const binary& b )
  17. {
  18. typedef bitset< sizeof(T)*char_bits > bs ;
  19. return os << bs( b._value ) << b._sep ;
  20. }
  21. private:
  22. T _value;
  23. string _sep;
  24. };
  25.  
  26. template <> class binary<string>
  27. {
  28. public:
  29. explicit binary( const string& value, const char *sep = " " )
  30. : _value( value ), _sep( sep ) {}
  31.  
  32. friend ostream& operator<<( ostream& os, const binary& b )
  33. {
  34. for( size_t i=0 ; i < b._value.size() ; ++i )
  35. os << bitset< char_bits >( b._value[i] ) << b._sep ;
  36. return os ;
  37. }
  38. private:
  39. string _value;
  40. string _sep;
  41. };
  42. }
  43.  
  44. int main()
  45. {
  46. cout<< hamrick::binary<int>( 1234 ) <<endl;
  47. cout<< hamrick::binary<string>( "ABCD" ) <<endl;
  48.  
  49. for ( int a = 0; a < 256; a++ )
  50. cout<< hamrick::binary<char>( a ) <<endl;
  51.  
  52. return 0;
  53. }
Last edited by vijayan121; Jun 28th, 2007 at 12:04 am.
Reply With Quote Quick reply to this message  
Join Date: Jun 2007
Posts: 322
Reputation: Hamrick will become famous soon enough Hamrick will become famous soon enough 
Solved Threads: 33
Hamrick's Avatar
Hamrick Hamrick is offline Offline
Posting Whiz

Re: Printing binary

 
0
  #6
Jun 28th, 2007
we don't have the requirements for the program so can't tell you if its right or wrong.
I don't have any requirements. I just wrote something that sounded useful and threw in a bunch of new C++ stuff I've been reading about like templates, manipulators and working with bits. Sorry about not giving more background into the program.
If you really coded the program you posted then you know more than what you give yourself credit for.
I coded it, but it took all day and I had to borrow ideas from all over the place to get it to work. I think your giving me too much credit.
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
But I thought because it's const that can't ever happen.
b. 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? 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<>
Now I'm completely lost.
d. 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?
Reply With Quote Quick reply to this message  
Join Date: Dec 2006
Posts: 1,089
Reputation: vijayan121 is a name known to all vijayan121 is a name known to all vijayan121 is a name known to all vijayan121 is a name known to all vijayan121 is a name known to all vijayan121 is a name known to all 
Solved Threads: 164
vijayan121 vijayan121 is offline Offline
Veteran Poster

Re: Printing binary

 
0
  #7
Jun 28th, 2007
> 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.
  1. binary<int> to_binary( int n )
  2. {
  3. char does_not_exist_once_fn_returns[] = "\n" ;
  4. binary<int> ret( n, sep ) ;
  5. return ret ;
  6. }
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
  1. struct person
  2. {
  3. const string name ; // name cannot be changed
  4. string address ; // address can change
  5. bool operator== ( const person& that ) const ;
  6. // both const qualifiers are required for const-correctness
  7. };
but when in doubt, always favour adding a const qualifier (over dropping it).
Last edited by vijayan121; Jun 28th, 2007 at 10:29 am.
Reply With Quote Quick reply to this message  
Join Date: Jun 2007
Posts: 322
Reputation: Hamrick will become famous soon enough Hamrick will become famous soon enough 
Solved Threads: 33
Hamrick's Avatar
Hamrick Hamrick is offline Offline
Posting Whiz

Re: Printing binary

 
0
  #8
Jun 28th, 2007
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.
I kind of figured what it does, but I haven't used enum yet, and I don't understand how numeric_limits works.
It doesn't depend on the endianness of the hardware platform. (that is one less detail we have to take care of.)
Endianness? What's that and how do I take care of it without bitset<>?
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 doesn't let me use _sep to divide the bytes. It just prints a long string of 1's and 0's.
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
I don't understand what the example is doing. Why is that different from what I have?
Reply With Quote Quick reply to this message  
Join Date: Dec 2006
Posts: 1,089
Reputation: vijayan121 is a name known to all vijayan121 is a name known to all vijayan121 is a name known to all vijayan121 is a name known to all vijayan121 is a name known to all vijayan121 is a name known to all 
Solved Threads: 164
vijayan121 vijayan121 is offline Offline
Veteran Poster

Re: Printing binary

 
0
  #9
Jun 28th, 2007
Originally Posted by Hamrick View Post
I kind of figured what it does, but I haven't used enum yet, and I don't understand how numeric_limits works.
an unnamed enum as in
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
see: http://en.wikipedia.org/wiki/Endianness

But it doesn't let me use _sep to divide the bytes. It just prints a long string of 1's and 0's.
we can do that quite easily. this is one way:
  1. template <typename T> class binary
  2. {
  3. public:
  4. explicit binary( const T value, const char *sep = " " )
  5. : _value( value ), _sep( sep ) {}
  6.  
  7. friend ostream& operator<<( ostream& os, const binary& b )
  8. {
  9. bitset< sizeof(T)*char_bits > bs( b._value ) ;
  10. const string& str = bs.to_string() ;
  11. for( size_t i=0 ; i<sizeof(T) ; ++i )
  12. os << str.substr( i*char_bits, char_bits ) << b._sep ;
  13. return os ;
  14. }
  15. private:
  16. T _value;
  17. string _sep;
  18. };

I don't understand what the example is doing. Why is that different from what I have?
in the above example, writing
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.
  1. struct S
  2. {
  3. const int c ; // never modifiable, even if S is modifiable
  4. int i ; // modifiable if S is modifiable, const otherwise
  5. mutable int m ; // always modifiable (never const even if S is const)
  6. S( int ii ) : c(ii) {}
  7. };
  8.  
  9. void foobar( S* ps, const S* pcs )
  10. {
  11. // both ps->c and pcs->c are of type const int; both are non-modifiable
  12. // ps->i is non-const, pcs->i is const
  13. // both ps->m and pcs->m are non-const, both are modifiable
  14. }
you were using member variables like c in the above example.
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.
Reply With Quote Quick reply to this message  
Join Date: Jun 2007
Posts: 322
Reputation: Hamrick will become famous soon enough Hamrick will become famous soon enough 
Solved Threads: 33
Hamrick's Avatar
Hamrick Hamrick is offline Offline
Posting Whiz

Re: Printing binary

 
0
  #10
Jun 28th, 2007
I don't really understand, but I don't think I will right away. I'll read all of the stuff you gave me and try to figure things out.
Reply With Quote Quick reply to this message  
Reply

This thread has been marked solved.
Perhaps start a new thread instead?
Message:




Views: 1276 | Replies: 9
Thread Tools Search this Thread



Tag cloud for C++
About Us | Contact Us | Advertise | DaniWeb | Acceptable Use Policy | RSS Feed

©2003 - 2009 DaniWeb® LLC