Преобразование строковой константы в числовое значение с использованием C

1
задан Rai 7 March 2019 в 13:12
поделиться

4 ответа

Хорошо, есть хотя бы одна проблема с вашей функцией atoi.
Вы зацикливаетесь на значении без знака и проверяете, больше ли оно равно нулю, что должно быть недостаточным.

Самым простым исправлением является смещение индекса, т. Е.

unsigned long long int my_atoi(const char str[]) {
    unsigned long long int i, j, power, num = 0;
    for (i = strlen(str); i != 0; --i) {
        power = 1;
        for (j = 0; j < strlen(str) - i; ++j) {
            power *= 10;
        }
        num += (str[i-1] - '0') * power;
    }
    return num;
}
0
ответ дан NotT90 7 March 2019 в 13:12
поделиться

atoi является частью стандартной библиотеки C, с подписью int atoi(const char *);.

Вы заявляете, что функция с таким именем существует, но выдает ей другой тип возвращаемого значения. Обратите внимание, что в C имя функции является единственным, что имеет значение, и набор инструментов может доверять только тому, что вы говорите в исходном коде. Если вы врете компилятору, как здесь, все ставки сняты.

Вы должны выбрать другое имя для собственной реализации, чтобы избежать проблем.


Как пишет @pmg, стандарт C (ссылка на C99.7.1.3 ) говорит, что использование имен из стандартной библиотеки C для ваших собственных глобальных символов (функций или глобальных переменных) явно Неопределенное поведение . Остерегайтесь носовых демонов!

0
ответ дан hyde 7 March 2019 в 13:12
поделиться

Слишком поздно, но может помочь. Я сделал для базы 10, если вы меняете базу, вам нужно позаботиться о том, как вычислить цифру 0 в *p-'0'.

Я бы использовал правило Хорнера для вычисления значения.

#include <stdio.h>
void main(void)
{
  char *a = "5363", *p = a;
  int unsigned base = 10;
  long unsigned x = 0;
  while(*p) {
    x*=base;
    x+=(*p-'0');
    p++;
  }
  printf("%lu\n", x);
}
0
ответ дан alinsoar 7 March 2019 в 13:12
поделиться

Ваша функция имеет бесконечный цикл: поскольку i не имеет знака, i >= 0 всегда верно.

Его можно улучшить различными способами:

  • Вы должны вычислить длину str только один раз. strlen() не дешево, он должен сканировать строку, пока не найдет нулевой терминатор. Компилятор не всегда способен оптимизировать избыточные вызовы для одного и того же аргумента.

  • power можно вычислять постепенно, избегая необходимости во вложенном цикле.

  • Вы не должны использовать имя atoi, так как это стандартная функция в библиотеке C. Если вы не реализуете его спецификацию точно и правильно, вы должны использовать другое имя.

Вот исправленная и улучшенная версия:

unsigned long long int atoi_power(const char str[]) {
    size_t i, len = strlen(str);
    unsigned long long int power = 1, num = 0;
    for (i = len; i-- > 0; ) {
        num += (str[i] - '0') * power;
        power *= 10;
    }
    return num;
}

Измененная таким образом, функция должна иметь производительность, аналогичную версии atoi_imp. Обратите внимание, что они не реализуют одну и ту же семантику. atoi_pow должна быть задана строка из цифр, тогда как atoi_imp может содержать завершающие символы.

Фактически, ни atoi_imp, ни atoi_pow не реализуют спецификацию atoi, расширенную для обработки больших целых чисел без знака:

  • atoi игнорировали любые ведущие пробельные символы, [ 1125]
  • atoi принимает необязательный знак: '+' или '-'.
  • atoi потребляет все последующие десятичные цифры, поведение при переполнении не определено.
  • atoi игнорирует и завершает символы, которые не являются десятичными цифрами.

Учитывая эту семантику, естественной реализацией или atoi является реализация atoi_imp с дополнительными тестами. Обратите внимание, что даже strtoull(), который вы могли бы использовать для реализации своей функции, обрабатывает пробелы и необязательный знак, хотя преобразование отрицательных значений может дать удивительные результаты.

0
ответ дан chqrlie 7 March 2019 в 13:12
поделиться
Другие вопросы по тегам:

Похожие вопросы: