Хорошо, есть хотя бы одна проблема с вашей функцией 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;
}
atoi
является частью стандартной библиотеки C, с подписью int atoi(const char *);
.
Вы заявляете, что функция с таким именем существует, но выдает ей другой тип возвращаемого значения. Обратите внимание, что в C имя функции является единственным, что имеет значение, и набор инструментов может доверять только тому, что вы говорите в исходном коде. Если вы врете компилятору, как здесь, все ставки сняты.
Вы должны выбрать другое имя для собственной реализации, чтобы избежать проблем.
Как пишет @pmg, стандарт C (ссылка на C99.7.1.3 ) говорит, что использование имен из стандартной библиотеки C для ваших собственных глобальных символов (функций или глобальных переменных) явно Неопределенное поведение . Остерегайтесь носовых демонов!
Слишком поздно, но может помочь. Я сделал для базы 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);
}
Ваша функция имеет бесконечный цикл: поскольку 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()
, который вы могли бы использовать для реализации своей функции, обрабатывает пробелы и необязательный знак, хотя преобразование отрицательных значений может дать удивительные результаты.