convert dec number to HEX and oct and bin without c library function

Discussion in 'C Programming' started by whatluo, Jun 10, 2005.

  1. whatluo

    whatluo Guest

    Hi, all

    I'm now working on a program which will convert dec number to
    hex and oct and bin respectively, I've checked the clc but with no
    luck, so can anybody give me a hit how to make this done without
    strtol or s/printf function.

    Thanks,

    whatluo.
     
    whatluo, Jun 10, 2005
    #1
    1. Advertising

  2. whatluo

    Eric Sosman Guest

    Re: convert dec number to HEX and oct and bin without c libraryfunction

    whatluo wrote:
    > Hi, all
    >
    > I'm now working on a program which will convert dec number to
    > hex and oct and bin respectively, I've checked the clc but with no
    > luck, so can anybody give me a hit how to make this done without
    > strtol or s/printf function.


    Homework? Well, here's a hint: With pencil and paper,
    how would you convert "54321 seconds" to hours, minutes,
    and seconds? Go ahead, do it -- and while you do it, ask
    yourself what you're doing at each step, and why.

    --
    Eric Sosman
    lid
     
    Eric Sosman, Jun 10, 2005
    #2
    1. Advertising

  3. whatluo

    CBFalconer Guest

    Re: convert dec number to HEX and oct and bin without c libraryfunction

    whatluo wrote:
    >
    > I'm now working on a program which will convert dec number to
    > hex and oct and bin respectively, I've checked the clc but with no
    > luck, so can anybody give me a hit how to make this done without
    > strtol or s/printf function.


    I just happen to have this lying about:

    /* base2txt.h. Public domain by C.B. Falconer, 2005-05-12. */
    /* Output values to a text stream. No buffers needed */

    #ifndef H_base2txt_h
    # define H_base2txt_h
    # ifdef __cplusplus
    extern "C"
    {
    # endif

    #include <stdio.h>

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

    /* Convert unsigned value to stream of digits in base base.
    A NULL value for f returns a char count with no output
    Returns count of chars. output
    return is negative for any output error */
    int unum2txt(unsigned long n, unsigned int base, FILE *f);

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

    /* Convert signed value to stream of digits in base base.
    A NULL value for f returns a char count with no output
    Returns count of chars. output
    return is negative for any output error */
    int num2txt(long n, unsigned int base, FILE *f);

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

    /* Convert unsigned value to stream of decimal digits in fld.
    A NULL value for f returns a char count with no output
    A negative fld left justifies, else right.
    Returns count of chars. output
    return is negative for any output error */
    int unum2fld(unsigned long n, int fld, FILE *f);

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

    /* Convert signed value to stream of decimal digits in fld.
    A NULL value for f returns a char count with no output
    A negative fld left justifies, else right.
    Returns count of chars. output
    return is negative for any output error */
    int num2fld(long n, int fld, FILE *f);

    # ifdef __cplusplus
    }
    # endif
    #endif


    /* base2txt.c. Public domain by C.B. Falconer, 2005-05-12. */
    /* <http://cbfalconer.home.att.net> */
    /* Output values to a text stream. No buffers needed */

    /* To compile a test version use -DTESTING with gcc */
    /* To avoid recursion use -DNORECURSE with gcc. This */
    /* may be useful on some non-conforming systems. */

    #include "base2txt.h"

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

    /* Convert unsigned value to stream of digits in base
    A NULL value for f returns a char count with no output
    Returns count of chars. output
    return is negative for any output error */
    int unum2txt(unsigned long n, unsigned int base, FILE *f)
    {
    /* MUST be a power of 2 in length */
    static char hexchars[] = "0123456789abcdef";

    /* allow for terminal '\0' */
    #define MAXBASE (sizeof(hexchars)-1)
    #ifdef NORECURSE
    #include <limits.h>
    int count, ix;

    /* sufficient for a binary expansion */
    char buf[CHAR_BIT * sizeof(long)];
    #else
    int count, err;
    #endif

    if ((base < 2) || (base > MAXBASE)) base = 10;
    #ifdef NORECURSE
    count = ix = 0;
    do {
    buf[ix++] = hexchars[(n % base) & (MAXBASE-1)];
    } while ((n = n / base));
    while (ix--) {
    count++;
    if (f && (putc(buf[ix], f) < 0)) return -count;
    }
    #else
    count = 1;
    if (n / base) {
    if ((err = unum2txt(n / base, base, f)) < 0) return err;
    else count += err;
    }
    if (f && (putc(hexchars[(n % base) & (MAXBASE-1)], f) < 0))
    return -count;
    #endif
    return count;
    } /* unum2txt */

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

    /* Convert signed value to stream of digits in base
    A NULL value for f returns a char count with no output
    Returns count of chars. output
    return is negative for any output error */
    int num2txt(long n, unsigned int base, FILE *f)
    {
    int count, err;
    unsigned long val;

    val = n; count = 0;
    if (n < 0) {
    count++; val = -(unsigned long)n;
    if (f && (putc('-', f) < 0)) return - count;
    }
    err = unum2txt(val, base, f);
    if (err < 0) return err - count;
    return err + count;
    } /* num2txt */

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

    /* Negative return if i/o error occurs */
    /* Returns number of blanks output attempted */
    static int putblks(int count, FILE *f)
    {
    int ix;

    if (f && (count > 0)) {
    for (ix = 0; ix < count; ix++) {
    if (putc(' ', f) < 0) return -ix - 1;
    }
    return ix;
    }
    else return 0;
    } /* putblks */

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

    /* Convert unsigned value to stream of decimal digits in fld.
    A NULL value for f returns a char count with no output
    A negative fld left justifies, else right.
    Returns count of chars. output
    return is negative for any output error */
    int unum2fld(unsigned long n, int fld, FILE *f)
    {
    int err, digs, blanks;

    if (fld >= 0) { /* right justify in field */
    digs = unum2txt(n, 10, NULL);
    if (0 > (blanks = putblks(fld - digs, f))) return blanks;
    if (0 > (err = unum2txt(n, 10, f))) return err - blanks;
    else return err + blanks;
    }
    else { /* left justify */
    if ((digs = unum2txt(n, 10, f)) < 0) return digs;
    if (0 > (blanks = putblks(fld - digs, f)))
    return blanks - digs;
    else return blanks + digs;
    }
    } /* unum2fld */

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

    /* Convert signed value to stream of decimal digits in fld.
    A NULL value for f returns a char count with no output
    A negative fld left justifies, else right.
    Returns count of chars. output
    return is negative for any output error */
    int num2fld(long n, int fld, FILE *f)
    {
    int err, digs, blanks;

    if (fld >= 0) { /* right justify in field */
    digs = num2txt(n, 10, NULL);
    if (0 > (blanks = putblks(fld - digs, f))) return blanks;
    if (0 > (err = num2txt(n, 10, f))) return err - blanks;
    else return err + blanks;
    }
    else { /* left justify */
    if ((digs = num2txt(n, 10, f)) < 0) return digs;
    if (0 > (blanks = putblks(fld - digs, f)))
    return blanks - digs;
    else return blanks + digs;
    }
    } /* num2fld */

    #ifdef TESTING

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

    /* This does some questionable things in order to get values to
    display. This doesn't affect the validity of the routines */
    int main(int argc, char **argv)
    {
    unsigned int base;
    long num;
    int fieldused;

    if ((argc < 3) || (1 != sscanf(argv[1], "%u", &base)))
    puts("Usage: base2txt base value [value ...]\n"
    " where the value list is in decimal");
    else {
    printf("Dec.Input Base %u value [digs]\n", base);
    while (argc > 2) {
    sscanf(argv[--argc], "%ld", &num);
    printf("%11s .", argv[argc]);
    fieldused = unum2txt(num, base, stdout);
    if (fieldused != unum2txt(num, base, NULL))
    fputs("*ERROR*", stdout);
    printf(". [%d] .", fieldused);
    fieldused = num2txt(num, base, stdout);
    if (fieldused != num2txt(num, base, NULL))
    fputs("*ERROR*", stdout);
    printf(". [%d]\n", fieldused);
    }
    }
    return 0;
    } /* main, testing */
    #endif

    --
    "If you want to post a followup via groups.google.com, don't use
    the broken "Reply" link at the bottom of the article. Click on
    "show options" at the top of the article, then click on the
    "Reply" at the bottom of the article headers." - Keith Thompson
     
    CBFalconer, Jun 10, 2005
    #3
  4. whatluo

    W4CKO Guest

    Re: convert dec number to HEX and oct and bin without c library function

    Understand the base system of the target type, and how to manipulate
    it. Or, read the source code for a library function that implements it
    or something simular.

    Example (convert a byte value into hex string, untested):

    char *str;
    int i, len = 0, val = 19;

    for(i=val; i /= 10; len++);

    str = malloc(len + 1);
    *str = len;

    do {
    *--str = (val % 10) + '0';
    } while(val /= 10);

    str[len + 1] = NUL;

    whatluo wrote:
    > Hi, all
    >
    > I'm now working on a program which will convert dec number to
    > hex and oct and bin respectively, I've checked the clc but with no
    > luck, so can anybody give me a hit how to make this done without
    > strtol or s/printf function.
    >
    > Thanks,
    >
    > whatluo.
     
    W4CKO, Jun 10, 2005
    #4
  5. whatluo

    W4CKO Guest

    Re: convert dec number to HEX and oct and bin without c library function

    Sorry I was too hasty in my reply.

    W4CKO wrote:
    > Understand the base system of the target type, and how to manipulate
    > it. Or, read the source code for a library function that implements it
    > or something simular.
    >
    > Example (convert a byte value into hex string, untested):
    >


    Rather, convert integer value into ascii string (an example of
    manipulating base-10).

    > char *str;
    > int i, len = 0, val = 19;
    >
    > for(i=val; i /= 10; len++);
    >
    > str = malloc(len + 1);
    > *str = len;
    >
    > do {
    > *--str = (val % 10) + '0';
    > } while(val /= 10);
    >
    > str[len + 1] = NUL;
    >


    Let me put this in the form of a function (tested):

    /* assumes buffer is adequate. */

    #define NUL '\0'

    char *int2str(char *buf, unsigned int val) {

    unsigned int i, len = 0;

    if(val == 0) return("0");

    /* compute the length of the resultant string. */
    for(i=val; i /= 10; len++);

    /* start at the end of the buffer, */
    *buf = len;

    /* because we work backwards in the buffer. */
    do {
    *--buf = (val % 10) + '0';
    } while(val /= 10);

    buf[len + 1] = NUL;

    return(buf);

    }

    > whatluo wrote:
    > > Hi, all
    > >
    > > I'm now working on a program which will convert dec number to
    > > hex and oct and bin respectively, I've checked the clc but with no
    > > luck, so can anybody give me a hit how to make this done without
    > > strtol or s/printf function.
    > >
    > > Thanks,
    > >
    > > whatluo.
     
    W4CKO, Jun 10, 2005
    #5
  6. whatluo

    pete Guest

    Re: convert dec number to HEX and oct and bin without c library function

    W4CKO wrote:

    > Let me put this in the form of a function (tested):


    Tested? Really!?
    It only works right when val equals zero.
    The function definition is very bad.

    > /* assumes buffer is adequate. */
    >
    > #define NUL '\0'
    >
    > char *int2str(char *buf, unsigned int val) {
    >
    > unsigned int i, len = 0;
    >
    > if(val == 0) return("0");


    The interface is overly complicated.
    Unless the return value is used directly,
    it has to be stored in a separate variable.

    >
    > /* compute the length of the resultant string. */
    > for(i=val; i /= 10; len++);


    When val is 9, you get a length of zero.

    >
    > /* start at the end of the buffer, */
    > *buf = len;


    Writing a length to the first byte of buf, doesn't make sense.

    >
    > /* because we work backwards in the buffer. */
    > do {
    > *--buf = (val % 10) + '0';


    This takes you into memory you don't own,
    because you didn't increment buf first.
    That's a crasher.

    > } while(val /= 10);
    >
    > buf[len + 1] = NUL;
    >
    > return(buf);
    >
    > }


    That needed some work.

    #include <stddef.h>

    void int2str(char *buf, unsigned int val)
    {
    size_t i, len;

    if (val == 0) {
    *buf++ = '0';
    *buf = '\0';
    return;
    }
    /* compute the length of the resultant string. */
    for (len = 1, i = val; (i /= 10) != 0; len++) {
    ;
    }
    /* start at the end of the buffer, */
    buf += len;
    *buf = '\0';
    /* because we work backwards in the buffer. */
    do {
    *--buf = (char)(val % 10 + '0');
    val /= 10;
    } while(val != 0);
    }

    --
    pete
     
    pete, Jun 10, 2005
    #6
  7. whatluo

    Malcolm Guest

    "whatluo" <> wrote
    > I'm now working on a program which will convert dec number to
    > hex and oct and bin respectively, I've checked the clc but with no
    > luck, so can anybody give me a hit how to make this done without
    > strtol or s/printf function.
    >

    Convert to and from binary, i.e. the machine representation. That way you
    need two functions for each base you support, instead of N-squared
    conversions.

    To convert from decimal to an integer, take the first digit, and convert
    from an ASCII value to the number the character represents. The check is
    there is another digit. If there is, multiply by ten, convert the next
    digit, and add.

    You can convert from all other number bases using similar logic.

    Converting from an integer to an arbitrary base is not very efficient. You
    need to take modulus ten for the last digit, divide by ten, take modulus ten
    for the second to last digit, and so on. So a reverse string function is
    very handy.

    However when the base is a power of two, things are much easier.

    1111 0010 in binary is
    F 2 in hex.

    As simple as that. So you can use the AND and OR operators with bitshifting
    to convert without any divides.
     
    Malcolm, Jun 10, 2005
    #7
  8. whatluo

    whatluo Guest

    Re: convert dec number to HEX and oct and bin without c library function

    Thanks everyone for the info, that's help me a lot, and I know how to
    make it done, It's not a homework, just I'm writing a embeded module
    which related to this.

    Thanks,

    huajian.
     
    whatluo, Jun 11, 2005
    #8
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Mike Wahler

    Re: convert hex to oct

    Mike Wahler, Apr 1, 2004, in forum: C++
    Replies:
    6
    Views:
    844
    Spid3r
    Apr 14, 2004
  2. Andrew Phillips

    Re: convert hex to oct

    Andrew Phillips, Apr 26, 2004, in forum: C++
    Replies:
    0
    Views:
    824
    Andrew Phillips
    Apr 26, 2004
  3. ^_^
    Replies:
    3
    Views:
    1,076
    Thomas Matthews
    Jan 9, 2004
  4. anne001
    Replies:
    1
    Views:
    484
  5. chirs
    Replies:
    3
    Views:
    168
    Dr John Stockton
    Dec 1, 2003
Loading...

Share This Page