Swift 用一个方法判断字符串是否表示为数值

1,631 阅读3分钟

今天在leetcode上看到一个算法题,需要用一个方法判断一个字符串是否可以表示为数值。原题如下:

请实现一个函数用来判断字符串是否表示数值(包括整数和小数)。例如,字符串"+100"、"5e2"、"-123"、"3.1416"、"-1E-16"、"0123"都表示数值,但"12e"、"1a3.14"、"1.2.3"、"+-5"及"12e+5.4"都不是。

看了一下官方提供的解题思路 image.png

swift实现

直接在控制器里面做的,有输入框和按钮,可以直接用于判断打印结果

//
//  ViewController.swift
//  isNumber
//
//  Created by 李灿 on 2021/4/9.
//

import UIKit

class ViewController: UIViewController {
    let text : UITextField = UITextField()
    override func viewDidLoad() {
        super.viewDidLoad()
        
        // Do any additional setup after loading the view.
        text.frame = CGRect(x: 20, y: 100, width: UIScreen.main.bounds.width - 40, height: 30)
        text.backgroundColor = UIColor.gray
        view .addSubview(text)
        
        let btn = UIButton()
        btn.frame = CGRect(x: 20, y: 150, width: UIScreen.main.bounds.width - 40, height: 40)
        btn.setTitle("sync", for: .normal)
        btn.setTitleColor(UIColor.green, for: .normal)
        btn.addTarget(self, action: #selector(sync), for: .touchUpInside)
        view.addSubview(btn)
    }

    @objc func sync() {
        let isNum = isNumber(string: text.text ?? "")
        if isNum {
            print("TRUE")
        }
        else
        {
            print("FALSE")
        }
    }
    
    enum state{
        case StartSpace  // 开始的空格
        case Sign  // 正负符号
        case Num  // 数字
        case dot // 小数点
        case Decimal // 小数位
        case E // 科学计数e
        case ESign // 指数符号
        case ENum // 指数数字
        case EndSpace // 结尾空格
        case Err
    }
    
    enum char_type : Int {
        case Char_number // 数字字符
        case Char_e // e
        case Char_dot // 小数点
        case Char_sign // 符号
        case Char_space // 空格
        case Char_error // 错误的数字字符
    }
    
    func charType(c : Character) -> char_type {
        if c >= "0" && c <= "9"
        {
            return .Char_number
        }
        else if c == "e" || c == "E"
        {
            return .Char_e
        }
        else if c == "."
        {
            return .Char_dot
        }
        else if c == "+" || c == "-"
        {
            return .Char_sign
        }
        else if c == " "
        {
            return .Char_space
        }
        return .Char_error
    }
    
    func isNumber(string : String) -> Bool {
        var state: state = .StartSpace
        for char in string {
            let cType : char_type = charType(c: char)
            switch cType {
            case .Char_number:
                state = syncNum(state: state) ?? .Err
                break
            case .Char_e:
                state = syncE(state: state) ?? .Err
                break
            case .Char_dot:
                state = syncDot(state: state) ?? .Err
                break
            case .Char_sign:
                state = syncSign(state: state) ?? .Err
                break
            case .Char_space:
                state = syncStartSpace(state: state) ?? .Err
                break
            default:
                state = .Err
                break
            }
            
            guard state != .Err else {
                return false
            }
        }
        return state == .Num || state == .Decimal || state == .dot || state == .ENum || state == .EndSpace
    }
    
    // 解析开始空格状态
    func syncStartSpace(state : state) -> state?
    {
        // 开始空格进来出去还是开始空格
        // 其他的合法情况以结束空格的状态出去
        switch state {
        case .StartSpace:
            return .StartSpace
        case .Num:
            return .EndSpace
        case .Decimal:
            return .EndSpace
        case .dot:
            return .EndSpace
        case .EndSpace:
            return .EndSpace
        default:
            return nil
        }
    }
    
    // 解析符号状态
    func syncSign(state : state) -> state?
    {
        // 如果开始空格状态进来、那么符号一定是正负符号 比如 "+200"、"-200"
        // 如果是E状态进来,那么符号一定是E后面的科学计数符号 比如 "1E-16"
        switch state {
        case .StartSpace:
            return .Sign
        case .E:
            return .ESign
        default:
            return nil
        }
    }
    
    // 解析数字状态
    func syncNum(state : state) -> state?
    {
        // 开始空格进来为整数位
        // 正负符号进来为整数位
        // 整数位进来为整数位
        // 小数点进来为小数位
        // 小数位进来为小数位
        // E进来为指数位
        // 指数位进来为指数位
        // 指数符号进来为指数位
        // 指数位进来为指数位
        // 其他位错误项
        switch state {
        case .StartSpace:
            return .Num
        case .Sign:
            return .Num
        case .Num:
            return .Num
        case .dot:
            return.Decimal
        case .Decimal:
            return .Decimal
        case .E:
            return .ENum
        case .ESign:
            return .ENum
        case .ENum:
            return .ENum
        default:
            return nil
        }
    }
    
    // 解析小数点
    func syncDot(state : state) -> state?
    {
        // 开始空格和正负符号进来为小数位
        // 数字进来为小数点
        switch state {
        case .StartSpace:
            return .Decimal
        case .Sign:
            return .Decimal
        case .Num:
            return .dot
        default:
            return nil
        }
    }
    
    func syncE(state : state) -> state?
    {
        switch state {
        case .Num:
            return .E
        case .dot:
            return .E
        default:
            return nil
        }
    }
}

最后附上原题地址:leetcode-cn.com/problems/bi…