Некорректно выводится строка в процедуре

Программа переводит число из троичной системы счисления в десятичную. Не понимаю, почему printf в void неправильно работает. Вроде бы строка успешно считывается, а сам num высчитывается неверно. Буду признателен за помощь.

void three(char* s) {
    int num = 0;
    char result[9];
    for (unsigned int i = 0; i < strlen(s); i++) {
        int digit = s[i] - '0';
        num += digit * pow(3, strlen(s) - i - 1);
    }
    sprintf(result, "%d", num);
    printf("%s", result);
}


int main() {
    char str[9];
    fgets(str,9,stdin);
    three(str);
}


Ответы (1 шт):

Автор решения: Stanislav Volodarskiy

fgets читает строку вместе с переводом строки. Если вы читаете 1212, то получаете такие коды символов в строке s:

символы '1'  '2'  '1'  '2' '\n' '\0'
коды     49   50   49   50  10   0
цифры    1    2    1    2  -38

Последняя цифра со странным значением -38 портит результат.

Поменяйте способ чтения данных чтобы исключить перевод строки. Лучше читать не строку, в которую могут попасть пробелы и в которую попадает перевод строки, а слово до следующего пробельного символа. Замените fgets(str,9,stdin); на scanf("%8s", str);.

P.S.

  • Если читаете в фиксированный буфер, то берите буфер с запасом. Девять символов мало, сто символов - нормально.

  • strlen в условии цикла - плохо. Он вычисляется в каждой итерации цикла, и вычисляется проходом по всей строке.

  • Не нужно использовать pow в этой задаче. Она не обязана считать степени точно для целочисленных аргументов. Небольшая ошибка приведёт к неправильному чтению числа.

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

#include <stdio.h>

unsigned parse(const char *s) {
    unsigned n = 0;
    for (const char *p = s; *p != '\0'; ++p) {
        n = 3 * n + (unsigned)(*p - '0');
    }
    return n;
}

int main() {
    char s[100];
    while (scanf("%99s", s) == 1) {
        printf("%u\n", parse(s));
    }
}
→ Ссылка