Tell me more ×
Code Review Stack Exchange is a question and answer site for peer programmer code reviews. It's 100% free, no registration required.

Implement atoi to convert a string to an integer.

Requirements for atoi: The function first discards as many whitespace characters as necessary until the first non-whitespace character is found. Then, starting from this character, takes an optional initial plus or minus sign followed by as many numerical digits as possible, and interprets them as a numerical value.

The string can contain additional characters after those that form the integral number, which are ignored and have no effect on the behavior of this function.

If the first sequence of non-whitespace characters in str is not a valid integral number, or if no such sequence exists because either str is empty or it contains only whitespace characters, no conversion is performed.

If no valid conversion could be performed, a zero value is returned. If the correct value is out of the range of representable values, INT_MAX (2147483647) or INT_MIN (-2147483648) is returned.

The following is my code:

int atoi(const char *str) {
    int sign = 1;
    long long i = 0, j = 0;

    while ((*str) != '\0' && isspace(*str)) {
        ++str;
    }

    if (((*str)!='\0') && ((*str) == '+' || (*str) == '-')) {
        if ((*str) == '-') {
            sign = -1;
        }
        ++str;
    }

    if (((*str) != '\0') && (!isdigit(*str))) {
        return 0;
    }

    while (((*str) != '\0') && (isdigit(*str))) {
        i = i * 10 + (*str - '0');
        j = i * sign;
        cout << j << endl;
        if (j > INT_MAX) {
            return INT_MAX;
        }
        if (j < INT_MIN) {
            return INT_MIN;
        }

        ++str;
    }

    return j;
}
share|improve this question

2 Answers

up vote 2 down vote accepted
if (((*str) != '\0') && (!isdigit(*str))) {
    return 0;
}

You don't need this condition, because of the condition in the while loop afterwards. If that fails the first time j with value 0 is returned anyway.

And a minimal (and maybe unnecessary) optimization:

if (j >= INT_MAX) {
    return INT_MAX;
}
if (j <= INT_MIN) {
    return INT_MIN;
}

Why look for the next character in the string which would only get appended to the number and would increase the value, if the number already has the maximumk/minimum value possible (INT_MAX/INT_MIN).

share|improve this answer
Why look for the next character which only makes the number bigger if you already reached INT_MAX/INT_MIN? Can you explain this sentence more detail. I don't understand. – FihopZz Mar 20 at 18:32
@FihopZz, I edited my answer, I hope its understandable now (English is not my native language) – Mogria Mar 20 at 19:17
If the number already has the maximum/minimum value, which is checked by if (j >= INT_MAX) and if (j <= INT_MIN) in my code, there is no necessary to check the next character. It seems that this is what I do. :-). – FihopZz Mar 20 at 22:40
In your code you return if j > INT_MAX, but you don't return if j is already equal to INT_MAX, so better IMO would be returning if j >= INT_MAX like I suggested. – Mogria Mar 21 at 6:48
Ooooh~, I see. Thanks so much – FihopZz Mar 21 at 12:38

You seem to have too many checks for '\0'. They don't add anything. Also too many brackets, but better too many than too few.

Also, is long long guaranteed to be bigger than int? I don't think it is. Here's another version that doesn't need a bigger representation than that of int:

int atoi(const char *str)
{
    int n = 0;
    int sign = 1;

    while (isspace(*str)) {
        ++str;
    }
    if (*str == '-') {
        sign = -1;
        ++str;
    } else if (*str == '+') {
        sign = 1;
        ++str;
    }
    while (isdigit(*str)) {
        if (n > INT_MAX/10) { /* EDIT: protect against overflow */
            break;
        }
        n *= 10;
        int ch = *str - '0';

        if (n > INT_MAX - ch) {
            break;
        }
        n += ch;
        ++str;
    }
    if (isdigit(*str)) {
        return sign == 1 ? INT_MAX : INT_MIN;
    }
    return sign * n;
}

EDIT: I added a check to prevent overflow of the n *= 10

EDIT2: improved to avoid using an unsigned int - it was a hack

share|improve this answer
very nice!!!!!!! – FihopZz Mar 20 at 19:01

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.