My C language Solution with too many if-else. Whether I can reduce these if statements?


  • 0
    N
    #define isDigit(c)  ( c >= '0' && c <= '9')
    
    int myAtoi(char* str) {
        int len = strlen(str);
        bool minus = false;
        int idx = 0;
    
        while(idx < len)
        {
            if(str[idx] != ' ')
            {
                break;
            }
            else
            {
                idx++;
            }
        }
        
        if(idx == len)
        {
            return 0;
        }
        
        if( str[idx] == '-')
        {
            minus = true;
            idx++;
        }
        else if(str[idx] == '+')
        {
            idx++;
        }
        else if(!isDigit(str[idx]))
        {
            return 0;
        }
        
        int tmp ;   
        int result = 0;
        while(idx < len && isDigit(str[idx]))
        {
            tmp = str[idx++] - '0';
            if(minus)
            {
                if( result < ( (INT_MIN +  tmp) / 10 ))
                {
                    return  INT_MIN ;
                }
                result = result * 10 - tmp;
            }
            else
            {
                if( result > ( (INT_MAX -tmp) / 10 ))
                {
                    return  INT_MAX;
                }
                result = result * 10 + tmp;
            }
        }
        return result;
    }

  • 0
    C

    There are many tricks in plain-old null-terminated strings that you can make use of in cases like this. You can access the c_string of the string as :

    const char* cstr = str.c_str();
    

    For example your code for skipping white spaces before any other character is:

    while(idx < len)
    {
        if(str[idx] != ' ')
        {
            break;
        }
        else
        {
            idx++;
        }
    }
    

    can be reduced to

    while (*cstr && (*cstr==' ' || *cstr=='\t')) ++cstr; // skip white space
    

    Sign comprehension in your code is

    if( str[idx] == '-')
    {
        minus = true;
        idx++;
    }
    else if(str[idx] == '+')
    {
        idx++;
    }
    

    I would suggest something like this to get the sign and advance the pointer at the same time.

    if (*cstr=='-' || cstr=='+')
         negative = *cstr++ =='-' ? true: false;
    

    No need to detect the first character after the sign as a special case.

    else if(!isDigit(str[idx]))
    

    Since you are starting with result = 0; it can be naturally handled by the following loop.



    Here is the best part ;) ... No need to handle sign within the loop which construct the integer. Making the integer without the sign is clearer. A condition like below let you construct the integer value without worrying about it's sign and hence the overflow condition.

    while (*cstr &&                      // while there is more
           *cstr>='0' && *cstr<='9' &&    // numbers from 0~9
           res< (long)INT_MAX+1)       // without result overflowing
    

    Since you want to increment the cstr pointer if this condition holds and keep building the number you might as well use a for loop instead.

    for (;
          *cstr &&                      // while there is more
          *cstr>='0' && *cstr<='9' &&  // numbers from 0~9
          res< (long)INT_MAX+1       // without result overflowing
         ; ++cstr)
      res = res*10 + *cstr - '0' ;
    

    Finally you are left to apply the sign and clamp the result to INT_MIN and INT_MAX if it's out of range. There is no way around these without if-else but ternary operator looks elegant and quite readable too.

    res = negative ? -res: res;       // apply sign
    return res > INT_MAX ? INT_MAX :  // clamp on to MIN, MAX boundaries
           res < INT_MIN ? INT_MIN : res ;
    

    You can find my complete solution here

    Hope you learned some tricks with c-style strings ! ;)


Log in to reply
 

Looks like your connection to LeetCode Discuss was lost, please wait while we try to reconnect.