一、Scala 字符串的两种定义方式
先从最基础的字符串定义开始,Scala 支持两种常用的字符串声明形式:
代码实现
package string
object string01 {
def main(args: Array[String]): Unit = {
val str1 = "静夜思 李白 420117200501256578"
val str2 =
""" 静夜思
李白
"""
println(str1)
println(str2)
}
}
二、字符串基础操作:索引、长度、截取、转数字
掌握了定义方式,接下来是字符串的核心操作 —— 这是后续实战的基础:
代码实现
package string
/*
字符串:
常见操作
1.获取单个字符
2.字符串的长度,空格也是有效的字符,他也会占长度
3.字符串的截取:从当前字符串中,截取一段出来 subString(起点下标,终点下标——不包含)
4.转成数字
*/
object string02 {
def main(args: Array[String]): Unit = {
val str1 = "hello scala"
//字符串(下标),下标从0开始
println(str1(0))
println("字符串的长度是: " + str1.length)
//把 ello 这四个字符取出来
val str2 = str1.substring(1,5)
println(str2)
//把 cal 这个三个字符取出来?
val str3 = "我的手机号的第三位是3"
//把 3 截取出来
val str4 = str1.substring(10,12)//str4是一个字符串"3"
println(str4 + 10)
val n = str4.toInt
println(n + 1)
}
}
三、实战:用 Scala 提取身份证信息
学会基础操作后,我们做一个实用案例 ——从身份证号中提取性别、年龄、所属省市,这也是企业开发中常见的字符串解析场景。
需求分析
身份证号(18 位)包含的信息:
- 前 2 位:省份编码
- 第 7-14 位:出生年月日
- 倒数第 2 位:性别(奇数为男,偶数为女)
代码实现
package string
import java.time.LocalDate
object string03 {
def main(args: Array[String]): Unit = {
// 1. 定义身份证前两位对应的省市映射表(补充缺失的regionMap)
val regionMap = Map(
"11" -> "北京市", "12" -> "天津市", "13" -> "河北省", "14" -> "山西省", "15" -> "内蒙古自治区",
"21" -> "辽宁省", "22" -> "吉林省", "23" -> "黑龙江省", "31" -> "上海市", "32" -> "江苏省",
"33" -> "浙江省", "34" -> "安徽省", "35" -> "福建省", "36" -> "江西省", "37" -> "山东省",
"41" -> "河南省", "42" -> "湖北省", "43" -> "湖南省", "44" -> "广东省", "45" -> "广西壮族自治区",
"46" -> "海南省", "50" -> "重庆市", "51" -> "四川省", "52" -> "贵州省", "53" -> "云南省",
"54" -> "西藏自治区", "61" -> "陕西省", "62" -> "甘肃省", "63" -> "青海省", "64" -> "宁夏回族自治区",
"65" -> "新疆维吾尔自治区", "71" -> "台湾省", "81" -> "香港特别行政区", "82" -> "澳门特别行政区"
)
// 测试用例修正:改为18位合法身份证(原17位无效)
// val str = scala.io.StdIn.readLine("请输入你要判断的身份证号: ") // 恢复键盘输入
val str = "430052200006110043"
// 2. 核心修正:先校验身份证长度(18位),这是所有逻辑的前提
if (str.length == 18) {
try {
// ========== 1. 性别判断 ==========
// 取出倒数第二位(索引16),转Int(解决类型问题)
val gender = str.substring(16, 17).toInt
println(s"性别位数字:$gender")
if (gender % 2 == 1) {
println("这是一个帅哥")
} else {
println("这是一个小姑娘")
}
// ========== 2. 年龄计算(精确到生日) ==========
// 提取出生年月日(身份证第7-14位:索引6-13)
val birthYear = str.substring(6, 10).toInt // 出生年
val birthMonth = str.substring(10, 12).toInt // 出生月
val birthDay = str.substring(12, 14).toInt // 出生日
println(s"出生日期:$birthYear年$birthMonth月$birthDay日")
// 精确计算年龄:判断生日是否已过
val now = LocalDate.now()
val currentYear = now.getYear
var age = currentYear - birthYear
if (birthMonth > now.getMonthValue || (birthMonth == now.getMonthValue && birthDay > now.getDayOfMonth)) {
age -= 1 // 生日未过,年龄减1
}
println(s"今年${age}岁")
// ========== 3. 省市判断 ==========
val pro = str.substring(0, 2) // 取出前两位省份编码
val province = regionMap.get(pro)
province match {
case Some(name) => println(s"所属省份/直辖市:$name")
case None => println(s"没有编号为${pro}的省份")
}
} catch {
// 处理非数字转换异常(比如身份证含字母)
case _: NumberFormatException =>
println("身份证号格式错误:出生日期/性别位必须是数字")
// 处理索引越界(理论上18位校验后不会触发,兜底用)
case _: StringIndexOutOfBoundsException =>
println("身份证号格式错误:索引越界")
}
} else {
// 长度不合法的提示
println(s"${str}不是一个合法的身份证号,长度不对(需18位,当前${str.length}位)")
}
// } // 循环输入的闭合括号(如需循环可取消注释)
}
}