d. Applied Task
Gradual-build lesson (top-level programs)
This version shows only what is new at each step, not the full script every time.
Template students should start with (Top-level Program)
No class Program, no Main method.
A) TXT Lesson (Top-level) - only new code each step
TXT Step 1 - Build the menu loop
What this step does
Creates a working menu shell so students can test navigation before adding data structures or file I/O.
New code
using System;
while (true)
{
Console.Clear();
Console.WriteLine("=== Student Results (TXT) ===");
Console.WriteLine("1) Add result");
Console.WriteLine("2) View results");
Console.WriteLine("3) Save & Exit");
Console.Write("Choose: ");
string choice = Console.ReadLine() ?? "";
if (choice == "1")
{
Console.WriteLine("Add result (not built yet). Press Enter...");
Console.ReadLine();
}
else if (choice == "2")
{
Console.WriteLine("View results (not built yet). Press Enter...");
Console.ReadLine();
}
else if (choice == "3")
{
Console.WriteLine("Saving (not built yet). Goodbye!");
break;
}
else
{
Console.WriteLine("Invalid choice. Press Enter...");
Console.ReadLine();
}
}
TXT Step 2 - Add a result type, list, and display method
What this step does
Introduces a StudentResult class and an in-memory list so Option 2 can show stored data.
New code
Add this using at the top:
Add this list before the while (true) loop:
Replace Option 2 inside the loop:
else if (choice == "2")
{
DisplayResults(results);
Console.WriteLine("\nPress Enter...");
Console.ReadLine();
}
Add this helper method after the loop:
static void DisplayResults(List<StudentResult> results)
{
if (results.Count == 0)
{
Console.WriteLine("\n(No results yet)");
return;
}
Console.WriteLine("\nStored results:");
for (int i = 0; i < results.Count; i++)
Console.WriteLine($"{i + 1}. {results[i].StudentName} - {results[i].Score}");
}
Add this class at the end of the file:
TXT Step 3 - Add input validation for new results
What this step does
Replaces the placeholder add action with validated input. Name must not be empty, score must be 0-100.
New code
Replace Option 1 inside the loop:
if (choice == "1")
{
results.Add(GetNewResultFromUser());
Console.WriteLine("\nAdded! Press Enter...");
Console.ReadLine();
}
Add this method after DisplayResults:
static StudentResult GetNewResultFromUser()
{
string name;
while (true)
{
Console.Write("Enter student name: ");
name = (Console.ReadLine() ?? "").Trim();
if (!string.IsNullOrWhiteSpace(name)) break;
Console.WriteLine("Name cannot be empty.");
}
int score;
while (true)
{
Console.Write("Enter score (0-100): ");
string input = Console.ReadLine() ?? "";
if (int.TryParse(input, out score) && score >= 0 && score <= 100) break;
Console.WriteLine("Score must be an integer from 0 to 100.");
}
return new StudentResult { StudentName = name, Score = score };
}
TXT Step 4 - Load existing TXT data at startup
What this step does
Loads previously saved results before the menu starts, so data persists between runs.
New code
Add this using at the top:
Replace list initialization before the loop:
Add this line to the menu display:
Add this method after GetNewResultFromUser:
static List<StudentResult> LoadResults()
{
var results = new List<StudentResult>();
if (!File.Exists(FilePath))
return results;
string[] lines = File.ReadAllLines(FilePath);
foreach (string rawLine in lines)
{
string line = rawLine.Trim();
if (string.IsNullOrWhiteSpace(line)) continue;
if (line.Equals("StudentName|Score", StringComparison.OrdinalIgnoreCase))
continue;
string[] parts = line.Split('|');
if (parts.Length != 2) continue;
string name = parts[0].Trim();
if (int.TryParse(parts[1].Trim(), out int score))
results.Add(new StudentResult { StudentName = name, Score = score });
}
return results;
}
TXT Step 5 - Save updated TXT data when exiting
What this step does
Writes all in-memory results back to file so new records are kept after the program closes.
New code
Replace Option 3 inside the loop:
Add this method after LoadResults:
TXT complete (compile-safe file order)
Use this order in the file:
usinglinesFilePathconstant andresults = LoadResults()- main
whileloop - helper methods (
LoadResults,SaveResults,GetNewResultFromUser,DisplayResults) StudentResultclass at the end
B) CSV Lesson (Top-level) - only what is new
Build TXT first, then apply only these changes for CSV.
CSV Step 1 - Update menu heading
What this step does
Makes the UI clearly indicate the format being used.
New code
Change the heading line:
CSV Step 2 - No model change
What this step does
No change. StudentResult and List<StudentResult> stay the same.
CSV Step 3 - No validation change
What this step does
No change. GetNewResultFromUser() is reused exactly as TXT.
CSV Step 4 - Change load logic for comma-delimited data
What this step does
Switches loading rules from pipe-separated TXT to comma-separated CSV.
New code
Change file path constant:
Replace LoadResults() with:
static List<StudentResult> LoadResults()
{
var results = new List<StudentResult>();
if (!File.Exists(FilePath))
return results;
string[] lines = File.ReadAllLines(FilePath);
foreach (string rawLine in lines)
{
string line = rawLine.Trim();
if (string.IsNullOrWhiteSpace(line)) continue;
if (line.Equals("StudentName,Score", StringComparison.OrdinalIgnoreCase))
continue;
string[] parts = line.Split(',');
if (parts.Length != 2) continue;
string name = parts[0].Trim();
if (int.TryParse(parts[1].Trim(), out int score))
results.Add(new StudentResult { StudentName = name, Score = score });
}
return results;
}
CSV Step 5 - Change save logic for comma-delimited data
What this step does
Saves records using CSV headers and comma separation.
New code
Replace SaveResults() with:
C) XML Lesson (Top-level) - only what is new
Build TXT first, then apply only these changes for XML.
XML Step 1 - Update menu heading
What this step does
Makes the UI clearly indicate XML mode.
New code
Change the heading line:
XML Step 2 - No model change
What this step does
No change. StudentResult and List<StudentResult> stay the same.
XML Step 3 - No validation change
What this step does
No change. GetNewResultFromUser() is reused exactly as TXT.
XML Step 4 - Change load logic to parse XML elements
What this step does
Loads from XML nodes (<Result>, <StudentName>, <Score>) instead of split text lines.
New code
Add this using:
Change file path constant:
Replace LoadResults() with:
static List<StudentResult> LoadResults()
{
var results = new List<StudentResult>();
if (!File.Exists(FilePath))
return results;
XDocument doc = XDocument.Load(FilePath);
XElement root = doc.Root;
if (root == null)
return results;
foreach (XElement element in root.Elements("Result"))
{
string name = (string)element.Element("StudentName");
string scoreText = (string)element.Element("Score");
if (string.IsNullOrWhiteSpace(name)) continue;
if (int.TryParse(scoreText, out int score))
results.Add(new StudentResult { StudentName = name.Trim(), Score = score });
}
return results;
}
XML Step 5 - Change save logic to write XML structure
What this step does
Creates a structured XML document and writes it to disk.
New code
Replace SaveResults() with:
40+ response tip
For format-justification questions, always compare:
- structure (TXT separator vs CSV delimiter vs XML tags/tree)
- reason for use in the scenario
- one trade-off for the two formats not chosen