How can I print all the items from the list to the console in C#?
I am writing a code to get the output (read from a text file): "the list of people with instances like name, gender, age". However, when I ran the code, I got only the first line of the list in a text file. Here is my code:
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
namespace Person_Del
{
class Program
{
public static void Main(String[] args)
{
Console.SetIn(new StreamReader("data.txt"));
List<Person> p = new();
string data = Console.ReadLine();
Person obj = new();
obj.SetData(data,"/");
p.Add(obj);
foreach (var ii in p)
{
Console.WriteLine(ii.GetInfo());
}
}
}
public class Person
{
//static methods
public static void CheckData(string name, string gender, byte age)
{
string msg = null;
if (string.IsNullOrEmpty(name)) msg += "Empty Name";
if (string.IsNullOrEmpty(gender)) msg += (msg != null ? "; " : "") + "Empty Gender";
if (age > 125) msg += (msg != null ? "; " : "") + $"Invalid age ({age})";
if (msg != null) throw new Exception(msg);
}
public static (string, string, byte) Parse(string data, string delimiter)
{
try
{
string[] arr = data.Split(delimiter);
string name = arr[0].Trim();
string gender = arr[1].Trim();
byte age = byte.Parse(arr[2]);
return (name, gender, age);
}
catch (Exception)
{
throw new Exception($"Given data \"{data}\" are invalid.");
}
}
//instance fields
protected string name;
protected string gender;
protected byte age;
//instance methods
public string GetName() => name;
public string GetGender() => gender;
public byte GetAge() => age;
public void SetData(string name, string gender, byte age)
{
Person.CheckData(name, gender, age);
this.name = name;
this.gender = gender;
this.age = age;
}
public void SetData(string data, string delimiter)
{
(string, string, byte) value = Person.Parse(data, delimiter);
string name = value.Item1;
string gender = value.Item2;
byte age = value.Item3;
this.SetData(name, gender, age);
}
public string GetInfo() => $"Name:{name}, Gender:{gender}, Age:{age}";
//new instance methods for homework
public void SetName(string name) => this.name = name;
public void SetGender(string gender) => this.gender = gender;
internal bool SetData()
{
throw new NotImplementedException();
}
}
}
Here is my text file (data.txt):
Alice/F/23
David/M/23
Note that: I want to get the output of the two lines above; however, what I got is only the first line "Alice/F/23".
Solution 1:
By reading all the lines into an array first:
public static void Main(String[] args)
{
var lines = File.ReadAllLines("data.txt");
List<Person> people = new();
foreach(var line in lines){
Person p = new();
p.SetData(line,"/");
people.Add(obj);
}
foreach (var person in people )
{
Console.WriteLine(person.GetInfo());
}
}
By reading incrementally using a StreamReader:
public static void Main(String[] args)
{
using var sr = new StreamReader("data.txt");
List<Person> people = new();
while(!sr.EndOfStream)
{
var line = sr.ReadLine();
Person p = new();
p.SetData(line,"/");
people.Add(p);
}
foreach (var person in people)
{
Console.WriteLine(person.GetInfo());
}
}
The problem you're asking about ultimately stems from the fact that you only call ReadLine once, but I don't recommend stashing your StreamReader in Console's stdin.
I also named your variables a little better; strive for meaningful names - use plurals for lists and arrays etc. Short lived variables can be relatively meaningless, like Person p
but longer lived ones/ones that are used in several places, try and make them so the code reads like a book: foreach(var person in people)
rather than foreach(var ii in p)