REAL-WORLD COMPUTER PROGRAMMING FOR KIDS
STEP 16: OF LISTS, SPLITS, AND FOREACHES (OR, THE RETURN OF BILLYGOAT BUTTHEAD)
It’s time! It’s time! We are finally going to read the CSV files we created into our app. Here’s how we will do it:
1) At the top of Form1.cs, add the following in with the other “uses” clauses:
using System.Collections.Generic;
using System.Text;
These “uses clauses” are added so that we can use a List and Split. What?!? You’ll find out below...
2) Add this above the const declarations (and below the bool variable):
List<MultipleChoiceClass> mccList;
This is an interesting data type: a List (which is a type of collection, sort of like an array). It is a List of our custom Class MultipleChoiceClass. In other words, any number of MultipleChoiceClass “instances” (cookies from the recipe) are saved into the List named mccList. So the List itself (the bag we keep the cookies in) is named mccList, but it contains multiple instances (“copies”) of MultipleChoiceClass.
So, we will create multiple instances of our custom class (one for each line in the CSV file we load), populate them with data, and then add them to the List named mccList. You can also think of a List as a special type of array; a “value-added” array that is easy to work with.
3) Add the following code into the cmbxSelectMultiChoiceFile_SelectedIndexChanged event handler so that it ends up looking like this:
private void cmbxSelectMultiChoiceFile_SelectedIndexChanged(object sender, EventArgs e)
{
string selectedFile = string.Empty;
string[] fileStrArray;
MultipleChoiceClass mcc;
mccList = new List<MultipleChoiceClass>();
const int QUESTION = 0;
const int CANDIDATEANSWER1 = 1;
const int CANDIDATEANSWER2 = 2;
const int CANDIDATEANSWER3 = 3;
selectedFile = cmbxSelectMultiChoiceFile.SelectedItem.ToString();
try
{
fileStrArray = File.ReadAllLines(
selectedFile, Encoding.UTF8);
foreach (string line in fileStrArray)
{
string[] subPhrases = line.Split(',');
mcc = new MultipleChoiceClass();
mcc.Question = subPhrases[QUESTION];
mcc.CandidateAnswer1 = subPhrases[CANDIDATEANSWER1];
mcc.CandidateAnswer2 = subPhrases[CANDIDATEANSWER2];
mcc.CandidateAnswer3 = subPhrases[CANDIDATEANSWER3];
if (mcc.CandidateAnswer1.Contains("*"))
{
mcc.CorrectAnswer = 1;
mcc.CandidateAnswer1 = mcc.CandidateAnswer1.Substring(1);
}
else if(mcc.CandidateAnswer2.Contains("*"))
{
mcc.CorrectAnswer = 2;
mcc.CandidateAnswer2 = mcc.CandidateAnswer2.Substring(1);
}
else if (mcc.CandidateAnswer3.Contains("*"))
{
mcc.CorrectAnswer = 3;
mcc.CandidateAnswer3 = mcc.CandidateAnswer3.Substring(1);
}
} // foreach
} // try
catch (Exception ex)
{
MessageBox.Show(ex.Message);
throw;
}
}
There’s obviously a lot going on here. In a nutshell, this code fires (runs) after the user has selected a CSV file from the ComboBox (which ultimately triggers the ComboBox’s “SelectedIndexChanged” event, causing this code to run).
Let’s examine what the code does now. First (after the declaration of the local variables and constants), the name of the file selected is stored in the string variable selectedFile for future reference using this code:
selectedFile = cmbxSelectMultiChoiceFile.SelectedItem.ToString();
Note: Before we go any further, note the declaration of variables and constants at the beginning of the cmbxSelectMultiChoiceFile_SelectedIndexChanged event handler. Just as these variable and constant declarations can be made at the top of the code (where they are “global,” or generally accessible, everywhere within the form), you can (and do, often) declare variables and constants within methods and event handlers, too. When you do that, they are “local” (only visible to that block of code). Note, too, that we didn’t name this event handler ourselves. Visual Studio named it automatically, by using the Control’s name (cmbxSelectMultiChoiceFile), inserting an underscore (_), and then appending the name of the event that is being triggered (SelectedIndexChanged).
To continue examining the code, the file selected by the user is then loaded into the string array using this line of code:
fileStrArray = File.ReadAllLines(selectedFile, Encoding.UTF8);
This code is probably fairly easy to read: All the lines (contents) of the selected file are read, and assigned to the string array variable. But if you’re still struggling with wrapping your head around it, that’s okay. It takes time. Besides, you don’t really need to “get it” all just yet, anyway.
You can always come back and re-read sections you found tough later. You might be surprised how much easier it sinks in on subsequent readings, after acquiring a more rounded out understanding of what’s going on.
Next, the foreach loop iterates over every line from the file, which is now in our string array:
foreach (string line in fileStrArray)
The next thing that happens (within the foreach loop) is the line from the file is split into separate lines on each comma:
string[] subPhrases = line.Split(',');
Here the string array subPhrases ends up being populated with the contents of the line, but with each element (separated from the elements that come before it and after it by commas) on its own separate line.
So the line:
Which of the following was a member of the Australian rock ’n’ roll outfit named “Little River Band”?,*Beeb Birtles,Billygoat Butthead,Bix Biederbeck
...is split apart on the commas and populated into the subPhrases array of string like so:
Which of the following was a member of the Australian rock ’n’ roll outfit named “Little River Band”?
*Beeb Birtles
Billygoat Butthead
Bix Biederbeck
As you can see, the original line is now “spread out” (or “spread down”) over four lines.

Photo by Martina Nolte
Still with me? Okay, take a deep breath now. In fact, if you’re feeling a bit overwhelmed or woozy, and feel like you need a break, go ahead and take one. If it’s possible for you, and safe to do so, get a little fresh air and exercise. Walk around the block, or around your house -- or around the world, if you have the time and energy to do so. Take one or both of your parents, or at least your dog or duckbilled platypus with you, though; we don’t want you out there on your own.
Note: In fact, it’s always a good idea to take frequent breaks when programming, for your brain as well as the rest of your body. Sitting in one spot for extended periods of time can lead to gluteus maximus syndrome (which is medical science’s technical jargon for “your butt might fall asleep”). Even worse, perhaps, your head will feel foggy and mushy and resistant to embracing new thoughts. Give the poor pinkish-grey wrinkly thing a breather (I’m talking about your brain here). At least get up and do some stretches, like this cat:

Photo of stretching Siberian Tiger by I, Malene / CC BY-SA (http://creativecommons.org/licenses/by-sa/3.0/)
Note: In this case, the cat under discussion is an actual feline (in case you didn’t notice). So there are two kinds of cats: felines of various sizes and color schemes and patterns, and adult human males. This is called “overloading” a word (the word is “overloaded” in that the same word has multiple meanings). Overloading is also a programming concept that we will explore later.
Okay, so now you’re nice and refreshed and ready to dive in again. There’s just a little more code to go through, and then we’ll sign off for this Step.
Remember that in programming, we start counting at/from zero (0)? The first line in the string array is at position 0. That is the question element (the first part of the line). The second line in the string array is Candidate Answer 1, at position 1; the third line in the string array is Candidate Answer 2, at position 2; and finally, the fourth line in the string array is Candidate Answer 3, at position 3.
With that in mind, it becomes clear why we declared these four constants above:
const int QUESTION = 0;
const int CANDIDATEANSWER1 = 1;
const int CANDIDATEANSWER2 = 2;
const int CANDIDATEANSWER3 = 3;
Onward. We now create an instance of our custom Class using this code:
mcc = new MultipleChoiceClass();
So, to continue with the earlier analogy, we use the “recipe” (MultipleChoiceClass) to bake a cookie (mcc).
This allows the elements from the line (now each on their own line in the subPhrases string array) to be assigned to mcc’s members like this:
mcc.Question = subPhrases[QUESTION];
mcc.CandidateAnswer1 = subPhrases[CANDIDATEANSWER1];
mcc.CandidateAnswer2 = subPhrases[CANDIDATEANSWER2];
mcc.CandidateAnswer3 = subPhrases[CANDIDATEANSWER3];
What’s happening here? subPhrases[QUESTION] equates to subPhrases[0], as the constant (“const”) QUESTION is assigned the value of 0. So the Question member of the mcc Class instance is being assigned the zeroeth element in subPhrases (the Question). And so on.
One final section of code is our old friend, the “if...else” block:
if (mcc.CandidateAnswer1.Contains("*"))
{
mcc.CorrectAnswer = 1;
mcc.CandidateAnswer1.Substring(1);
}
else if (mcc.CandidateAnswer2.Contains("*"))
{
mcc.CorrectAnswer = 2;
mcc.CandidateAnswer2.Substring(1);
}
else if (mcc.CandidateAnswer3.Contains("*"))
{
mcc.CorrectAnswer = 3;
mcc.CandidateAnswer3.Substring(1);
}
Here, the last member of the MultipleChoiceClass (CorrectAnswer) is populated by examining the three Candidate Answers. The question is, which one has the “*” prepended to it, indicating that it’s the correct answer? We look for it by this code:
if (mcc.CandidateAnswer1.Contains("*"))
If the Candidate Answer that we are examining does contain a “*”, we assign the corresponding value to our custom Class’s CorrectAnswer member.
Then (since we don’t want the “*” to remain as part of the string and tip off the user that it is different from the other answers when we display it to him in the radio button), we remove that first character from the string with this code:
mcc.CandidateAnswer3 = mcc.CandidateAnswer3.Substring(1);
The Substring() function returns a subset of the string, starting from the position passed in the argument (1). As 0 is the first element, and “*” is the first element, that is stripped out; everything after the “*” (from element 1 on, the second element) is then assigned to the CandidateAnswer member. So, for example, “*Beeb Birtles” becomes “Beeb Birtles.”
Once the “*” is found in one of the Candidate Answers, any remaining “else” parts of the code are ignored, or skipped; they only run if the “*” has not been found yet.
There is actually one more piece of the code to be discussed (the “try...except” block), but that is a big and important enough topic to leave for the next Step.
Until then!
Earth-shakingly Important Notice: If you have a basic programming question (suitable to an audience of “Kids”), send it to idiolectable@gmail.com, specifying whether you would like your name and location used if it is printed in a future “Step” of this newsletter. If you are a subscriber to the newsletter, you can also leave a question at the bottom of this Step, in the “Comments” section.
If you do not want to give your real name, a nickname is acceptable (the first “Letter to the Editor” of mine that was printed appeared in Rolling Stone magazine, back in the early 1970s, and I signed it “Sylvester” for some reason which I no longer remember).
Also, it’s always interesting to see where people are from, so please provide your City or Town and the State it’s in, too (or Province, or whatever the region where you live is called).
To listen to this Step, the audio of it can be found here: