LeetCode Brushing Notes 08 String to integer

Author: Ma Zhifeng
link: https: //zhuanlan.zhihu.com/p/24047577
Source: know almost
copyrighted by the author. For commercial reprints, please contact the author for authorization. For non-commercial reprints, please indicate the source.

link

leetcode.com/problems/s

topic

Realize atoi, convert string to integer

Paraphrase

The focus of this question is to consider what possible situations

  1. How to deal with non-digit characters
  2. Sign
  3. overflow

Of course, the idea is definitely to process each character in the string, so how to turn the character '1' into the number 1?

Brother Xiao Ma is rather stupid, I didn't expect it after thinking for a long time

I thought it might be related to the ASCII table, but I couldn't study it in depth, and finally peeked at the answer. . .

You are blessed, if you don’t expect it, you don’t need to read the answer anymore, I will tell you

'1' - '0' = 1;

Yes, just subtract from the character 0. Because they are continuous in the table

Okay, the key problem is solved, let’s take a look at how to deal with a few special cases

  1. For non-digit characters, we can ignore the empty characters at the beginning and the end ("23"). If there are other characters ("123x21") in the middle of the number, it is considered illegal input.
  2. Sign, need to be saved
  3. Overflow, we still have the method of the previous topic, use long long to deal with

Supplementary description

We can write some test cases based on the supplementary description of the topic:

  1. “ 123 ” → 123
  2. “ -123 “ → -123
  3. “ 123x456 “ → 123
  4. “ 123 456” → 123
  5. “343485894858938553” → INT_MAX
  6. “” → 0
  7. “xxxyyy” → 0

Before doing the questions, you can preview which character operations C++ supports, see "C++ Primer" Fifth Edition (Chinese Edition) P82, Table 3.3

Everything is ready, start to do the problem formally

Code

class Solution {
      
        
public:  
    int myAtoi(string str) {
      
        

        int iFlag = 1;  

        bool bStart = false;  
        vector<int> vecDigits;  

        for( auto c : str )  
        {
      
        
            if( !bStart )  
            {
      
        
               if( isspace(c) )  
                {
      
        
                    continue;  
                }   

                if( ('+' == c || '-' == c ) )  
                {
      
        
                    iFlag = '+' == c ? 1 : -1;  
                    bStart = true;  
                    continue;  
                }  
            }  

            if( isdigit(c) )  
            {
      
        
                bStart = true;  
                vecDigits.push_back( c - '0' );  
            }  
            else  
            {
      
        
                break;  
            }  
        }  

        if( vecDigits.size() == 0 )  
        {
      
        
            return 0;  
        }  

        long long result = 0;  
        long long iFactor = 1;  

        auto i = vecDigits.size();  
        while( i > 0 )  
        {
      
        
            --i;  
            result += iFactor * vecDigits[i];  
            iFactor *= 10;  

            if( result*iFlag > INT_MAX )  
            {
      
        
                return INT_MAX;  
            }  

            if( result*iFlag < INT_MIN )  
            {
      
        
                return INT_MIN;  
            }  
        }  

        return result*iFlag;  
    }  
};

The logic is a bit complicated, let me explain:

  1. The first for loop is used to push legal numbers into a vector
    • iFlag is used to save the sign
    • bStart is used to save whether the number has already been processed. The reason for adding this flag is because the space before the number and the space after the number are handled differently
  2. If after the for loop, the vector is still empty, there is no legal number, and 0 is returned directly
  3. The following while statement is used to get an integer, in the same way as the previous question. The overflow judgment is put inside the loop to avoid a string longer than long long

Of course, this code has also been modified several times in order to pass on the LeetCode.

Then let’s see if we can simplify the above logic

Before we modify the code, we have to think about a question, how to ensure the correctness of the logic when simplifying the code?

This is a very common problem, and we will often encounter it during the coding process. Originally, I wanted to be responsible for the code and strive for perfection. As a result, the speed increased, but the result was not right. This is not worth the gain.

To solve this problem, you can try the "test-driven development" approach, that is, design test cases before you start writing code. If the code can pass all test cases, it meets our functional requirements. When making subsequent code modifications, you must ensure that all use cases pass. If the use cases fail, it means that there is a problem with the modified code.

Just like the use cases we wrote earlier, of course these use cases are definitely not sufficient, but they are much better than writing nothing. You know, there are 1047 test cases for this topic on leetcode!

When writing some small programs, we can use assert to complete the result judgment.

//leetcode08.h  

#include <string  

using std::string;  

class Solution08 {  
public:  
    static int myAtoi(string str);  
};
//main  

#include "cassert"  

assert(Solution::myAtoi("123")== 123);  
assert(Solution08::myAtoi("123") == 123);  
assert(Solution08::myAtoi("-123") == -123);  
assert(Solution08::myAtoi("    -123   ") == -123);  
assert(Solution08::myAtoi("    123   456   ") == 123);

Fill in the above test cases, and then think about whether there are other scenarios. If there are any, don't be stingy with using test cases, the more the better.

Guess you like

Origin blog.csdn.net/qq_26751117/article/details/53442419
Recommended