atoi函数的实现(考虑不同进制、溢出)

  • Post author:
  • Post category:其他

atoi就是将ASCII码表示的字符转换为int型数据

对于该函数的实现要考虑以下方面:
1、输入字符串为NULL;
2、输入开始是否包含符号’+’、’-’;
3、输入的字符是否合法(是否为’0’~‘9’);
4、计算出的数值必须为unsigned int,才能判断是否溢出;
5、数据溢出的处理(上溢出时,反回最大正数;下溢出时,反悔最大负数);
6、输入的字符包含空格;
7、进制的考虑,考虑16进制和8进制,通过开头为0或0x判断;
8、对于不同进制的判断范围不同;
对8进制:01234567
对10进制:0123456789
对16进制:0123456789ABCDEF或0123456789abcdef

#include <iostream>
#include <cmath>
using namespace std;

#define SIZE 100

//没有区别输入0与\0
//只能对十进制数进行转换
//没有处理溢出
int _atoi_1(char* str)
{
    if (NULL == str)    //输入合法性检查
    {
        cout << "NULL input" << endl;
        exit(0);
    }
     
    int sign = 0;
    int IntNumber = 0;

    while (*str)
    {
        if (0 == sign)
        {
            if ('-' == *str)
            {
                sign = -1;
                ++str;
            }
            else if ('+' == *str)
            {
                sign = 1;
                ++str;
            }
            else if (*str >= '0' && *str <= '9')
            {
                sign = 1;  //不更新str
            }
            else
            {
                cout << "invalid input!" << endl;
                exit(0);
            }
        }
        else if (*str >= '0' && *str <= '9')
        {
            IntNumber = IntNumber * 10 + *str - '0';
            ++str;
        }
        else
        {
            cout << "invalid input!" << endl;
            exit(0);
        }
    }

    return (sign * IntNumber);
}



//加上溢出处理
//并可对10进制、16进制以及8进制转换
//状态标志
bool IsNotNULL = true;
bool IsDigit = true;
bool IsNotOverflow = true;

int IsOverflow(unsigned long int IntNumber, int sign)
{
    unsigned long int MaxPositive = (long int)pow((float)2, (int)(8 * sizeof(long int) - 1)) - 1;

    if ((sign == 1) && !(IntNumber >= 0 && IntNumber <= MaxPositive))   //判断是否溢出
    {
        IsNotOverflow = true;
        return 1;
    }

    if ((sign == -1) && !(IntNumber > 0 && IntNumber <= (MaxPositive + 1)))   //判断是否溢出
    {
        IsNotOverflow = true;
        return -1;
    }

    return 0;
}

long int _atoi_2(char* str)
{
    if (NULL == str)
    {
        IsNotNULL = false;
        return 0;
    }

    int sign = 0;
    unsigned long int MaxPositive = (long int)pow((float)2, (int)(8 * sizeof(long int) - 1)) - 1;
    unsigned long int IntNumber = 0;   //要表示最小负数,须用unsigned long int,若用long int,其范围为-2^31到2^31 -1,不能表示2^31
    unsigned int base = 0;

    while (*str)
    {
        while (' ' == *str || '\t' == *str)     //忽略前导的空格或TAB
            ++str;

        if (0 == sign)  //判断数值的符号
        {
            if ('+' == *str)
            {
                sign = 1;
                ++str;
            }
            else if ('-' == *str)
            {
                sign = -1;
                ++str;
            }
            else if (isdigit(*str))
            {
                sign = 1;
            }
        }
        else
        {
            if (isdigit(*str))
            {
                if (0 == base)    //判断数值的进制
                {
                    if ('0' == *str && ('x' == *(str + 1) || 'X' == *(str + 1)))
                    {
                        base = 16;
                        str = str + 2;
                    }
                    else if ('0' == *str && !('x' == *(str + 1) || 'X' == *(str + 1)))
                    {
                        base = 8;
                        str = str + 1;
                    }
                    else
                    {
                        base = 10;   //不更新str
                    }
                }
                else
                {
                    IntNumber = IntNumber * base + *str - '0';

                    if (IsOverflow(IntNumber, sign) == 1)
                    {
                        return MaxPositive;
                    }

                    if (IsOverflow(IntNumber, sign) == -1)
                    {
                        return -((MaxPositive + 1));
                    }

                    ++str;
                }
            }
            else
            {
                IsDigit = false;
                return 0;
            }
        }
    }

    return (sign * IntNumber);   //如果为空串,也即第一个字符即为\0,返回值为0
}

//对不同的进制,判断的范围不同
//对16进制0123456789ABCDEF
//对8进制01234567
//对10进制0123456789
long int _atoi_3(char* str)
{
    if (NULL == str)    //输入合法性检查
    {
        IsNotNULL = false;
        return 0;
    }

    int sign = 0;
    unsigned long int IntNumber = 0;   //要表示最小负数,须用unsigned long int,若用long int,其范围为-2^31到2^31 -1,不能表示2^31
    unsigned long int MaxPositive = (long int)pow((float)2, (int)(8 * sizeof(long int) - 1)) - 1;
    unsigned int base = 0;

    while (*str)
    {
        while (' ' == *str || '\t' == *str)     //忽略前导的空格或TAB
            ++str;

        if (0 == sign)  //判断数值的符号
        {
            if ('+' == *str)
            {
                sign = 1;
                ++str;
            }
            else if ('-' == *str)
            {
                sign = -1;
                ++str;
            }
            else if (isdigit(*str))
            {
                sign = 1;
            }
            else
            {
                IsDigit = false;
                return 0;
            }
        }
        else
        {
            if (0 == base)    //判断数值的进制
            {
                if ('0' == *str && ('x' == *(str + 1) || 'X' == *(str + 1)))
                {
                    base = 16;
                    str = str + 2;
                }
                else if ('0' == *str && !('x' == *(str + 1) || 'X' == *(str + 1)))
                {
                    base = 8;
                    str = str + 1;
                }
                else
                {
                    base = 10;   //不更新str
                }
            }
            else
            {
                if (10 == base)
                {
                    if (isdigit(*str))
                    {
                        IntNumber = IntNumber * base + *str - '0';
                        if (IsOverflow(IntNumber, sign) == 1)
                        {
                            return MaxPositive;
                        }

                        if (IsOverflow(IntNumber, sign) == -1)
                        {
                            return -((MaxPositive + 1));
                        }
                        ++str;
                    }
                    else
                    {
                        IsDigit = false;
                        return 0;
                    }
                }
                else if (16 == base)
                {
                    if (isdigit(*str) || (*str >= 'a' && *str <= 'f') || (*str >= 'A' && *str <= 'F'))
                    {
                        if (isdigit(*str))
                        {
                            IntNumber = IntNumber * base + *str - '0';
                        }
                        else if (*str >= 'a' && *str <= 'f')
                        {
                            IntNumber = IntNumber * base + *str - 'a' + 10;
                        }
                        else if (*str >= 'A' && *str <= 'F')
                        {
                            IntNumber = IntNumber * base + *str - 'A' + 10;
                        }

                        if (IsOverflow(IntNumber, sign) == 1)
                        {
                            return MaxPositive;
                        }

                        if (IsOverflow(IntNumber, sign) == -1)
                        {
                            return -((MaxPositive + 1));
                        }
                        ++str;
                    }
                    else
                    {
                        IsDigit = false;
                        return 0;
                    }
                }
                else
                {
                    if (*str >= '0' && *str <= '7')
                    {
                        IntNumber = IntNumber * base + *str - '0';
                        if (IsOverflow(IntNumber, sign) == 1)
                        {
                            return MaxPositive;
                        }

                        if (IsOverflow(IntNumber, sign) == -1)
                        {
                            return -((MaxPositive + 1));
                        }
                        ++str;
                    }
                    else
                    {
                        IsDigit = false;
                        return 0;
                    }
                }
            }
        }
    }

    return (sign * IntNumber);   //如果为空串,也即第一个字符即为\0,返回值为0
}

//测试程序
int main()
{
    char str[SIZE];

    cout << "size of type int is : " << sizeof(int) << endl;   //4
    cout << "size of type long int is : " << sizeof(long int) << endl;    //4
    cout << "size of type float is : " << sizeof(float) << endl;    //4
    cout << "size of type long double is : " << sizeof(long double) << endl;    //8
    /*char str[SIZE] = "100278";
    char str[SIZE] = "+1267
    char str[SIZE] = "-12";
    char str[SIZE] = "+";
    char str[SIZE] = "-";
    char str[SIZE] = "";
    char str[SIZE] = "z98";
    char str[SIZE] = "-9s8";*/

    //test _atoi_1...
    cout << "test _atoi_1..." << endl;
    cout << "please enter the string :" << endl;
    while (cin >> str)
    {
        cout << "the string is :" << str << endl;
        cout << "the int number is : " << _atoi_1(str) << endl;
        cout << "please enter the string :" << endl;
    }

    cin.clear();
    cin.sync();
    cout << endl;

    //test _atoi_2...
    cout << "test _atoi_2..." << endl;
    cout << "please enter the string :" << endl;
    while (cin >> str)
    {
        cout << "the string is :" << str << endl;
        cout << "the int number is : " << _atoi_2(str) << endl;
        cout << "please enter the string :" << endl;
    }

    cin.clear();
    cin.sync();
    cout << endl;

    //test _atoi_3...
    cout << "test _atoi_3..." << endl;
    cout << "please enter the string :" << endl;
    while (cin >> str)
    {
        cout << "the string is :" << str << endl;
        cout << "the int number is : " << _atoi_3(str) << endl;
        cout << "please enter the string :" << endl;
    }

    return 0;
}

参考文献


版权声明:本文为veneno_one原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。