Home > Blockchain >  How to convert a negative decimal number to octal base without any helping funtions
How to convert a negative decimal number to octal base without any helping funtions

Time:08-17

I'm implementing the printf function and now am stuck at the conversion of the negative base 10 number into a base 8 octal number, below i placed the piece of code which is working just fine in regard to converting a positive decimal number to octal just like the printf

my ft_printf => 15 octal => 017

original printf => 15 octal => 017

but regarding the negative numbers:

my ft_printf => -15 octal => 0-17

original printf => -15 octal => 037777777761

what should i modify with my function in order for it to print the negative numbers just like the printf does thank you!!!

void    process_octal(unsigned int n)
{
    char    *str;
    int     oct = 0;
    int     rem = 0;
    int     place = 1;

    while (n)
    {
        rem = n % 8;
        oct = oct   rem * place;
        n = n / 8;
        place = place * 10;    
    }
    str = ft_itoa(oct);
    ft_putstr_fd(str, 1);
}

CodePudding user response:

Here is a very simple function to convert number to any base (limited to the number of available digit symbols).

char *reverse(char *ptr, size_t length)
{
    char *str = ptr;
    if(ptr && length)
    {
        char *end = ptr   length - 1;
        while(end > str)
        {
            char tmp = *str;
            *str   = *end;
            *end-- = tmp;
        }
    }
    return ptr;
}


char *convert(char *buff, long long val, unsigned base)
{
    const char digits[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVXYZ";
    int negative = val < 0;
    size_t count = 0;

    if(base < 2 || base > sizeof(digits) - 1) return NULL;

    do
    {
        buff[count  ] = digits[abs(val % base)];
        val /= base;
    }while(val);
    if(negative) buff[count  ] = '-';
    buff[count] = 0;
    return reverse(buff, count);
    
}

https://godbolt.org/z/Wz15h4x41

After OPs comment:

function which will print signed or unsigned representation of the value depending on the asUnsigned parameter:

char *convert(char *buff, long long val, unsigned base, int asUnsigned)
{
    const char digits[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVXYZ";
    int negative = val < 0;
    size_t count = 0;

    if(base < 2 || base > sizeof(digits) - 1) return NULL;

    do
    {
        buff[count  ] = digits[asUnsigned ? ((unsigned)val) % base : abs(val % base)];
        val = (asUnsigned ? (unsigned)val : val) / base;
    }while(val);
    if(!asUnsigned && negative) buff[count  ] = '-';
    buff[count] = 0;
    return reverse(buff, count);
    
}

https://godbolt.org/z/MdMGerTTs

int main(void) {
    char str[32];
    printf("%s\n", convert(str, -15, 8, 1));  
    printf("%s\n", convert(str, -15, 8, 0));  

}

Result:

37777777761
-17

CodePudding user response:

I'm implementing the printf function and now am stuck at the conversion of the negative base 10 number into a base 8 octal number

This implies OP is incorrectly getting the argument.

With "%o", "%x", "%X", "%u", the corresponding argument is type unsigned, not int.

With a proper printf(), there is no printing of a signed integer with specifiers oxXu.

Code attempting to pass a negative integer to match a oxXu results in undefined behavior (UB). A common UB is to treat the signed argument as if it was unsigned.

  •  Tags:  
  • c
  • Related