判断一个电话号码是否合法

20 阅读3分钟
package lmp

/*
目标:让一个字符串具备一个功能,判断是否是一个合适的手机号。
String是系统提供的,并没有isPhone这个方法。
现在就尝试在不修改String源码的情况下,增加这个方法。
*/

object img05 {
  
  // 隐式类要为String添加新功能
  implicit class RichString(s: String) {
    
    /**
     * 判断是否是合法的手机号
     * 规则:1开头,第二位3-9,共11位数字
     */
    def isPhone: Boolean = {
      if (s == null || s.isEmpty) return false
      
      // 检查长度是否为11位
      if (s.length != 11) return false
      
      // 检查是否全部为数字
      if (!s.forall(_.isDigit)) return false
      
      // 检查开头:1开头,第二位3-9
      s.charAt(0) == '1' && s.charAt(1) >= '3' && s.charAt(1) <= '9'
    }
    
    /**
     * 判断是否是合法的身份证号(简化版)
     * 规则:18位,前17位数字,最后一位可能是数字或X
     */
    def isIDCard: Boolean = {
      if (s == null || s.isEmpty) return false
      
      // 检查长度是否为18位
      if (s.length != 18) return false
      
      // 检查前17位是否为数字
      if (!s.substring(0, 17).forall(_.isDigit)) return false
      
      // 检查最后一位:数字或X(大写)或x(小写)
      val lastChar = s.charAt(17)
      lastChar.isDigit || lastChar == 'X' || lastChar == 'x'
    }
    
    /**
     * 使用正则表达式验证手机号(更严格的版本)
     */
    def isPhoneRegex: Boolean = {
      val pattern = "^1[3-9]\d{9}$".r
      s match {
        case pattern() => true
        case _ => false
      }
    }
    
    /**
     * 使用正则表达式验证身份证号(更严格的版本)
     */
    def isIDCardRegex: Boolean = {
      val pattern = "^\d{17}[\dXx]$".r
      s match {
        case pattern() => true
        case _ => false
      }
    }
  }
  
  def main(args: Array[String]): Unit = {
    // 测试手机号验证
    val str1 = "13017295863"
    val str2 = "13017295863"  // 可以直接使用字符串字面量
    
    println("手机号测试:")
    println(s"$str1.isPhone = ${str1.isPhone}")  // true
    println(s"$str1.isPhoneRegex = ${str1.isPhoneRegex}")  // true
    
    println(""134567891a".isPhone = " + "134567891a".isPhone)  // false(包含字母)
    println(""134567891a".isPhoneRegex = " + "134567891a".isPhoneRegex)  // false
    
    println(""13056789123".isPhone = " + "13056789123".isPhone)  // true
    println(""13056789123".isPhoneRegex = " + "13056789123".isPhoneRegex)  // true
    
    // 测试错误格式
    println(""12345678901".isPhone = " + "12345678901".isPhone)  // false(第二位是2)
    println(""1380013800".isPhone = " + "1380013800".isPhone)    // false(只有10位)
    println(""19800138000".isPhone = " + "19800138000".isPhone)  // true
    
    println("\n身份证号测试:")
    println(""42900520201012333X".isIDCard = " + "42900520201012333X".isIDCard)  // true
    println(""42900520201012333X".isIDCardRegex = " + "42900520201012333X".isIDCardRegex)  // true
    
    println(""409005202010123333".isIDCard = " + "409005202010123333".isIDCard)  // true
    println(""409005202010123333".isIDCardRegex = " + "409005202010123333".isIDCardRegex)  // true
    
    // 测试错误格式
    println(""42900520201012333".isIDCard = " + "42900520201012333".isIDCard)  // false(只有17位)
    println(""42900520201012333A".isIDCard = " + "42900520201012333A".isIDCard)  // false(最后一位是A)
    println(""42900520201012333x".isIDCard = " + "42900520201012333x".isIDCard)  // true(小写x)
    
    // 额外的测试用例
    println("\n更多测试用例:")
    val testPhones = List(
      "13800138000",  // true
      "15812345678",  // true
      "19987654321",  // true
      "12345678901",  // false
      "1380013800",   // false
      "13800a38000",  // false
      "01012345678"   // false
    )
    
    testPhones.foreach { phone =>
      println(s"$phone -> isPhone: ${phone.isPhone}, isPhoneRegex: ${phone.isPhoneRegex}")
    }
  }
}

使用注意事项:

  1. 隐式类导入:在实际项目中,需要在需要的地方导入隐式类:

    scala

    arduino
     体验AI代码助手
     代码解读
    复制代码
    import lmp.img05._
    // 或者
    import lmp.img05.RichString
    
  2. 值类优化:如果需要性能优化,可以让隐式类继承 AnyVal

    scala

    scala
     体验AI代码助手
     代码解读
    复制代码
    implicit class RichString(val s: String) extends AnyVal {
      // 方法实现
    }
    
  3. 正则表达式说明

    • ^:字符串开始
    • 1[3-9]:1开头,第二位3-9
    • \d{9}:9位数字
    • $:字符串结束
  4. 身份证验证说明

    • 这只是简化的格式验证,真实的身份证验证需要检查校验位和地区码

    • 如果需要完整的验证,需要更复杂的算法