I am pretty new to c# . Got a problem with command line arguments. what i want to do is make use of the third cmd line argument and write to it. I have specified the path of the file I want to write into and other stuffs. But the question here is can i access the command line arguments(for eg; args[3]) from user defined functions? How do we do tat? below is my code.
public class Nodes
{
public bool isVisited;
public string parent;
public string[] neighbour;
public int nodeValue;
public Nodes(string[] arr, int nodeValue)
{
this.neighbour = new string[arr.Length];
for (int x = 0; x < arr.Length; x++)
this.neighbour[x] = arr[x];//hi...works??
this.isVisited = false;
this.nodeValue = nodeValue;
}
}
public class DFS
{
static List<string> traversedList = new List<string>();
static List<string> parentList = new List<string>();
static BufferBlock<Object> buffer = new BufferBlock<object>();
static BufferBlock<Object> buffer1 = new BufferBlock<object>();
static BufferBlock<Object> buffer3 = new BufferBlock<object>();
static BufferBlock<Object> buffer2 = new BufferBlock<object>();
public static void Main(string[] args)
{
int N = 100;
int M = N * 4;
int P = N * 16;
Stopwatch stopwatch = new Stopwatch();
stopwatch.Start();
List<string> global_list = new List<string>();
StreamReader file = new StreamReader(args[2]);
string text = file.ReadToEnd();
string[] lines = text.Split('\n');
string[][] array1 = new string[lines.Length][];
Nodes[] dfsNodes = new Nodes[lines.Length];
for (int i = 0; i < lines.Length; i++)
{
lines[i] = lines[i].Trim();
string[] words = lines[i].Split(' ');
array1[i] = new string[words.Length];
dfsNodes[i] = new Nodes(words, i);
for (int j = 0; j < words.Length; j++)
{
array1[i][j] = words[j];
}
}
StreamWriter sr = new StreamWriter(args[4]);
int startNode = int.Parse(args[3]);
if (args[1].Equals("a1"))
{
Console.WriteLine("algo 0");
buffer.Post(1);
dfs(dfsNodes, startNode, "root");
}
else if (args[1].Equals("a2"))
{
Console.WriteLine("algo 1");
buffer1.Post(1);
dfs1(dfsNodes, startNode, "root",sr);
}
else if (args[1].Equals("a3"))
{
buffer3.Post(1);
List<string> visitedtList = new List<string>();
Console.WriteLine("algo 2");
dfs2(dfsNodes, startNode, "root", visitedtList,sr);
}
stopwatch.Stop();
Console.WriteLine(stopwatch.Elapsed);
Console.ReadLine();
}
public static void dfs(Nodes[] node, int value, string parent,StreamWriter sr1)
{
int id = (int)buffer.Receive();
sr1=new StreamWriter(arg
Console.WriteLine("Node:" + value + " Parent:" + parent + " Id:" + id);
sr1.Write("Node:" + value + " Parent:" + parent + " Id:" + id);
id++;
traversedList.Add(value.ToString());
buffer.Post(id);
for (int z = 1; z < node[value].neighbour.Length; z++)
{
if (!traversedList.Contains(node[value].neighbour[z]))
{
dfs(node, int.Parse(node[value].neighbour[z]), value.ToString(),sr1);
}
}
return;
}
public static void dfs1(Nodes[] node, int value, string parent, StreamWriter sr)
{
int id = (int)buffer1.Receive();
sr.Write("Node:" + value + " Parent:" + parent + " Id:" + id);
node[value].isVisited = true;
node[value].parent = parent;
id++;
buffer1.Post(id);
for (int z = 1; z < node[value].neighbour.Length; z++)
{
buffer2.Post(node[int.Parse(node[value].neighbour[z])]);
if (!isVisited())
{
dfs1(node, int.Parse(node[value].neighbour[z]), value.ToString(),sr);
}
}
return;
}
public static void dfs2(Nodes[] node, int value, string parent, List<string> visitedtList, StreamWriter sr)
{
int id = (int)buffer3.Receive();
sr.Write("Node:" + value + " Parent:" + parent + " Id:" + id);
id++;
visitedtList.Add(value.ToString());
buffer3.Post(id);
for (int z = 1; z < node[value].neighbour.Length; z++)
{
buffer2.Post(node[int.Parse(node[value].neighbour[z])]);
if (!visitedtList.Contains(node[value].neighbour[z]))
dfs2(node, int.Parse(node[value].neighbour[z]), value.ToString(), visitedtList,sr);
}
return;
}
public static bool isVisited()
{
Nodes node = (Nodes)buffer2.Receive();
return node.isVisited;
}
}
So the thing is I want to write the output of each dfs to the file specified as the command line argument. So can I have access to the args in the dfs, dfs1 methods??? Thank you.
You could either keep a static field to hold it, or just use Environment.GetCommandLineArgs().
Well, in its simplest form, just save it to use later
class Program
{
static string _fpath;
static void Main(string[] args)
{
// ...stuff
_fpath = args[3];
}
static void WriteFile()
{
using(var stream = File.Open(_fpath, ...))
{
// write to file
}
}
}
Not necessarily exactly how I would do it, but you get the idea.
Also, regarding this bit of code...
this.neighbour = new string[arr.Length];
for (int x = 0; x < arr.Length; x++)
this.neighbour[x] = arr[x];//hi...works??
You can simply write
this.neighbour = arr;
Ahh, the wonders of managed code :D. No need to copy elements across to the second array. Of course, you need to consider the fact that changes to elements in the argument array (arr) will be reflected in your internal array now.
It would be better to pass arguments into functions instead of relying on some "hidden" way to pass them.
Both static variable and GetCommandLineArgs are useful to pass them in hidden way (as pointed out in other answers). Drawbacks are harder to test (since need to set static shared dependency) and less clear for future readers that there is this hidden dependency.
Related
so I wrote some C# code and I am trying to test it incrementally, do to something that would take a while to explain, but bottom line, I'm new to c# and not understanding the online compiler error messages. Here is the error message I get when I try and compile, but the strings look good to me.
string solutionSet = "white|black|beige|pink|green|blue|red|yellow|orange|cyan|purple|brown";
string[] solutionSetArray = new string[12];
string ret = "";
string delimeter = "|";
int tempPos = 0;
int counter = 0;
int successFlag = 0;
int patternLength = 5;
for (int index = 0; index < solutionSet.Length; index++)
{
if (solutionSet[index] == delimeter)
{
solutionSetArray[counter] = solutionSet.Substring(tempPos, index);
tempPos = index + 1;
counter++;
}
if (solutionSet.Length - index == 1)
{
solutionSetArray[solutionSetArray.Length-1] = solutionSet.Substring(tempPos, solutionSet.Length);
}
}
for (int i = 0; i < patternLength; i++)
{
Random rnd = new Random();
int randIndex = rnd.Next(solutionSetArray.Length);
if (i != patternLength - 1)
{
ret += solutionSetArray[randIndex] + "|";
successFlag++;
}
else
{
ret += solutionSetArray[randIndex];
}
}
if (successFlag == patternLength - 1)
{
Console.WriteLine(ret);
}
else
{
Console.WriteLine("ERROR");
}
The error (which, according to the message, is on line 1, column 11) is being caused by your very first line of code, which begins string.
I can't tell the context from just your post, but my guess is that you are declaring solutionSet in a block that is not inside of a class or function. You should enclose your code in a class or method, e.g.
public class MyClass
{
static public void Main()
{
string solutionSet = "white|black|beige|pink|green|blue|red|yellow|orange|cyan|purple|brown";
//Rest of code goes here
}
}
By the way, if you're trying to convert solutionSet to an array, you can just write
var solutionSetArray = solutionSet.Split("|");
the problem with your code is
solutionSetArray[counter] = solutionSet.Substring(tempPos, index);
after 6 iterations tempPos=34 and index=37 which is running out of bounds of solutionSet. I would suggest to use var solutionSetArray = solutionSet.Split("|"); and also use LinqPad which can be easy for you to debug if possible,.
I can't permanently replace the array members. When I change the value of String Clue, the string being displayed only displays the current value of clue. I think the problem us on the initialization of char[]. I tried to put them in other parts of the code but it produces error. Beginner here! Hope you can help me. Thanks! :)
private void clues(String clue)
{
int idx = numb[wordOn]+4;
char[] GuessHide = Words[idx].ToUpper().ToCharArray();
char[] GuessShow = Words[idx].ToUpper().ToCharArray();
for (int a = 0; a < GuessHide.Length; a++)
{
if (GuessShow[a] != Convert.ToChar(clue.ToUpper()))
GuessHide[a] = '*';
else
GuessHide[a] = Convert.ToChar(clue.ToUpper());
}
Guess(string.Join("", GuessHide));
}
Edited - because you initalize GuessHide at each call of calls in your code and you do not store its current state you basically reset it each time. Still, you can make some small changes in your code like this:
private static void clues(string clue, char[] GuessHide, char[] GuessShow)
{
for (int a = 0; a < GuessHide.Length; a++)
{
if (GuessShow[a] == Convert.ToChar(clue.ToUpper()))
{
GuessHide[a] = Convert.ToChar(clue.ToUpper());
}
}
Console.WriteLine(string.Join("", GuessHide));
}
Call it like this:
clues("p", GuessHide, GuessShow);
clues("a", GuessHide, GuessShow);
Initialise GuessShow and GuessHide in the outside code like this:
char[] GuessHide = new string('*', Words[idx].Length).ToCharArray();
char[] GuessShow = Words[idx].ToUpper().ToCharArray();
public class Program
{
static string[] Words;
static string[] HiddenWords;
public static void Main()
{
Words = new string[] { "Apple", "Banana" };
HiddenWords = new string[Words.Length];
for (int i = 0; i < Words.Length; i++)
{
HiddenWords[i] = new string('*', Words[i].Length);
}
Guess('P', 0);
Guess('a', 0);
Guess('A', 1);
Guess('N', 1);
Console.ReadLine();
}
private static void Guess(char clue, int idx)
{
string originalWord = Words[idx];
string upperedWord = Words[idx].ToUpper();
char[] foundSoFar = HiddenWords[idx].ToCharArray();
clue = char.ToUpper(clue);
for (int i = 0; i < upperedWord.Length; i++)
{
if (upperedWord[i] == clue)
{
foundSoFar[i] = originalWord[i];
}
}
HiddenWords[idx] = new string(foundSoFar);
Console.WriteLine(HiddenWords[idx]);
}
}
I am creating a word list of possible uppercase letters to prove how insecure 8 digit passwords are this code will write aaaaaaaa to aaaaaaab to aaaaaaac etc. until zzzzzzzz using this code:
class Program
{
static string path;
static int file = 0;
static void Main(string[] args)
{
new_file();
var alphabet = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ123456789+-*_!$£^=<>§°ÖÄÜöäü.;:,?{}[]";
var q = alphabet.Select(x => x.ToString());
int size = 3;
int counter = 0;
for (int i = 0; i < size - 1; i++)
{
q = q.SelectMany(x => alphabet, (x, y) => x + y);
}
foreach (var item in q)
{
if (counter >= 20000000)
{
new_file();
counter = 0;
}
if (File.Exists(path))
{
using (StreamWriter sw = File.AppendText(path))
{
sw.WriteLine(item);
Console.WriteLine(item);
/*if (!(Regex.IsMatch(item, #"(.)\1")))
{
sw.WriteLine(item);
counter++;
}
else
{
Console.WriteLine(item);
}*/
}
}
else
{
new_file();
}
}
}
static void new_file()
{
path = #"C:\" + "list" + file + ".txt";
if (!File.Exists(path))
{
using (StreamWriter sw = File.CreateText(path))
{
}
}
file++;
}
}
The Code is working fine but it takes Weeks to run it. Does anyone know a way to speed it up or do I have to wait? If anyone has a idea please tell me.
Performance:
size 3: 0.02s
size 4: 1.61s
size 5: 144.76s
Hints:
removed LINQ for combination generation
removed Console.WriteLine for each password
removed StreamWriter
large buffer (128k) for file writing
const string alphabet = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ123456789+-*_!$£^=<>§°ÖÄÜöäü.;:,?{}[]";
var byteAlphabet = alphabet.Select(ch => (byte)ch).ToArray();
var alphabetLength = alphabet.Length;
var newLine = new[] { (byte)'\r', (byte)'\n' };
const int size = 4;
var number = new byte[size];
var password = Enumerable.Range(0, size).Select(i => byteAlphabet[0]).Concat(newLine).ToArray();
var watcher = new System.Diagnostics.Stopwatch();
watcher.Start();
var isRunning = true;
for (var counter = 0; isRunning; counter++)
{
Console.Write("{0}: ", counter);
Console.Write(password.Select(b => (char)b).ToArray());
using (var file = System.IO.File.Create(string.Format(#"list.{0:D5}.txt", counter), 2 << 16))
{
for (var i = 0; i < 2000000; ++i)
{
file.Write(password, 0, password.Length);
var j = size - 1;
for (; j >= 0; j--)
{
if (number[j] < alphabetLength - 1)
{
password[j] = byteAlphabet[++number[j]];
break;
}
else
{
number[j] = 0;
password[j] = byteAlphabet[0];
}
}
if (j < 0)
{
isRunning = false;
break;
}
}
}
}
watcher.Stop();
Console.WriteLine(watcher.Elapsed);
}
Try the following modified code. In LINQPad it runs in < 1 second. With your original code I gave up after 40 seconds. It removes the overhead of opening and closing the file for every WriteLine operation. You'll need to test and ensure it gives the same results because I'm not willing to run your original code for 24 hours to ensure the output is the same.
class Program
{
static string path;
static int file = 0;
static void Main(string[] args)
{
new_file();
var alphabet = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ123456789+-*_!$£^=<>§°ÖÄÜöäü.;:,?{}[]";
var q = alphabet.Select(x => x.ToString());
int size = 3;
int counter = 0;
for (int i = 0; i < size - 1; i++)
{
q = q.SelectMany(x => alphabet, (x, y) => x + y);
}
StreamWriter sw = File.AppendText(path);
try
{
foreach (var item in q)
{
if (counter >= 20000000)
{
sw.Dispose();
new_file();
counter = 0;
}
sw.WriteLine(item);
Console.WriteLine(item);
}
}
finally
{
if(sw != null)
{
sw.Dispose();
}
}
}
static void new_file()
{
path = #"C:\temp\list" + file + ".txt";
if (!File.Exists(path))
{
using (StreamWriter sw = File.CreateText(path))
{
}
}
file++;
}
}
your alphabet is missing 0
With that fixed there would be 89 chars in your set. Let's call it 100 for simplicity. The set you are looking for is all the 8 character length strings drawn from that set. There are 100^8 of these, i.e. 10,000,000,000,000,000.
The disk space they will take up depends on how you encode them, lets be generous - assume you use some 8 bit char set that contains the these characters, and you don't put in carriage returns, so one byte per char, so 10,000,000,000,000,000 bytes =~ 10 peta byes?
Do you have 10 petabytes of disk? (10000 TB)?
[EDIT] In response to 'this is not an answer':
The original motivation is to create the list? The shows how large the list would be. Its hard to see what could be DONE with the list if it was actualised, i.e. it would always be quicker to reproduce it than to load it. Surely whatever point could be made by producing the list can also be made by simply knowing it's size, which the above shows how to work it out.
There are LOTS of inefficiencies in you code, but if your questions is 'how can i quickly produce this list and write it to disk' the answer is 'you literally cannot'.
[/EDIT]
Dear stackoverflow members,
I have this string:
string data = "1Position1234Article4321Quantity2Position4323Article3323Quantity";
I want to search for the values where the "keyword" is Position. In this case I want to get back 1 and 2. Each value is "indexed" with its own "keyword". So the value 1 in this string has the Position seperator. The value 1234 has the Article seperator and the value 4321 has the Quantity seperator.
I need a way to search through the string and want to get all positions, articles and quantitys back. Without the keywords.
Output shout be:
string[] position = {"1", "2"};
string[] article = {"1234", "4323"};
string[] quantity = {"4321", "3323"};
Hopefully some can help me here.
Thanks!
This is q quick solution I've come up with in LinqPad:
void Main()
{
string data = "1Position1234Article4321Quantity2Position4323Article3323Quantity";
var Articles = Indices(data, "Article").Dump("Articles: ");
var Posistions = Indices(data, "Position").Dump("Positions :");
var Quantities = Indices(data, "Quantity").Dump("Quantities :");
}
// Define other methods and classes here
public List<int> Indices(string source, string keyword)
{
var results = new List<int>();
//source: http://stackoverflow.com/questions/3720012/regular-expression-to-split-string-and-number
var temp = Regex.Split(source, "(?<Alpha>[a-zA-Z]*)(?<Numeric>[0-9]*)").ToList().Where (r => !String.IsNullOrEmpty(r)).ToList();
//select the list with index only where key word matches
var indices = temp.Select ((v,i) => new {index = i, value = v})
.Where (t => t.value == keyword);
foreach (var element in indices)
{
int val;
//get previous list entry based on index and parse it
if(Int32.TryParse(temp[element.index -1], out val))
{
results.Add(val);
}
}
return results;
}
Output:
Here's a possible algorithm:
Run trough the list and take each number / keyword.
Put them in a dictionary with key "keyword", value a list with all "numbers".
Iterate the dictionary and print they key + its values.
Below snippet can use to get the output like what you expected.
string data = "1Position1234Article4321Quantity2Position4323Article3323Quantity";
StringBuilder sb = new StringBuilder();
StringBuilder sbWord = new StringBuilder();
bool isDigit = false;
bool isChar = false;
Dictionary<int, string> dic = new Dictionary<int, string>();
int index = 0;
for (int i = 0; i < data.Length; i++)
{
if (char.IsNumber(data[i]))
{
isDigit = true;
if (isChar)
{
dic.Add(index, sb.ToString() + "|" + sbWord.ToString());
index++;
isChar = false;
sb.Remove(0, sb.Length);
sbWord.Remove(0, sbWord.Length);
}
}
else
{
isDigit = false;
isChar = true;
sbWord.Append(data[i]);
}
if (isDigit)
sb.Append(data[i]);
if (i == data.Length - 1)
{
dic.Add(index, sb.ToString() + "|" + sbWord.ToString());
}
}
List<string> Position = new List<string>();
List<string> Article = new List<string>();
List<string> Quantity = new List<string>();
if (dic.Count > 0)
{
for (int i = 0; i < dic.Count; i++)
{
if (dic[i].Split('|')[1] == "Position")
Position.Add(dic[i].Split('|')[0]);
else if (dic[i].Split('|')[1] == "Article")
Article.Add(dic[i].Split('|')[0]);
else
Quantity.Add(dic[i].Split('|')[0]);
}
}
string[] Position_array = Position.ToArray();
string[] Article_array = Article.ToArray();
string[] Quantity_array = Quantity.ToArray();
Try this simple solution.
class StrSplit{
public static void main(String args[]){
int i;
String str = "1Position1234Article4321Quantity2Position4323Article3323Quantity";
String pattern= "(?<=Position)|(?<=Article)|(?<=Quantity)";
String[] parts = str.split(pattern);
List<String> Position = new ArrayList<String>();
List<String> Article = new ArrayList<String>();
List<String> Quantity = new ArrayList<String>();
for( i=0;i<parts.length;i++)
{
pattern="Position";
String[] subParts;
if(parts[i].contains(pattern))
{
subParts = parts[i].split(pattern);
Position.add(subParts[0]);
}
pattern="Article";
if(parts[i].contains(pattern))
{
subParts = parts[i].split(pattern);
Article.add(subParts[0]);
}
pattern="Quantity";
if(parts[i].contains(pattern))
{
subParts = parts[i].split(pattern);
Quantity.add(subParts[0]);
}
}
System.out.println("Position:");
for(i = 0; i < Position.size(); i++) {
System.out.println(Position.get(i));
}
System.out.println("Article:");
for(i = 0; i < Article.size(); i++) {
System.out.println(Article.get(i));
}
System.out.println("Quantity:");
for(i = 0; i < Quantity.size(); i++) {
System.out.println(Quantity.get(i));
}
}
}
Output:
Position:
1
2
Article:
1234
4323
Quantity:
4321
3323
I am writing a program that uses a StudentStruct (structure) that consists of: studentID, studentName, and grades (which is a separate List). The program is supposed to read in a sequential text file and contains methods that allow the user to: Add Student, Add Grades (to a particular student), Change Student Name, and Delete Student. At the end of the program it is supposed to overwrite the previous file with the new changes made from the current program session.
My question is how do I read in data from the text file into the separate structure variables within the lists?
My text file looks like this:
00000,Mimzi Dagger,100,50,75,70,45,10,98,83
00001,Alexander Druaga,89,45,80,90,15,73,99,100,61
00002,Nicholas Zarcoffsky,100,50,80,50,75,100,100
00003,Kantmiss Evershot,50,100
Once the structure variables within the list are filled, how do I overwrite the file with the contents of the List structure in the same format as the above file?
Since I have multiple and varying amounts of grades, how would I achieve looping through and adding each grade to the grades list?
As you can maybe already tell, I am very new to c# and this is my first project. Any help would be greatly appreciated!
class Program
{
static string pathSource = #"C:\schoolfiles\StudentGrades.txt";
struct StudentStruct
{
public string studentID;
public string studentName;
public List<string> grades;
}
static void Main(string[] args)
{
StudentStruct student = new StudentStruct();
List<StudentStruct> myList = new List<StudentStruct>();
student.grades = new List<string>();
}
UPDATE: Here is what I have come up with so far:
for (int i = 0; i < fileLines.Length; i++)
{
output = fileLines[i];
string[] outputArray = output.Split(',');
student.grades = new List<string>();
student.studentID = outputArray[0];
student.studentName = outputArray[1];
for (int j = 2; j < outputArray.Length; j++)
{
student.grades.Add(outputArray[j]);
}
myList.Add(student);
UPDATE: The code above worked out wonderfully. Here is the top part of my code involving this question:
static void Main(string[] args)
{
//Declare variables
string output;
//Read the File into an array
string[] fileLines = File.ReadAllLines(PathSource);
StudentStruct student = new StudentStruct();
List<StudentStruct> myList = new List<StudentStruct>();
for (int i = 0; i < fileLines.Length; i++)
{
output = fileLines[i];
string[] outputArray = output.Split(',');
student.grades = new List<string>();
student.studentID = outputArray[0];
student.studentName = outputArray[1];
for (int j = 2; j < outputArray.Length; j++)
{
student.grades.Add(outputArray[j]);
}
myList.Add(student);
}
MainMenu(myList);
}
And then to add the list back to the file I did this:
static void ExitModule(List<StudentStruct> myList)
{
//Declare variables
string inputChoice = null;
string output = null;
System.IO.StreamWriter file = new System.IO.StreamWriter(PathSource);
Console.Clear();
Console.WriteLine("Are You Sure You Want To Exit The Program? Y/N");
inputChoice = Console.ReadLine();
if (inputChoice == "Y" || inputChoice == "y")
{
for (int i = 0; i < myList.Count; i++)
{
output = (myList[i].studentID + "," + myList[i].studentName);
for (int j = 0; j < myList[i].grades.Count; j++)
{
output += ("," + myList[i].grades[j]);
}
file.WriteLine(output);
}
file.Close();
Environment.Exit(0);
Since this is clearly homework, it may be a good time for you to learn about data structures. This will help you store the information you've read in from the text file efficiently, allowing you to write it out much more easily after modifying the records.
Here are a couple of other random pointers:
The System.IO.File.ReadLines(pathSource) method would be a good place to start reading each line of a text file
You should almost never be using a struct in C# (especially one that is mutable like in your example) unless you are well-versed in its semantics and purpose. Use a class instead
try this code. it's working for me
class Program
{
static string pathSource = #"C:\schoolfiles\StudentGrades.txt";
struct StudentStruct
{
public string studentID;
public string studentName;
public List<string> grades;
}
static void Main(string[] args)
{
StudentStruct student = new StudentStruct();
List<StudentStruct> myList = new List<StudentStruct>();
student.grades = new List<string>();
// get all lines from text file
string[] allLinesFromFile = File.ReadAllLines(pathSource);
// iterate through each line and process it
foreach(string line in allLinesFromFile)
{
// split each line on ','
string[] sections = line.Split(',');
student.studentID = sections[0];
student.studentName = sections[1];
// use this loop to add numbers to list of grades
for(int i =2; i < sections.Length; i++)
{
student.grades.Add(sections[i]);
}
// add this student to list
myList.Add(student);
// create new object of student
student = new StudentStruct();
student.grades = new List<string>();
}
}
A few things.
(1) I am not sure why your teacher/professor would have you use a struct here. A class is much more appropriate. I actually cringed when I first saw the code
(2) having something as a const also implies that it is static "pathSource"
(3) Properties should be capitalized "pathSource" -> "PathSource"
(4) You should separate responsibilities... Try not to put everything in Main
(5) You shouldn't have to create an instance of grades outside of StudentStruct, this can lead to errors. i.e. NullPointerException... basically the struct should be self containing.
(6) Everything should compile. I haven't tested it. If you have any issues. let me know.
Program {
private const string PathSource = #"C:\schoolfiles\StudentGrades.txt";
private struct StudentStruct
{
public string StudentID;
public string StudentName;
private List<string> _gradeList;
public List<string> GradeList
{
// if _gradeList is null create a new instance
get { return _gradeList ?? (_gradeList = new List<string>()); }
private set { _gradeList = value; }
}
}
private static void Main( string[] args )
{
var studentFile = File.ReadAllLines( PathSource );
// If you haven't learned about delegates or extensions methods...
// You can just change it to a foreach statement
var myList = studentFile.Select( GetStudent ).ToList();
// make sure we have everything
foreach (var studentStruct in myList)
{
Console.WriteLine( "{0} {1}", studentStruct.studentName, studentStruct.studentID );
foreach (var grade in studentStruct.GradeList) { Console.Write( grade + " " ); }
Console.WriteLine();
}
}
private static StudentStruct GetStudent( string line )
{
var student = new StudentStruct();
var studentDelimited = line.Split( ',' );
student.studentID = studentDelimited[ 0 ];
student.studentName = studentDelimited[ 1 ];
for ( int i = 2; i < studentDelimited.Length; i++ ) { student.GradeList.Add( studentDelimited[ i ] ); }
return student;
}
}