Home > database >  Why is my code converting the first number wrong to hexadecimal?
Why is my code converting the first number wrong to hexadecimal?

Time:07-14

I have this function which receives the number 894867 (nbr) and the length 16 (i). When I run this code, it writes =A793 instead of what it should write DA793.

void ft_transformers(int nbr, int i) {

    char num[100];
    int t;
    int temp;
    int j;

    temp = 0;
    t = 0;
    while (nbr != 0) {
        temp = nbr % i;
        if (num[t] < 10) {
            num[t] = temp   48; 
        } else {
            num[t] = temp   55; 
        }         
        nbr /= i;
        t  ;
    }

    j = t;
    while (j >= 0) {
        ft_putchar(num[j]);
        j--;
    }   
}

CodePudding user response:

There are multiple problems:

  • Instead of if (num[t] < 10), you should be testing if (temp < 10)

  • instead of hardcoding ASCII values such as 48 and 55, you should use character constants and expressions '0' and 'A' - 10

  • the final loop should decrement j before accessing the character in the array.

  • the behavior is undefined if i is 0, 1 or -1.

Here is a modified version:

void ft_transformers(int nbr, int base) {

    char num[100];
    int t;
    int j;

    if (base < 2 || base > 36)
        base = 10;

    t = 0;
    while (nbr != 0) {
        int temp = nbr % base;
        if (temp < 10) {
            num[t] = '0'   temp; 
        } else {
            num[t] = 'A'   (temp - 10); 
        }         
        nbr /= base;
        t  ;
    }

    j = t;
    while (j > 0) {
        j--;
        ft_putchar(num[j]);
    }
}

Note also these shortcomings:

  • the function will not output anything if the initial value of nbr is zero.

  • the function will not output digits if nbr is negative.

Here is an improved version:

void ft_transformers(int nbr, int base) {

    char num[100];
    int t;
    int j;
    int isneg;

    if (base < 2 || base > 36)
        base = 10;

    isneg = 0;
    t = 0;
    for (;;) {
        int temp = nbr % base;
        if (temp < 0) {
            isneg = 1;
            temp = -temp;
        }
        if (temp < 10) {
            num[t] = '0'   temp; 
        } else {
            num[t] = 'A'   (temp - 10); 
        }         
        t  ;
        nbr /= base;
        if (nbr == 0)
            break;
    }

    if (isneg) {
        ft_putchar('-');
    }
    j = t;
    while (j > 0) {
        j--;
        ft_putchar(num[j]);
    }
}

CodePudding user response:

Your code has two errors:

  • The condition num[t] < 10 is wrong. num[t] is uninitialized at that point. It should be temp < 10.
  • The initialization of the second loop j = t; is wrong. t ; is executed at the end of the first loop and nothing is written to num[t] after that before the second loop. It should be j = t - 1;.

Also using magic numbers like 48 and 55 should be avoided. They should be '0' and 'A' - 10 to make it more clear. (unless your code has chance to be used in environments where character sets that are not compatible to ASCII are used)

CodePudding user response:

There are at least three drawbacks in the function.

For starters instead of the while loop you have to use do-while loop. Otherwise if nbr initially is equal to 0 the function will have undefined behavior.

Secondly, in this if statement

if (num[t] < 10) {

you have to use the variable temp instead of num[t]

if ( temp < 10) {

After the while loop the variable t points to after the last digit of the number. So in the first iteration of this loop

j = t;
while (j >= 0) {
    ft_putchar(num[j]);
    j--;
} 

there will be outputted an indeterminate value.

T least you should write

j = t;
while (j != 0) {
    ft_putchar(num[--j]);
} 

Pay also attention to that your function ignores the sign of the original number.

And it is a bad idea to use magic numbers like for example 48 or 55.

The function can be declared the following way as it is shown in the demonstration program be.low.

#include <stdio.h>

void ft_transformers( int nbr, int base ) 
{
    if ( base < 2 || base >  36 )
    {
        printf( "%d\n", nbr );
    }
    else
    {
        char num[8 * sizeof( int )];

        int sign = nbr < 0;

        size_t i = 0;

        do
        {
            int digit = nbr % base;

            if ( sign ) digit = -digit;
            
            if ( digit <  10 )
            {
                digit  = '0';
            }
            else
            {
                digit = digit - 10   'A'; 
            }

            num[i  ] = digit;
        } while ( nbr /= base );

        if ( sign ) putchar( '-' );

        while ( i != 0 ) putchar( num[--i] );
        putchar( '\n' );
    }
}

int main( void )
{
    int nbr = 0;

    ft_transformers( nbr, 16 );

    nbr = 894867;

    ft_transformers( nbr, 16 );

    nbr = -894867;

    ft_transformers( nbr, 16 );
}

The program output is

0
DA793
-DA793

In this declaration of the character array

char num[8 * sizeof( int )];

instead of the number 8 (the number of bits in a character) you can use the constant CHAR_BIT like

char num[CHAR_BIT * sizeof( int )];

To do so you need to include the header <limits.h>.

  • Related