I am working through K&R for review and I thought that I would write some of my own routines for conversion of binary strings to int and int to binary string. I realize this is reinvetning the wheel; I am just doing this for fun. Also, I am attempting to follow this coding style CodingStyle.txt. Any and all critiques are welcomed.
#include <mybin.h>
#include <limits.h>
#include <errno.h>
/*
Parameters:
s - String with a maximum of 63 binary digits
Return:
- Decimal value of the binary string pointed to by s
Error:
- Negative returned on error check errno
*/
signed long binstr2int(char *s)
{
signed long rc;
for (rc = 0; '\0' != *s; s++) {
if (rc > (LONG_MAX/2)) {
errno = ERANGE;
return -1;
} else if ('1' == *s) {
rc = (rc * 2) + 1;
} else if ('0' == *s) {
rc *= 2;
} else {
errno = EINVAL;
return -1;
}
}
return rc;
}
/*
Parameters:
num - The number to convert to a binary string
s - Pointer to a memory region to return the string to
len - Size in bytes of the region pointed to by s
Return:
- Pointer to the beginning of the string
Error:
- NULL returned on error check errno
*/
char *int2binstr(unsigned long num, char *s, int len)
{
if (len < 2) {
errno = ERANGE;
*s = '\0';
return s;
} else if (0 == num) {
s[--len] = '\0';
s[--len] = '0';
return s + len;
} else {
for (s[--len] = '\0'; 0 != num; num >>= 1) {
if (0 == len) {
errno = ERANGE;
*s = '\0';
return s;
} else if (num & 1) {
s[--len] = '1';
} else {
s[--len] = '0';
}
}
}
return s + len;
}
Edit 1: Okay, here is the revised code. Most of the suggestions I agree with. I did retain filling the buffer from end to beginning because it seems like a logical flow to me and requires one less variable to deal with.
- The do while suggestion was spot on. The for loop was unusual and the do while consumed one of the conditionals making the code easier to read.
- The names of the functions have been revised so they are not misleading
- The functions now handle unsigned long ints
- ul2binstr now returns NULL on error. So this needs to be checked.
- Also the string parameter was in binstr2ul was made const
- The len parameter was changed to size_t type
/*
Parameters:
s - String with a maximum of log2(ULONG_MAX) binary characters
num - Memory address to store the result in
Return:
- Status integer
Error:
- Negative returned on error check errno
*/
int binstr2ul(const char *s, unsigned long *num)
{
unsigned long rc;
for (rc = 0; '\0' != *s; s++) {
if (rc > (ULONG_MAX/2)) {
errno = ERANGE;
return -1;
} else if ('1' == *s) {
rc = (rc * 2) + 1;
} else if ('0' == *s) {
rc *= 2;
} else {
errno = EINVAL;
return -1;
}
}
*num = rc;
return 0;
}
/*
Parameters:
num - The number to convert to a binary string
s - Pointer to a memory region to return the string to
len - Size in bytes of the region pointed to by s
Return:
- Pointer to the beginning of the string
Error:
- NULL returned on error check errno
*/
char *ul2binstr(unsigned long num, char *s, size_t len)
{
if (0 == len) {
errno = EINVAL;
return NULL;
} else {
s[--len] = '\0';
}
do {
if (0 == len) {
errno = ERANGE;
return NULL;
} else {
s[--len] = ((num & 1) ? '1' : '0');
}
} while ((num >>= 1) != 0);
return s + len;
}