944,165 Members | Top Members by Rank

Ad:
  • C++ Discussion Thread
  • Marked Solved
  • Views: 1496
  • C++ RSS
Jun 27th, 2007
1

Printing binary

Expand Post »
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)
  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.
Similar Threads
Reputation Points: 180
Solved Threads: 34
Posting Whiz
Hamrick is offline Offline
322 posts
since Jun 2007
Jun 27th, 2007
0

Re: Printing binary

>>Did I do anything wrong?
Don't know -- why do you ask?
Sponsor
Team Colleague
Featured Poster
Reputation Points: 5608
Solved Threads: 2283
Retired and Enjoying Life
Ancient Dragon is offline Offline
21,963 posts
since Aug 2005
Jun 27th, 2007
0

Re: Printing binary

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.
Reputation Points: 180
Solved Threads: 34
Posting Whiz
Hamrick is offline Offline
322 posts
since Jun 2007
Jun 27th, 2007
0

Re: Printing binary

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.
Sponsor
Team Colleague
Featured Poster
Reputation Points: 5608
Solved Threads: 2283
Retired and Enjoying Life
Ancient Dragon is offline Offline
21,963 posts
since Aug 2005
Jun 27th, 2007
0

Re: Printing binary

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
C++ Syntax (Toggle Plain Text)
  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.
Reputation Points: 1159
Solved Threads: 285
Posting Virtuoso
vijayan121 is offline Offline
1,606 posts
since Dec 2006
Jun 28th, 2007
0

Re: Printing binary

Quote ...
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.
Quote ...
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.
Quote ...
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.
Quote ...
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?
Quote ...
c. we could reuse the functionality available in std::bitset<>
Now I'm completely lost.
Quote ...
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?
Reputation Points: 180
Solved Threads: 34
Posting Whiz
Hamrick is offline Offline
322 posts
since Jun 2007
Jun 28th, 2007
0

Re: Printing binary

> 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.
C++ Syntax (Toggle Plain Text)
  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
C++ Syntax (Toggle Plain Text)
  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.
Reputation Points: 1159
Solved Threads: 285
Posting Virtuoso
vijayan121 is offline Offline
1,606 posts
since Dec 2006
Jun 28th, 2007
0

Re: Printing binary

Quote ...
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.
Quote ...
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<>?
Quote ...
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.
Quote ...
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?
Reputation Points: 180
Solved Threads: 34
Posting Whiz
Hamrick is offline Offline
322 posts
since Jun 2007
Jun 28th, 2007
0

Re: Printing binary

Click to Expand / Collapse  Quote originally posted by Hamrick ...
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"

Quote ...
Endianness? What's that
see: http://en.wikipedia.org/wiki/Endianness

Quote ...
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:
C++ Syntax (Toggle Plain Text)
  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. };

Quote ...
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.
C++ Syntax (Toggle Plain Text)
  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.
Reputation Points: 1159
Solved Threads: 285
Posting Virtuoso
vijayan121 is offline Offline
1,606 posts
since Dec 2006
Jun 28th, 2007
0

Re: Printing binary

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.
Reputation Points: 180
Solved Threads: 34
Posting Whiz
Hamrick is offline Offline
322 posts
since Jun 2007

This thread is solved

Either the thread starter or a moderator has marked this thread as solved. You can most likely trust the responses and answers given. There is most likely no reason for any further responses to be posted here. If you have a related question, please start a new thread in this forum instead.

This thread is more than three months old

No one has posted to this discussion for at least three months. Please let old threads die and do not reply to them unless you feel you have something new and valuable to contribute that absolutely must be added to make the discussion complete. Otherwise, please start a new thread in this forum instead.
Message:
Previous Thread in C++ Forum Timeline: which process reads the cin
Next Thread in C++ Forum Timeline: How do I initialize an array from infile?





About Us | Contact Us | Advertise | Acceptable Use Policy
Forum Index | Build Custom RSS Feed


Follow us on Twitter


© 2011 DaniWeb® LLC