bowsayge wrote:
Rich Grise said to us:
.... snip ...
It's also an awful lot of rigamarole - why not just allocate
temp[] to write the bit digits to, then do
data[pos++] = temp[pos2--]. You could also stack them.
Yes! That'll eliminate the need to reverse the string. Thanks.
Nothing wrong with reversing strings. A routine to do so is short
and quite efficient, and useful elsewhere. Now that you have
beaten this to death take a look at the following (which I have
published before). Only the first 80 odd lines are generically
useful, the rest is stuff to exercise it and convince oneself that
it works correctly.
/* Routines to display values in various bases */
/* with some useful helper routines. */
/* by C.B. Falconer, 19 Sept. 2001 */
/* Released to public domain. Attribution appreciated */
#include <stdio.h>
#include <string.h>
#include <limits.h> /* ULONG_MAX etc. */
/* ======================= */
/* reverse string in place */
size_t revstring(char *stg)
{
char *last, temp;
size_t lgh;
lgh = strlen(stg);
if (lgh > 1) {
last = stg + lgh; /* points to '\0' */
while (last-- > stg) {
temp = *stg; *stg++ = *last; *last = temp;
}
}
return lgh;
} /* revstring */
/* ============================================ */
/* Mask and convert digit to hex representation */
/* Output range is 0..9 and a..f only */
int hexify(unsigned int value)
{
static char hexchars[] = "0123456789abcdef";
return (hexchars[value & 0xf]);
} /* hexify */
/* ================================================== */
/* convert unsigned number to string in various bases */
/* 2 <= base <= 16, controlled by hexify() */
/* Returns actual output string length */
size_t basedisplay(unsigned long number, unsigned int base,
char *stg, size_t maxlgh)
{
char *s;
/* assert (stg[maxlgh]) is valid storage */
s = stg;
if (maxlgh && base)
do {
*s = hexify(number % base);
s++;
} while (--maxlgh && (number = number / base) );
*s = '\0';
revstring(stg);
return (s - stg);
} /* basedisplay */
/* ================================================ */
/* convert signed number to string in various bases */
/* 2 <= base <= 16, controlled by hexify() */
/* Returns actual output string length */
size_t signbasedisplay(long number, unsigned int base,
char * stg, size_t maxlgh)
{
char *s;
size_t lgh;
unsigned long n;
s = stg; lgh = 0;
n = (unsigned long)number;
if (maxlgh && (number < 0L)) {
*s++ = '-';
maxlgh--;
n = -(unsigned long)number;
lgh = 1;
}
lgh = lgh + basedisplay(n, base, s, maxlgh);
return lgh;
} /* signbaseddisplay */
/* ==================== */
/* flush to end-of-line */
int flushln(FILE *f)
{
int ch;
while ('\n' != (ch = fgetc(f)) && (EOF != ch)) /* more */;
return ch;
} /* flushln */
/* ========== END of generically useful routines ============ */
/* ========================= */
/* Prompt and await <return> */
static void nexttest(char *prompt)
{
static char empty[] = "";
if (NULL == prompt) prompt = empty;
printf("\nHit return for next test: %s", prompt);
fflush(stdout);
flushln(stdin);
} /* nexttest */
/* ============================== */
/* Display a value and its length */
static void show(char *caption, int sz, char *stg)
{
if ((unsigned)sz != strlen(stg))
printf("Something is wrong with the sz value\n");
printf("%s: sz = %2d \"%s\"\n", caption, sz, stg);
} /* show */
/* =========== */
/* exercise it */
int main(void)
{
#define LGH 40
#define VALUE 1234567890
char stg[LGH];
unsigned int base;
int sz;
printf("\nExercising basedisplay routine\n");
printf("\nbase sz value\n");
for (base = 2; base <= 16; base++) {
sz = (int)basedisplay(VALUE, base, stg, LGH - 1);
printf("%2d %2d %s\n", base, sz, stg);
}
nexttest("ULONG_MAX");
for (base = 8; base <= 16; base++) {
sz = (int)basedisplay(ULONG_MAX, base, stg, LGH - 1);
printf("%2d %2d %s\n", base, sz, stg);
}
basedisplay(0, 10, stg, 3);
printf("\nzero %s\n", stg);
basedisplay(VALUE, 10, stg, 3);
printf("3 lsdigits only, base 10 %s\n", stg);
printf("\nBad calls:\n");
sz = (int)basedisplay(VALUE, 10, stg, 0);
show("0 length field", sz, stg);
sz = (int)basedisplay(VALUE, 1, stg, 20);
show("base 1, lgh 20", sz, stg);
sz = (int)basedisplay(VALUE, 0, stg, 20);
show("base 0, lgh 20", sz, stg);
sz = (int)signbasedisplay(-1234, 10, stg, 0);
show("0 lgh fld, -ve", sz, stg);
sz = (int)signbasedisplay(-1234, 10, stg, 2);
show("truncate -1234", sz, stg);
nexttest("System limits");
sz = (int)signbasedisplay(SCHAR_MIN, 10, stg, 20);
show("SCHAR_MIN ", sz, stg);
sz = (int)signbasedisplay(SCHAR_MAX, 10, stg, 20);
show("SCHAR_MAX ", sz, stg);
sz = (int)signbasedisplay(UCHAR_MAX, 10, stg, 20);
show("UCHAR_MAX ", sz, stg);
sz = (int)signbasedisplay(CHAR_MIN, 10, stg, 20);
show("CHAR_MIN ", sz, stg);
sz = (int)signbasedisplay(CHAR_MAX, 10, stg, 20);
show("CHAR_MAX ", sz, stg);
sz = (int)signbasedisplay(MB_LEN_MAX, 10, stg, 20);
show("MB_LEN_MAX ", sz, stg);
sz = (int)signbasedisplay(SHRT_MIN, 10, stg, 20);
show("SHRT_MIN ", sz, stg);
sz = (int)signbasedisplay(SHRT_MAX, 10, stg, 20);
show("SHRT_MAX ", sz, stg);
sz = (int)signbasedisplay(USHRT_MAX, 10, stg, 20);
show("USHRT_MAX ", sz, stg);
sz = (int)signbasedisplay(INT_MIN, 10, stg, 20);
show("INT_MIN ", sz, stg);
sz = (int)signbasedisplay(INT_MAX, 10, stg, 20);
show("INT_MAX ", sz, stg);
sz = (int)signbasedisplay(INT_MAX, 10, stg, 20);
show("INT_MAX ", sz, stg);
sz = (int) basedisplay(UINT_MAX, 10, stg, 20);
show("UINT_MAX ", sz, stg);
sz = (int)signbasedisplay(LONG_MIN, 10, stg, 20);
show("LONG_MIN ", sz, stg);
sz = (int)signbasedisplay(LONG_MAX, 10, stg, 20);
show("LONG_MAX ", sz, stg);
sz = (int) basedisplay(ULONG_MAX, 10, stg, 20);
show("ULONG_MAX ", sz, stg);
nexttest("DONE");
return 0;
} /* main */
--
Chuck F (cb********@yahoo.com) (cb********@worldnet.att.net)
Available for consulting/temporary embedded and systems.
<http://cbfalconer.home.att.net> USE worldnet address!