Scala 学生成绩总分平均分计算程序

41 阅读2分钟
object class7 {
  case class Stu(name:String, yuwen:Double, shuxue:Double, yingyu:Double)

  def main(args: Array[String]): Unit = {
    // 0. 创建一个可变List
    val stuList = scala.collection.mutable.ListBuffer[Stu]()

    // 1. 读入文件 迭代器
    val lines = scala.io.Source.fromFile("score.txt").getLines()

    lines.next() // 跳过第一行

    while(lines.hasNext){
      val line = lines.next()
      // 字符串拆分
      val li = line.split(":")
      stuList += Stu(li(0), li(1).toDouble, li(2).toDouble, li(3).toDouble)
    }
    // 读入数据结束
    println("读入数据结束")

    // 2. 计算
    println("计算结束,开始写入")

    // 3. 保存结果
    val fileWriter = new FileWriter("score_result.txt")
    fileWriter.write("高三19班成绩单 \r")
    stuList.foreach(stu => {
      val total = stu.yuwen + stu.yingyu + stu.shuxue
      val avg = total / 3
      fileWriter.write(s"${stu.name}, 总分:${total}, 平均分:${avg} \r\n")
    })
    fileWriter.close()
  }
}

一、核心流程梳理

整体流程:定义学生数据结构 → 读取 score.txt 成绩文件 → 解析数据并封装为学生对象 → 计算每位学生的总分/平均分 → 将结果写入 score_result.txt 文件

二、逐行代码解释

scala

object score01 {  // Scala 程序入口(单例对象)
  // 1. 定义样例类:封装学生成绩(姓名+三门科目分数)
  case class Stu(name:String, yuwen:Double, shuxue:Double, yingyu:Double)
  // 样例类优势:自动生成构造器、toString 等方法,无需手动写 getter/setter

  def main(args: Array[String]): Unit = {  // 程序主方法
    // 2. 创建可变 ListBuffer:存储解析后的学生对象(支持动态添加)
    val stuList = scala.collection.mutable.ListBuffer[Stu]()

    // 3. 读取 score.txt 文件,获取行迭代器
    val lines = scala.io.Source.fromFile("score.txt").getLines()
    // Source.fromFile("score.txt"):打开成绩文件(需确保文件在项目根目录)
    // getLines():按行读取文件,返回迭代器(省内存,逐行处理)

    // 4. 跳过文件第一行(表头,比如“姓名:语文:数学:英语”)
    lines.next() 

    // 5. 循环解析每一行成绩数据
    while(lines.hasNext){  // 判断迭代器是否还有未读取的行
      val line = lines.next()  // 取出当前行(格式:姓名:语文:数学:英语,如“小红:98:82:93”)
      val li = line.split(":")  // 按冒号拆分字符串,得到数组
      // 将拆分后的数据封装为 Stu 对象,添加到 ListBuffer
      stuList += Stu(li(0), li(1).toDouble, li(2).toDouble, li(3).toDouble)
      // li(0)=姓名,li(1)=语文(转 Double 支持小数成绩),li(2)=数学,li(3)=英语
    }
    println("读入数据结束")  // 提示数据读取完成

    // 6. 计算前的提示(仅日志作用)
    println("计算结束,开始写入")

    // 7. 核心扩展:将结果写入新文件 score_result.txt
    // 7.1 创建文件写入器,指定要写入的文件名称
    val fileWriter = new FileWriter("score_result.txt")
    // 7.2 写入文件标题(\r 是回车符,适配不同系统换行)
    fileWriter.write("高三19班成绩单 \r")
    // 7.3 遍历学生列表,计算并写入每位学生的成绩
    stuList.foreach(stu => {
      val total = stu.yuwen + stu.yingyu + stu.shuxue  // 计算总分
      val avg = total / 3  // 计算平均分
      // 写入一行结果:姓名 + 总分 + 平均分(\r\n 是回车+换行,保证每行独立)
      fileWriter.write(s"${stu.name}, 总分:${total}, 平均分:${avg} \r\n")
    })
    // 7.4 关闭文件写入器(必须!否则数据可能只存在缓存,未真正写入文件)
    fileWriter.close()
  }
}

三、关键细节补充

1. 文件操作核心知识点

代码片段作用注意事项
new FileWriter("score_result.txt")创建文件写入器,若文件不存在则自动创建;若已存在则覆盖原有内容如需追加内容,改用 new FileWriter("score_result.txt", true)
fileWriter.write(内容)将字符串写入文件(先存到内存缓存)单次写入不会立即刷到硬盘
fileWriter.close()关闭写入器,同时将缓存中的数据刷入硬盘必须调用!否则文件可能为空或内容不完整

2. 输入 / 输出文件格式说明

  • 输入文件(score.txt)  格式(冒号分隔,第一行是表头):

    plaintext

    姓名:语文:数学:英语
    小红:98:82:93
    小明:90:85:95
    小刚:98:83:79
    
  • 输出文件(score_result.txt)  生成后的内容示例:

    plaintext

    高三19班成绩单 
    小红, 总分:273.0, 平均分:91.0 
    小明, 总分:270.0, 平均分:90.0 
    小刚, 总分:260.0, 平均分:86.66666666666667 
    

3. 潜在问题(也是优化点)

这段代码缺少异常处理,实际运行中可能出现报错:

  • 如果 score.txt 不存在 → 抛出「文件未找到」异常;
  • 如果成绩数据格式错误(比如非数字)→ toDouble 抛出类型转换异常;
  • 如果写入文件时权限不足 → 抛出 IO 异常;
  • 未使用 try-finally 确保 fileWriter.close() 执行(比如报错时可能跳过关闭操作)。