Take the 2-minute tour ×
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 2

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. –  Fihop Mar 20 '13 at 18:32
    
@FihopZz, I edited my answer, I hope its understandable now (English is not my native language) –  MarcDefiant Mar 20 '13 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. :-). –  Fihop Mar 20 '13 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. –  MarcDefiant Mar 21 '13 at 6:48
    
Ooooh~, I see. Thanks so much –  Fihop Mar 21 '13 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!!!!!!! –  Fihop Mar 20 '13 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.