ProgramGuru

Build a validated student report

Build a validated student report

Now combine typed records, validation, collection transformations and readable output. Our school report must reject impossible marks, show each student in a stable order and calculate an average without dividing by an empty class count. These are concrete requirements you can test independently.

What you’ll learn

  • Validate student records, sort them and calculate an average.
  • Handle empty input without dividing by zero and plan invalid-record feedback.

Build a validated student report in the example

  1. Validate records

    Now combine typed records, validation, collection transformations and readable output.

    Validate records
  2. Sort and aggregate

    A failable initializer protects each record’s score range.

    Sort and aggregate
  3. Format report

    Both records validate successfully.

    Format report
Both records validate successfully. Although the input order starts with Saira, sorting produces Diya first. The total is 170 and the two-student average is 85.0. The second call handles an empty list before any division and returns No students.

How build a validated student report works

A failable initializer protects each record’s score range. A separate function formats the report and handles an empty list. Sorting names makes display order explicit, while reduce calculates the total. Returning report text keeps calculation separate from the caller’s print operation.

Work through build a validated student report

Save this complete program as main.swift and run it with the Swift toolchain. No separate input file is needed.

Swift · complete program

struct Student {
  let name: String
  let score: Int
  init?(name: String, score: Int) {
    guard (0...100).contains(score) else { return nil }
    self.name = name
    self.score = score
  }
}
func report(_ students: [Student]) -> String {
  guard !students.isEmpty else { return "No students" }
  let lines = students.sorted { $0.name < $1.name }.map { "\($0.name): \($0.score)" }
  let total = students.reduce(0) { $0 + $1.score }
  let average = Double(total) / Double(students.count)
  return (lines + ["Average: \(average)"]).joined(separator: "\n")
}
if let diya = Student(name: "Diya", score: 80),
   let saira = Student(name: "Saira", score: 90) {
  print(report([saira, diya]))
}
print(report([]))

Expected output

Diya: 80
Saira: 90
Average: 85.0
No students

Follow the execution

Both records validate successfully. Although the input order starts with Saira, sorting produces Diya first. The total is 170 and the two-student average is 85.0. The second call handles an empty list before any division and returns No students.

Try this program in the Swift compiler. Paste the complete source above.

Plan an application beyond the console

Move the calculation into a library or model layer before building an interface. SwiftUI observes state and describes a view hierarchy, while UIKit follows another application framework model. Use Apple’s current Develop in Swift tutorials for the app lifecycle and UI environment; this console project does not implement those frameworks.

Practice: Build a validated student report

Your task: What should happen if you add Noor with score 120?

Swift · complete program

struct Student {
  let name: String
  let score: Int
  init?(name: String, score: Int) {
    guard (0...100).contains(score) else { return nil }
    self.name = name
    self.score = score
  }
}
func report(_ students: [Student]) -> String {
  guard !students.isEmpty else { return "No students" }
  let lines = students.sorted { $0.name < $1.name }.map { "\($0.name): \($0.score)" }
  let total = students.reduce(0) { $0 + $1.score }
  let average = Double(total) / Double(students.count)
  return (lines + ["Average: \(average)"]).joined(separator: "\n")
}
if let diya = Student(name: "Diya", score: 80),
   let saira = Student(name: "Saira", score: 90) {
  print(report([saira, diya]))
}
print(report([]))

Worked answer

The initializer returns nil, and the caller should show a validation error rather than silently add a false score. If Noor instead has 70, the three valid marks total 240 and average 80.0.

Keep report requirements explicit

Names are display values, not guaranteed unique identifiers. A real report also needs an explicit policy for absent marks, stable student IDs and appropriate storage. Keep those requirements separate from this small validated console project.

Check your decision

What should happen if you add Noor with score 120?
Choose one answer. You can try again.

Answer and explanation

The initializer returns nil, and the caller should show a validation error rather than silently add a false score.

The initializer returns nil, and the caller should show a validation error rather than silently add a false score. If Noor instead has 70, the three valid marks total 240 and average 80.0.

Check the practical consequence

The report receives an empty array. Why check it before averaging?
Choose one answer. You can try again.

Answer and explanation

The average has no observations and would otherwise divide by zero.

Names are display values, not guaranteed unique identifiers. A real report also needs an explicit policy for absent marks, stable student IDs and appropriate storage. Keep those requirements separate from this small validated console project.

Keep report requirements explicit

The initializer returns nil, and the caller should show a validation error rather than silently add a false score. If Noor instead has 70, the three valid marks total 240 and average 80.0. Names are display values, not guaranteed unique identifiers.

Further reading: official Swift language guide.

Reaching the recap and completing the quizzes are separate milestones.

    Course overview →