Реализация сделан вывод()


Как это решение можно усовершенствовать?

#include <limits.h>

void itoa(int n, char s[])
{
    int min_int = 0;
    int i, sign;
    if (INT_MIN == n) {
        min_int = 1;
        n++;
    }

    if ((sign = n) < 0)
        n = -n;
    i = 0;
    do {
        s[i++] = n % 10 + '0';
    } while ((n /= 10) > 0);

    if (sign < 0)
        s[i++] = '-';

    s[i] = '\0';

    if (min_int)
        s[0]++;

    reverse(s);
}


Комментарии
2 ответа

Я думаю, что я бы разорвать этот вверх на несколько отдельных подпрограмм, каждая из которых содержит одну более конкретную цель. Я думаю, что самый простой способ сделать это , вероятно, чтобы начать с учетом абсолютного значения входного сигнала (представленный как беззнаковый тип), что-то вроде этого:

unsigned iabs(int input) { 
if (input >= 0)
return (unsigned)input;
return (UINT_MAX - (unsigned)input)+1U;
}

Я считаю, что требования для перевода подписанного в unsigned гарантирует, что этого производить правильные результаты для всех входов (включая INT_MIN).

При том, что почти все остальное может справиться с беззнаковым числом. Лично я тоже предпочитаю генерировать результат для того, вместо создания в обратном порядке, затем отменить. Один довольно простой способ сделать это с помощью рекурсии, с каждым шагом первая генерирующая предыдущие цифры (если таковые имеются), затем добавив свои цифры до конца строки. Я бы рекурсивный интернет работает только с беззнаковым типом (как произведено выше). Конечно, как и почти все, что манипулирует данными в буфере в C, вы должны также передать максимальная длина буфера для его использования, чтобы предотвратить переполнение буфера. Ради общности, я также принимаю основой для преобразования в качестве параметра, а не всегда предполагается, что основание 10.

char *itoa_internal(char *buffer, size_t len, unsigned input, int base) { 
static const char digits[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
char *pos = buffer;
if (input >= base)
pos = itoa_internal(buffer, len, input/base, base);

if (pos-buffer < len-1)
*pos++ = digits[input % base];
return pos;
}

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

char *itoa(char *buffer, size_t len, int input, int base) {
char *pos = buffer;

if (base < 2 || base > 36 || len < 1)
return NULL;

if (input < 0)
*pos++ = '-';

pos = itoa_internal(pos, len, iabs(input), base);
*pos = '\0';
return buffer;
}

Это должно также сделать это довольно тривиально, чтобы написать utoa , который обрабатывает неподписанных входы-как был сделан вывод без кода, чтобы справиться с отрицательными числами. Как мелкие доработки, я бы, наверное, тоже сделать Иябс и itoa_internal статические функции, чтобы минимизировать шансы их мешать с другими именами.

6
ответ дан 22 ноября 2011 в 05:11 Источник Поделиться

Просто некое общее представление о коде (без каких-либо усилий для создания лучшего алгоритма).

Во-первых, я согласен с @Джефф, если есть библиотеки, которые используют его. Вы не должны поддерживать его и все будут знать, что код делает.

Так, код. Я хотел бы использовать более длинные имена переменных:

void itoa(int number, char result[])

int i, sign;

Я предпочитаю одно объявление на каждую линию, потому что его легче читать и находить тип переменных.

if ((sign = n) < 0)

Это выглядит здорово, но трудно поддерживать. Просто некоторые вопросы:


  • Зачем это здесь?

  • Это умышленно = (а не ==)?

  • Почему не в линию перед?

Если вам придется поддерживать этот код такого рода вопрос может быть больно. Поэтому, я бы написал

sign = number;
if (number < 0) ...

Вопросы в цикл while:

do { 
...
} while ((n /= 10) > 0);

Я бы написал:

do { 
...
n /= 10;
} while (n > 0);

Наконец, я думаю, что есть потенциальные переполнения буфера, если абонент проход слишком мал char массив в функцию.

5
ответ дан 21 ноября 2011 в 10:11 Источник Поделиться