2016-12-02 5 views
0

Я пытаюсь создать свою личную функцию atoi, но я не работаю должным образом. Я не знаю почему.Почему моя функция atoi не работает?

void ft_putchar(char c) 
{ 
    write(1, &c, 1); 
} 

int ft_atoi(const char *str) 
{ 
    int i; 

    i = 0; 
    while (str[i] == 9 || str[i] == 32 || str[i] == 43 || str[i] == 45) 
     i++; 
    while (str[i] > 48 && str[i] < 57) 
    { 
     ft_putchar(str[i]); 
     i++; 
    } 
    return (0); 
} 

int main(void) 
{ 
    printf("%d", atoi("  2794ffafsaasf")); 
    printf("\n%d",ft_atoi("  2794fsffsf")); 

    return(0); 
} 

Я вроде как работает, но это не так. Это дает мне странный результат, когда он даже игнорирует «\ n». В результате он дает мне это.

272794 and a new line. 

только моя функция дает мне только номер 27.

EDIT:

Я создал новую программу. Но это все еще не работает. Он просто не может видеть цифры.

int ft_atoi(const char *str) 
{ 
    int i; 
    int n; 

    i = 0; 
    while (str[i] == '\t' || str[i] == ' ' || str[i] == '+' || str[i] == '-') 
     ++i; 
    n = i; 
    while (str[n] >= '0' && str[n] <= '9') 
    { 
      ++n; 
    } 
    return(str[n]); 
} 
+8

все я вижу ваша функция возврат 0 ..? – yano

+0

Отладка по строкам вы легко увидите свою ошибку в условиях IF. Возьмите отладчик. –

+3

Вы прошли через это с помощью отладчика? Кроме того, он считал очень плохой практикой использовать 9,48, .... say '\ t', '0' и т. Д. Используйте тот факт, что '' дает вам числовое значение этого символа, это упрощает код read – pm100

ответ

2

Ваш тест на цифры имеет неправильные границы. Вы тестируете str[i] > 48 && str[i] < 57, но 48 - порядковый номер для символа 0, а 57 - порядковый номер для 9. Это означает, что вы считаете от 1 до 8 включительно числовыми цифрами, и вы прекратите синтаксический анализ 2794fsffsf на 9, а не на первых f.

Изменение теста на str[i] >= 48 && str[i] <= 57 могло бы устранить проблему с ограничениями, но все равно будет меньше, чем самодокументирование. Для того, чтобы сделать это очевидным, что вы делаете для людей, которые не имеют таблицы ASCII запомнили, вы можете сделать:

while ('0' <= str[i] && str[i] <= '9') 

или, возможно, немного медленнее, но еще более очевидно с ctype.h:

while (isdigit(str[i])) 

Аналогичным образом можно заменить многие неочевидные тесты для простых порядковых значений с isspace(str[i]).

+2

Я бы предложил 'str [i]> = '0' && str [i] <= '9'' – e0k

+0

@ e0k: Хорошая точка. Добавлено это в (и упоминается с использованием 'isdigit' для полностью самодокументированных тестов). – ShadowRanger

+1

Существует также 'isspace()' для проверки пробела (что было бы предпочтительнее для проверки определенных значений ASCII). – e0k

0

Первое, что нужно игнорировать ведущие пробелы. Вы можете сделать это с i, как вы делаете, но это проще сделать, сдвинув начало строки вперед. Я предполагаю, что вы переопределяете стандартную библиотеку C как упражнение. Я не, поэтому я буду использовать ctype.h functions. Отрегулируйте, как вам нравится, базовый код остается тем же. Вероятно, вы должны написать свои собственные ft_isspace и ft_isdigit, а не жестко кодировать логику.

/* Move str to point at the first non-space character */ 
while(isspace(str[0])) { 
    str++; 
} 

Теперь нет необходимости в i держать свое место, вы можете просто работать с str[0] и это будет первый непробельным характер.


Далее мы должны найти и добавить наши цифры. Опять же, я буду использовать isdigit. Следуйте the advice in ShadowRanger's answer, если вы не можете использовать эту функцию.

Метод состоит в том, чтобы преобразовать каждый символ в цифру и добавить его в общую сумму. Поскольку мы читаем число слева направо, каждая новая цифра умножает существующую сумму на 10. Например, если бы у нас было 1234, это было бы ... 1 затем 10 + 2, затем 120 + 3, затем 1230 + 4.

int num = 0; 
while(isdigit(str[0])) { 
    int digit = str[0] - '0'; 
    num *= 10; 
    num += digit; 

    str++; 
} 

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

И, наконец, не забудьте вернуть номер!

return num; 

насчет отрицательных чисел? Нам нужно искать -, прежде чем мы проверим цифры, если там есть флип знак. Нам также нужно обрабатывать + и игнорировать его.

/* Assume it's positive. */ 
short sign = 1; 

/* Check for a sign. */ 
switch(str[0]) { 
    case '-': 
     sign = -1; 
     str++; 
     break; 
    case '+': 
     str++; 
     break; 
} 

И затем умножьте знак, чтобы перевернуть результат.

return sign * num; 
0

Ваш код пишет только цифры - и не все, как было указано передо мной (потому что она исключает '0' и '9', и они должны быть включены!) - в файл, идентифицированной 1 (что, может быть, стандартный вывод, я точно не помню ...) и возвращает 0 в качестве параметра printf. Мне кажется немного странным, у вас было только 27 распечатанных с вашей функцией, но это может быть окружением (?) Конкретным. (Я не тестировал его, поэтому он, возможно, не совсем работает, как я полагаю ...)

Я сделал свою версию atoi, надеясь, что смогу показать, с чего начать/:

int nvi9_atoi(const char *s) { 
    int n = 0, valid = 0, prev = 0; 
    while(1) {       // infinite loop 
    if (*s == '\0') break;   // if it is the end of the string, finish further processing 
    if (*s >= '0' && *s <= '9') { // check whether the current character is an ascii number 
     n *= 10;      // "move" all previous digits (eg. 1 -> 10, 43 -> 430); if n is 0, this has no effect 
     if (n >= 0) n += (*s - '0'); // if n is not negative, add the value of the last digit (here is ascii-number "conversion"!) 
     else n -= (*s - '0');   // if it is negative, the number should be substracted (note eg. if there was -10 so far, and the new number is 2, the new value should be -12, not -8) 
     if (n > 0 && !valid) {   // if n not 0, and there was no digits before it, check if there was a minus sign before 
     valid = 1;     // preventing more check 
     if (prev == '-') n *= -1; // makes n negative 
     } 
    } else if (valid) break;   // if there was numbers processed, but the current character is not a number, finish loop 
    prev = *s;      // store current character for minus sign checking of next loop 
    s++;        // move string pointer to the next character 
    } 
    return n;       // return the converted value 
} 

Он также не проверен, поэтому исправления/исправления/улучшения приветствуются!

Эта функция может обрабатывать только строки, такие как " sfg afg-65sd1g". В этом случае возвращаемое значение будет -65, потому что оно ищет первое число, а затем возвращается.