Я не понимаю itoa () в книге K & R - PullRequest
5 голосов
/ 02 октября 2009

Я читаю K & R; пока у меня все хорошо, но в функции itoa() есть что-то, чего я не понимаю. Здесь, в itoa(), они говорят, что сами меняют числа. Например, 10 - 01 (они переворачивают строку):

void itoa(int n, char s[])
{
    int i, sign;
    if ((sign = n) < 0) /* record sign */
        n = -n; /* make n positive */
    i = 0;
    do { /* generate digits in reverse order */
        s[i++] = n % 10 + '0'; /* get next digit */
    } while ((n /= 10) > 0); /* delete it */
    if (sign < 0)
        s[i++] = '-';
    s[i] = '\0';
    reverse(s);
    return;
}

Я не понимаю, как это изменило число. Даже если мы просто делаем n % 10 + '0', то следующая цифра, которая удаляется 10, затем 1, затем идет к 0, верно? Или я не понимаю его логики?

Ответы [ 3 ]

12 голосов
/ 02 октября 2009

В цикле do-while он вытягивает числа сзади (сначала младшая цифра). Итак, если у вас есть число -123456789, оно обрабатывает 9, затем 8, затем 7 и т. Д.

Таким образом, когда он попадает в нулевой терминатор (с третьей по последнюю строку), у вас будет «987654321-», который затем переворачивается.

2 голосов
/ 02 октября 2009

n % 10 дает 0 для n = 10, поэтому после цикла строка s содержит 01.

Звонок на reverse() исправляет это.

0 голосов
/ 03 октября 2009

Алгоритм определяет цифры от наименьшего до наиболее значимого порядка. Поскольку общее количество сгенерированных цифр заранее неизвестно, правильная позиция не может быть определена, поскольку они генерируются - наименее значащая цифра будет в конце, но «конец» неизвестен. Таким образом, они буферизуются в порядке их вычисления (обратный), а затем вся строка переворачивается, чтобы исправить порядок.

Один из способов избежать этого - заранее определить длину:

decimal_digits = (int)log10( n ) + 1 ;

но на устройствах без FPU (и на некоторых с очень простыми FPU), которая, вероятно, будет более сложной задачей, чем обращение строк.

...