1

I have:

#include <unistd.h>

//can't use atoi
void    ft_putnbr(int nb)
{
    if (nb == -2147483648)
    {
        write(1, "-2147483648", 11);
    }
    if (nb > -2147483648 && nb < 0)
    {
        write(1, "-", 1);
        ft_putnbr(nb * -1);
    }
    if (nb >= 0 && nb < 10)
    {
        write(1, &nb, 1);
        return;
    }
    if (nb >= 10 && nb <= 2147483647)
    {
        ft_putnbr(nb / 10);
        ft_putnbr(nb % 10);
    }
}

int main(void)
{
    ft_putnbr(-2147483648);
    write(1, "\n", 1);
    ft_putnbr(-200);
    write(1, "\n", 1);
    ft_putnbr(-1);
    write(1, "\n", 1);
    ft_putnbr(0);
    write(1, "\n", 1);
    ft_putnbr(1);
    write(1, "\n", 1);
    ft_putnbr(9);
    write(1, "\n", 1);
    ft_putnbr(10);
    write(1, "\n", 1);
    ft_putnbr(11);
    write(1, "\n", 1);
    ft_putnbr(2147483647);
}

I get only the first condition but not anything else besides the "-" if I replace it with printf I do get them. But even if I add a new function like:

void print(char c)
{
    write(1, &c, 1);
}

and put:

print((char) nb);

I don't get anything still. Just by doing:

print(nb + 48);

Do I get the desired output. WHAT is going on?

Miguel M
  • 302
  • 3
  • 16
  • 2
    You really should be using `else if` rather than `if` for all of the checks after the first. – Tom Karzes Jul 13 '21 at 19:19
  • 2
    In any case, you need to understand the difference between `'0'` and `0`. They are not the same. Try doing `'0' == 0` and see what you get. You want to write `'0'` to your file, not `0`, and similarly for the other digits. `'0'` is a character code. `0` is an integer whose value corresponds to the null character. – Tom Karzes Jul 13 '21 at 19:20
  • 3
    This line `write(1, &nb, 1);` is writing a single byte on stdout but the byte is not encoded as a decimal digit. You need an array of chars ('0','1',...'9') that you index with `nb` and then `write(1, digitArray+nb, 1);` instead of what you're doing. If you pipe your existing command's output through `od`, then you'll better see what is being printed. – Jeff Holt Jul 13 '21 at 19:22
  • Does this answer your question? [Why is there a need to add a '0' to indexes in order to access array values?](https://stackoverflow.com/questions/60994353/why-is-there-a-need-to-add-a-0-to-indexes-in-order-to-access-array-values) – anastaciu Jul 13 '21 at 19:35
  • 1
    Problems with `0` vs. `'0'` aside, though, recursion is the coolest way to write `itoa`, which is essentially whats going on here. – Steve Summit Jul 13 '21 at 19:38
  • 1
    look at [this](https://upload.wikimedia.org/wikipedia/commons/thumb/1/1b/ASCII-Table-wide.svg/1200px-ASCII-Table-wide.svg.png) (ASCII table). you will find that (char)0 through (char)9 are actually used for formatting like backspace and tab etc or for special meanings like NULL. So, you will not see them as numbers. When you add 48, it's like saying ``0+'0'``` or 48 in the table, which is 0. To sum up, This table maps how chars look like, to how they are stored in memory – Mohamed Akram Jul 13 '21 at 19:39
  • You can think of `write` as being sort of like `printf("%c")`. And if you compare the behavior of `printf("%c%c%c%c", 0, 1, 2, 3)` with `printf("%c%c%c%c", '0', '1', '2', '3')`, you should see what's going on. – Steve Summit Jul 13 '21 at 19:41

1 Answers1

2

To print a character '0' to '9', code needs to add '0' to the value nb. Attempting to print the first byte of nb might access its least or most significant byte - depending on endian. IAC, it is not accessing a digit character: '0' to '9', but, at best, a value of 0 to 9. See Jeff Holt.

if (nb >= 0 && nb < 10) {
    // write(1, &nb, 1);
    char ch = nb + '0';  // Convert value to digit character.
    write(1, &ch, 1);
    return;
}

For fun, a C99 or later alternative simplification:

// Only pass value <= 0
static void ft_putnbr_helper(int nb) {
  if (nb <= -10) {
    ft_putnbr_helper(nb/10);
  }
  putchar('0' - nb%10);  // Go from value to digit character.
}

void ft_putnbr(int nb) {
  if (nb < 0) {
    putchar('-');
    ft_putnbr_helper(nb);
  } else {
    ft_putnbr_helper(-nb);
  }
}

Why use the negative side of int?
To avoid UB of -INT_MIN.

chux - Reinstate Monica
  • 143,097
  • 13
  • 135
  • 256