面试题 49,atoi 字符串转化为整数的实现(考察edge case的典型题) [LeetCode]

面试题49是一道案例分析题,里面模拟了考官和应聘者的全部面试过程和考官心理活动。

案例中的重头戏就是atoi 字符串转化为整数的实现。

这道题因为边界情况比较多,所以很常见,我也曾经被考过,当时回答得并不理想。

做这道题的关键是要事先和面试官多沟通,在各种边界处理上达成一致。再开始写代码。

现在罗列出要考虑的边界问题:

(1) NULL输入。

(2) 非法字符输入(如果只考虑十进制,除了正负号和数字,其他都是非法输入,若还要考虑十六进制,需要判断第二个字符是不是'X')。

(3) 只有一个正负号的输入。

(4) 空字串“”输入。

(5) 非法输入后返回值如果规定为0,如何区分正常的‘0’输入和异常输入的结果 (需要定义全局异常变量,若检测出异常,则给其设置值,这也是C++中异常处理的一种典型方式)。

(6) 溢出处理,输入的字符串已经超出int表示范围[-231-1, 231] [0x80000000, 0x7FFFFFFF]。

 自己实现的代码:

#include <stdio.h>

enum Status {kValid = 0, kInvalid};
int g_nStatus = kValid;

long long atoiCore(const char* s){
    long long res = 0;
    const char *p = s;
    int size = 0;
    bool sign = false;
    if(*s == '+' || *s == '-') p++;
    for(; *p != '\0'; p++){
        if(*p < '0' || *p > '9'){
            g_nStatus = kInvalid;
            return 0;
        }
        if(*s == '-'){
            res = (res * 10 - (*p - '0'));
            if((res * -1) > 0x80000000){
                g_nStatus = kInvalid;
                return 0;
            }
        }else{
            res = (res * 10 + (*p - '0'));
            if(res > 0x7FFFFFFF){
                g_nStatus = kInvalid;
                return 0;
            }
        }
        
    }
    return res;
}
int custAtoi(const char* s){
    g_nStatus = kValid;
    if(NULL == s || '\0' == *s){
        g_nStatus = kInvalid;
        return 0;
    }
    if(s[1] == '\0' && (*s == '+' || *s == '-')){
        g_nStatus = kInvalid;
        return 0;
    }
    long long res = atoiCore(s);
    return (int)res;
}

// ====================测试代码====================
void Test(char* string)
{
    int result = custAtoi(string);
    if(result == 0 && g_nStatus == kInvalid)
        printf("the input %s is invalid.\n", string);
    else
        printf("number for %s is: %d.\n", string, result);
}

int main()
{
    Test(NULL);

    Test("");

    Test("123");

    Test("+123");
    
    Test("-123");

    Test("1a33");

    Test("+0");

    Test("-0");

    //有效的最大正整数, 0x7FFFFFFF
    Test("+2147483647");    

    Test("-2147483647");

    Test("+2147483648");

    //有效的最小负整数, 0x80000000
    Test("-2147483648");    

    Test("+2147483649");

    Test("-2147483649");

    Test("+");

    Test("-");

    return 0;
}

 

LeetCode上也有这一题,不过要求的细节上有一点不同。

(1) 如果最后结果越界,给出边界值,比如:如果结果比 int 的下限小,则返回int的下限。

(2) 如果含有非法字符,则输出当前已经计算出的值,也就是说,非法字符后面的字符串不考虑了,但是之前的字符串依然转化为数输出。

(3) 如果字符串开始有空格,略去空格。

能通过的代码:

class Solution {
public:
    int atoi(const char *str) {
        if(str == NULL) {status = 0; return 0;}
        while(*str == ' ') ++str;
        bool negative = false;
        if(*str == '-' || *str == '+'){
            if(*str == '-') negative = true;
            ++str;
            if(*str == '\0'){ status = 0; return 0;}
        }
        long long res = 0; int len = 0; //len is used to stop calculating if str is a too big number.
        for(; *str != '\0' && len <= 10; ++str){
            if(!(*str <= '9' && *str >= '0')) { status = 0; break;}
            if(*str != '0' || len > 0) ++len;
            res = res*10 + (*str - '0');
        }
        res = negative ? 0 - res : res;
        if(res > 0x7FFFFFFF) { status = 0; res = 0x7FFFFFFF;}
        if((res * -1) > 0x80000000) { status = 0; res = 0 - 0x80000000;}
        return (int)res; 
    }
private:
    int status = 1;
};

 

 

posted on 2014-03-13 10:32  Felix Fang  阅读(319)  评论(0)    收藏  举报

导航