Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C Programming > integers to binary

Reply
Thread Tools

integers to binary

 
 
rayw
Guest
Posts: n/a
 
      12-13-2005
I've been trying to write a program that converts an entered number into its
binary representation using three different techniques - bit shifting, mod
2, and itoa..

However, I'm getting 'snow blind', and can't get the non-ISO itoa to work as
I'd like. The snow blindness makes me think it's me, and not the function!

The idea of the program was to be able to change #define I_TYPE char to any
scalar type, re-compile, and then play. Limited success so far though, and
I'm sure the code could be 'better'.

Any constructive comments welcome.

#include <stdio.h >
#include <stdlib.h>
#include <string.h>
#include <limits.h>


#define I_TYPE char

#define K sizeof(I_TYPE) * CHAR_BIT


// Forward decs.
//
char * binary1(I_TYPE n);
char * binary2(I_TYPE n);
char * binary3(I_TYPE n);
char * strrev (char * str);



int main(void)
{
char buffer[100];

puts("Enter numbers to convert to binary, or hit enter to quit");

while(strlen(fgets(&buffer[0], sizeof(buffer), stdin)) > 1)
{
I_TYPE l = (I_TYPE)strtol(&buffer[0], NULL, 10);

puts(binary1(l));

puts(binary2(l));

puts(binary3(l));
}

return 0;
}



char * binary1(I_TYPE n)
{
// Loop counter.
//
int i = 0;

// Bit-mask.
//
unsigned long int j = 1;

// 'static' essential - buffer is a local variable!!
//
static char buffer[K + 1];

buffer[sizeof(buffer) - 1] = '\0';

for(i = 0; i < K; i++)
{
buffer[i] = (n & j) == j ? '1' : '0';

j = j << 1;
}

return strrev(buffer);
}



char * binary2(I_TYPE n)
{
int i;

// 'static' essential - buffer is a local variable!!
//
static char buffer[K + 1];

buffer[sizeof(buffer) - 1] = '\0';

for(i = K - 1; i >= 0; n /= (unsigned long int)2)
{
buffer[i--] = n % 2 == 0 ? '0' : '1';
}

return buffer;
}



char * binary3(I_TYPE n)
{
// 'static' essential - buffer is a local variable!!
//
static char buffer[K + 1];

buffer[sizeof(buffer) - 1] = '\0';

// itoa() not a standard ISO function.
//
itoa(n, buffer, 2);

return buffer;
}



char * strrev(char * s)
{
char * p1;
char * p2;

if (!s || !*s)
{
return s;
}

else

{
for(p1 = s, p2 = s + strlen(s) - 1; p2 > p1; ++p1, --p2)
{
*p1 ^= *p2;
*p2 ^= *p1;
*p1 ^= *p2;
}
}

return s;
}


 
Reply With Quote
 
 
 
 
pete
Guest
Posts: n/a
 
      12-13-2005
rayw wrote:

> However, I'm getting 'snow blind',
> and can't get the non-ISO itoa to work as I'd like.
> The snow blindness makes me think it's me, and not the function!


> // itoa() not a standard ISO function.
> //
> itoa(n, buffer, 2);


This is the wrong newsgroup to ask about your itoa.
Doesn't your library have any documentation?

--
pete
 
Reply With Quote
 
 
 
 
rayw
Guest
Posts: n/a
 
      12-13-2005

"pete" <(E-Mail Removed)> wrote in message
news:(E-Mail Removed)...
> rayw wrote:
>
>> However, I'm getting 'snow blind',
>> and can't get the non-ISO itoa to work as I'd like.
>> The snow blindness makes me think it's me, and not the function!

>
>> // itoa() not a standard ISO function.
>> //
>> itoa(n, buffer, 2);

>
> This is the wrong newsgroup to ask about your itoa.
> Doesn't your library have any documentation?


Yes, it does, but I was hoping to get some theory here as to what it's
doing: I don't have the source.

For example, if you run the program 'as posted' and enter 255 for the value,
the output is:

[compiler 1: gcc]
255
11111111
11111111
11111111111111111111111111111111

[compiler 2: msvc]
255
11111111
11111111
11111111111111111111111111112111

If you enter something like 128, you get this

[compiler 1: gcc]
128
10000000
10000000
11111111111111111111111110000000

[compiler 2: msvc]
128
10000000
10000000
11111111111111111111111110001000

but for 127, you get this

[compiler 1: gcc]
127
01111111
01111111
1111111

[compiler 2: msvc]
127
01111111
01111111
1111111

So, I *think* there's 'weird stuff going on' - and that's about as
descriptive as I can get.

btw, on trying to debug the above, I noticed that msvc's itoa overwrites the
buffer, e.g., for 255 it returns

11111111111111111111111111111111

<--- 32 --->

So, I altered my code in binary3 to set the buffer larger:

static char buffer[sizeof(unsigned long int) * CHAR_BIT + 1];

That's cured most of the weirdness, but I'd like to understand what's going
on when you use an initial value like 128 - like it's using signed long ints
internally or something?

[from *both* msvc and gcc now]
128
10000000
10000000
11111111111111111111111110000000

Any clues as to what itoa might be doing?


 
Reply With Quote
 
Pieter Droogendijk
Guest
Posts: n/a
 
      12-13-2005
On Tue, 13 Dec 2005 10:21:09 +0000, rayw wrote:

> I've been trying to write a program that converts an entered number into its
> binary representation using three different techniques - bit shifting, mod
> 2, and itoa..
>
> However, I'm getting 'snow blind', and can't get the non-ISO itoa to work as
> I'd like. The snow blindness makes me think it's me, and not the function!


See below for comments about itoa().

> The idea of the program was to be able to change #define I_TYPE char to any
> scalar type, re-compile, and then play. Limited success so far though, and
> I'm sure the code could be 'better'.


Why, yes. Yes it can.

> Any constructive comments welcome.


Alright. I hope I haven't missed anything.

> #include <stdio.h >
> #include <stdlib.h>
> #include <string.h>
> #include <limits.h>
>
>
> #define I_TYPE char


Alright. I'll play. No comment, given that I_TYPE can change.

> #define K sizeof(I_TYPE) * CHAR_BIT


'K' is not a very verbose identifier. I wouldn't know what it's for by
looking at it.

Also, I_TYPE could contain padding bits and a sign bit. Perhaps you should
do something with xxx_MAX instead? I'll let you work on it.

> char * binary1(I_TYPE n);
> char * binary2(I_TYPE n);
> char * binary3(I_TYPE n);
> char * strrev (char * str);


> int main(void)
> {
> char buffer[100];
>
> puts("Enter numbers to convert to binary, or hit enter to quit");
>
> while(strlen(fgets(&buffer[0], sizeof(buffer), stdin)) > 1)


Bang!

What if fgets() fails? It's going to return NULL when it does. Don't you
want to know?

Oh, and strlen(NULL) is undefined.

> {
> I_TYPE l = (I_TYPE)strtol(&buffer[0], NULL, 10);


As I said before, l is a char at the moment, though it could be anything.
strtol's return type doesn't fit in there unless you're very very lucky,
because strtol() always returns a long.

strtol() also has this neat error reporting thing. You should use it.

Here's how to 'fix' this thing:
- l should be a long. Remove the cast.
- Check for errors (is l negative? Does errno equal ERANGE and is l
LONG_MIN or LONG_MAX?)
- Check if the value of l fits in an I_TYPE.
- Assign l to an I_TYPE.

> puts(binary1(l));
> puts(binary2(l));
> puts(binary3(l));
> }
> return 0;
> }


You use a lot of blank lines that serve no purpose I can detect.

> char * binary1(I_TYPE n)
> {
> // Loop counter.
> //


C++ type comments have been included in the C standard in C99 (and has
been available as a compiler extension in many compilers for years
before it was published). However, C99 is not quite the leading standard
just yet. Also, these comments can cause painful things on Usenet, though
I'll admit this comment isn't quite long enough for that. Perhaps after
being quoted in follow-ups a few dozen times.

> int i = 0;


Why not remove the comment and call it loop_counter?

> // Bit-mask.
> //
> unsigned long int j = 1;


Why not remove the comment and call it bit_mask?

More comments on 'j' below.

> // 'static' essential - buffer is a local variable!!
> //
> static char buffer[K + 1];


I'm a bit confused about this. Did you just declare buffer with static
storage duration because it's been defined in main() already? Because you
really don't have to. Read your C book up to and including the topic about
'scope'.

> buffer[sizeof(buffer) - 1] = '\0';
> for(i = 0; i < K; i++)
> {
> buffer[i] = (n & j) == j ? '1' : '0';


This expression could be nicer. How's this:

if ( (n & j) == j ) {
buffer[i] = '1';
}
else {
buffer[i] = '0';
}

> j = j << 1;


I can imagine what would happen if I_TYPE is wider than an unsigned long
int. Perhaps you should make j an I_TYPE? That would make sense, wouldn't
it?

> }
> return strrev(buffer);


You know how long the string's going to be in advance. Why not just fill
it the other way around (from K to 0 instead of from 0 to K)?

Though, okay, it's another method of converting it. I'll play.

> }


> char * binary2(I_TYPE n)
> {
> int i;
>
> // 'static' essential - buffer is a local variable!!
> //
> static char buffer[K + 1];


Again with this mysterious static, and the even more mysterious comment...

> buffer[sizeof(buffer) - 1] = '\0';
>
> for(i = K - 1; i >= 0; n /= (unsigned long int)2)


How about:
for (i = K-1; i >= 0; i--)

That keeps the loop nice and central. You'll have to change some other
things too to make the loop work again, but I'll leave those to you.

> {
> buffer[i--] = n % 2 == 0 ? '0' : '1';


See the last comment about awful expressions. Conditional expressions
should generally be avoided (IMHO).

> }
> return buffer;
> }


> char * binary3(I_TYPE n)
> {
> // 'static' essential - buffer is a local variable!!
> //
> static char buffer[K + 1];


Repeat.

> buffer[sizeof(buffer) - 1] = '\0';
>
> // itoa() not a standard ISO function.
> //
> itoa(n, buffer, 2);


Indeed it isn't. I don't have it.

Though according to http://www.mkssoftware.com/docs/man3/itoa.3.asp this
should work, unless I've gone blind.

What does it make of it? What do you /expect/ it to make of it?

> return buffer;
> }


> char * strrev(char * s)
> {
> char * p1;
> char * p2;
>
> if (!s || !*s)
> {
> return s;
> }
> else
> {
> for(p1 = s, p2 = s + strlen(s) - 1; p2 > p1; ++p1, --p2)
> {
> *p1 ^= *p2;
> *p2 ^= *p1;
> *p1 ^= *p2;


Though the swapping works, there's nothing wrong with just using a
temporary. I don't really know of a really good reason to do it this way.

> }
> }
> return s;
> }


--
Pieter Droogendijk <pieter at binky dot org dot uk>
PGP/1E92DBBC [ Make way for the Emperor's Finest. ] binky.org.uk

 
Reply With Quote
 
rayw
Guest
Posts: n/a
 
      12-13-2005

"Pieter Droogendijk" <(E-Mail Removed)> wrote in message
news(E-Mail Removed) OR.ukME...
> On Tue, 13 Dec 2005 10:21:09 +0000, rayw wrote:
>
>> I've been trying to write a program that converts an entered number into
>> its
>> binary representation using three different techniques - bit shifting,
>> mod
>> 2, and itoa..
>>
>> However, I'm getting 'snow blind', and can't get the non-ISO itoa to work
>> as
>> I'd like. The snow blindness makes me think it's me, and not the
>> function!

>
> See below for comments about itoa().
>
>> The idea of the program was to be able to change #define I_TYPE char to
>> any
>> scalar type, re-compile, and then play. Limited success so far though,
>> and
>> I'm sure the code could be 'better'.

>
> Why, yes. Yes it can.


<snip>

> I'm a bit confused about this. Did you just declare buffer with static
> storage duration because it's been defined in main() already? Because you
> really don't have to. Read your C book up to and including the topic about
> 'scope'.


Each binary?'()s local buffer is declared static as each of them returns
&buffer[0] to the caller - so, nothing to do with scope, just don't want to
return a frame variable.

>> buffer[sizeof(buffer) - 1] = '\0';
>> for(i = 0; i < K; i++)
>> {
>> buffer[i] = (n & j) == j ? '1' : '0';

>
> This expression could be nicer. How's this:
>
> if ( (n & j) == j ) {
> buffer[i] = '1';
> }
> else {
> buffer[i] = '0';
> }


I agree that to some it's more readable, but as it's more lines of code, and
duplicates the assignment etc, I think it's more prone to errors later -
like if someone changes it.

<snip>

>> // itoa() not a standard ISO function.
>> //
>> itoa(n, buffer, 2);

>
> Indeed it isn't. I don't have it.
>
> Though according to http://www.mkssoftware.com/docs/man3/itoa.3.asp this
> should work, unless I've gone blind.


Thanks for the ref and the comments.


 
Reply With Quote
 
Chuck F.
Guest
Posts: n/a
 
      12-13-2005
rayw wrote:
>
> I've been trying to write a program that converts an entered
> number into its binary representation using three different
> techniques - bit shifting, mod 2, and itoa..
>
> However, I'm getting 'snow blind', and can't get the non-ISO
> itoa to work as I'd like. The snow blindness makes me think
> it's me, and not the function!
>
> The idea of the program was to be able to change #define I_TYPE
> char to any scalar type, re-compile, and then play. Limited
> success so far though, and I'm sure the code could be 'better'.
>
> Any constructive comments welcome.


.... snip long winded code etc. ...

The following, which includes a test routine enabled by defining
TESTING at compile time, will convert any unsigned integral types
to a string on the output file. To handle signed values just
output a - sign and then use putword for the negation. Watch out
for maximum values with 2's complement.

#include <stdio.h>

int putword(unsigned long w, FILE *f)
{
if (w > 9)
if (0 > putword(w / 10, f)) return EOF;
return putc((w % 10) + '0', f);
} /* putword */

/* --------------- */

#ifdef TESTING

#include <stdlib.h>

int main(void)
{
int i;

for (i = 0; i < 10; i++) {
putword(i, stdout);
putc(' ', stdout);
putword(rand(), stdout);
putc('\n', stdout);
}
return 0;
} /* main */
#endif



--
Read about the Sony stealthware that is a security leak, phones
home, and is generally illegal in most parts of the world. Also
the apparent connivance of the various security software firms.
http://www.schneier.com/blog/archive...drm_rootk.html
 
Reply With Quote
 
Netocrat
Guest
Posts: n/a
 
      12-13-2005
On Tue, 13 Dec 2005 13:28:09 +0000, rayw wrote:
> "pete" <(E-Mail Removed)> wrote in message

[...]
>> This is the wrong newsgroup to ask about your itoa.
>> Doesn't your library have any documentation?

>
> Yes, it does, but I was hoping to get some theory here as to what it's
> doing: I don't have the source.


You haven't described the prototype, but likely the first parameter is an
int, to which your char would be converted, and which would require an
appropriately sized buffer...

> So, I altered my code in binary3 to set the buffer larger:
>
> static char buffer[sizeof(unsigned long int) * CHAR_BIT + 1];
>
> That's cured most of the weirdness


....as you discovered.

Reading the documentation carefully will probably help explain any other
unexpected behaviour.

One (likely unrelated) error in your code is the space between the end
of "stdio.h" and the closing ">" in the #include directive.

Make sure you're compiling in standards mode with warnings enabled.

[...]
--
http://members.dodo.com.au/~netocrat
 
Reply With Quote
 
Mark McIntyre
Guest
Posts: n/a
 
      12-13-2005
On Tue, 13 Dec 2005 15:42:49 -0000, in comp.lang.c , "rayw"
<(E-Mail Removed)> wrote:

>
>"Pieter Droogendijk" <(E-Mail Removed)> wrote in message
>news(E-Mail Removed) FOR.ukME...
>> On Tue, 13 Dec 2005 10:21:09 +0000, rayw wrote:
>>
>>> buffer[i] = (n & j) == j ? '1' : '0';

>>
>> This expression could be nicer. How's this:
>>
>> if ( (n & j) == j ) {
>> buffer[i] = '1';
>> }
>> else {
>> buffer[i] = '0';
>> }

>
>I agree that to some it's more readable, but as it's more lines of code, and
>duplicates the assignment etc, I think it's more prone to errors later -
>like if someone changes it.


IME readable code is considerably easier to maintain than unreadable
code. Write for readability first. Consider clever tricks only if
trying to obfuscate code.

if ( (n & j) == j )
buffer[i]='1';
else
buffer[i]='0';




----== Posted via Newsfeeds.Com - Unlimited-Unrestricted-Secure Usenet News==----
http://www.newsfeeds.com The #1 Newsgroup Service in the World! 120,000+ Newsgroups
----= East and West-Coast Server Farms - Total Privacy via Encryption =----
 
Reply With Quote
 
rayw
Guest
Posts: n/a
 
      12-13-2005

"Netocrat" <(E-Mail Removed)> wrote in message
news(E-Mail Removed)...
> On Tue, 13 Dec 2005 13:28:09 +0000, rayw wrote:


<snip>

> One (likely unrelated) error in your code is the space between the end
> of "stdio.h" and the closing ">" in the #include directive.


That's an error? I thought the preprocessor ignored such things?


 
Reply With Quote
 
Netocrat
Guest
Posts: n/a
 
      12-13-2005
On Tue, 13 Dec 2005 19:50:47 +0000, rayw wrote:
> "Netocrat" <(E-Mail Removed)> wrote in message
> news(E-Mail Removed)...

[...]
>> One (likely unrelated) error in your code is the space between the end
>> of "stdio.h" and the closing ">" in the #include directive.

>
> That's an error? I thought the preprocessor ignored such things?


"<" and ">" are delimiters. Everything between them is interpreted as the
header name, including the space. The same applies when double quotes are
used as the delimiters. (a newline character within the header name
delimiters is invalid though)

--
http://members.dodo.com.au/~netocrat
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
(8-bit binary to two digit bcd) or (8-bit binary to two digit seven segment) Fangs VHDL 3 10-26-2008 06:41 AM
writing binary file (ios::binary) Ron Eggler C++ 9 04-28-2008 08:20 AM
A 64-bit binary returning a value to a 32-bit binary? spammenotplui31@yahoo.ca C Programming 12 04-08-2007 07:02 AM
Picking out integers from a binary character string rusttree@gmail.com C++ 1 06-12-2005 03:19 AM
Re: ostreams, ios::binary, endian, mixed binary-ascii Marc Schellens C++ 8 07-15-2003 12:27 PM



Advertisments