0

So some reason a loop that is meant to populate an array with is not running and I am not sure why. I am reading data from a text files that contains the following data.

Jazz
Jets
Owls
Rams
Cubs
Zips

this file is called Names.txt I am reading it in and assigning that to an array. I am then passing it to a sub to popular an array structure but the loop does run and I do not understand why.

Option Strict On
Public Class frmScoccer




    Public Structure Team
        Dim name As String
        Dim wins As Integer

    End Structure

    Dim output As Team() 'this is going to be holder for the output data. 


    Private Sub frmScoccer_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        'this is going to be doing everything that needs to be done at load time. 
        Dim grabNames() As String = IO.File.ReadAllLines("Names.txt") 'this is to pull the names from the text file. 
        Dim names() As String 'this is going to be the array that holds the names. 
        'this is going assigned the names to the array

        Dim grabWins() As String = IO.File.ReadAllLines("Wins.txt") 'this is going to be used to grab the data on wins before it is assigned to the array. 
        Dim wins(,) As String 'this is going to hold wins and loses.

       ' output(2).name = "bacon" 'this is just for troubleshooting and does not serve a purpose. 
        nameAssignment(grabNames, output)
        ' winAssignment(grabWins, wins)

        '  countIf(wins, output) 'this is going to count the number of wins per team. 




    End Sub

    Sub countIf(wins(,) As String, ByRef output As Team())
        'this is going to bring the win counter up for a team if the value is true.

        For row As Integer = 0 To (wins.GetUpperBound(0))
            output(row).wins = 0
            For column As Integer = 0 To (wins.GetUpperBound(1))
                If wins(row, column) = "true" Then
                    output(row).wins += 1
                End If
            Next
        Next

    End Sub

    Sub nameAssignment(grabNames() As String, ByRef output() As Team)
        'this is goning to be a way to get the names from the input array to the useable array. 

        For Each team In grabNames
            MessageBox.Show("loop is running")
            output(CInt(team)).name = grabNames(CInt(team))

        Next



    End Sub

    Sub winAssignment(grabWins() As String, ByRef wins(,) As Integer)
        Dim line, data() As String
        For row As Integer = 0 To (grabWins.GetUpperBound(0))
            line = grabWins(row)
            data = line.Split(","c)
            For column As Integer = 0 To (grabWins.GetUpperBound(1))
                wins(row, column) = CInt(data(column))
            Next
        Next
    End Sub

    Private Sub btnDisplay_Click(sender As Object, e As EventArgs) Handles btnDisplay.Click
        'this is going to display the output

        Dim query = From win In output
                    Order By win.wins Descending
                    Select win
        For Each win In query
            dgvTeamWins.DataSource = query.ToList
            dgvTeamWins.CurrentCell = Nothing

            dgvTeamWins.Columns("name").HeaderText = "Team"
            dgvTeamWins.Columns("wins").HeaderText = "Wins"
        Next

    End Sub

    Private Sub btnTesting_Click(sender As Object, e As EventArgs) Handles btnTesting.Click
        'this is going to be for fast trouble shooting. 
        MessageBox.Show(output(2).name.ToString)
    End Sub

End Class

It looks like it should work because a for each loop should run for each line of information correct? Am I not understanding how a for each loop works, am I not properly formatting my data file/reading it wrong?

I know it is not working because when I run my test looking for output(1).name I get a null reference error, I know the loop is not running because the messagebox in the loop never triggers.

Please forgive the messageboxes, they are what I use to try to find out where errors are happening.

Any ideas on where my logic is wrong?

Grimmjow56
  • 19
  • 1
  • 1
  • 9
  • @plutonix, I know what a Null reference is, I know what is causing it I am asking why the loop in nameAssignment() is not triggering. My question is not the same as the one you have posted. Please mark it as such because I know what is causing the null reference I am asking how to fix the loop. Not the reference. – Grimmjow56 Apr 14 '17 at 20:49
  • 1
    Your message box line is never hit because it throws an NRE on the line before that: `output(team).name = grabNames(team)`. The class-level `output` variable has not been initialized. – Visual Vincent Apr 14 '17 at 22:15
  • 1
    I agree to an extent that it's not a simple duplicate, but there are just too many things going wrong here. `Dim output() As Team` is an empty array. The first thing you do with it is `output(team).name = grabNames(team)`. There are a few things wrong with this. 1. You are indexing the array with a string instead of an integer. 2. The array isn't even populated yet anyway. 3, 4, 5, 6.... There are innumerable other type mismatches throughout your code. Put this at the top of your code file: `Option Strict On` and first fix the errors reported by the IDE. Then ask a specific question – djv Apr 14 '17 at 22:17
  • @djv Apologies. I thought I had turned Option Strict on in the default settings. I guess I hadn't on my personal laptop. After doing that I have corrected all the IDE errors but the loop still never triggers. I am thinking it is the way I am reading in data is wrong but I have added a trouble shooting line that assigned output(2).name = "bacon" and it still gives me a null reference when I call that. Have I made my output array wrong? I have posted my corrected code after strict was turned on. – Grimmjow56 Apr 14 '17 at 23:08
  • @VisualVincent I have been googling but I can't see to grasp an understanding how do you initialize structures? I have been looking at examples like this but I am not understanding the answer provided. https://bytes.com/topic/visual-basic-net/answers/364772-default-value-structures Apologies for such lower level questions. The professor did not cover this and my google skills are providing me with answers I do not understand. – Grimmjow56 Apr 14 '17 at 23:08
  • Structures are initialized automatically. They're so-called _value types_ so they must always have a value (they cannot be null). In this case it is _**the array**_ that you need to initialize. – Visual Vincent Apr 14 '17 at 23:14
  • [**How to: Initialize an Array Variable in Visual Basic**](https://msdn.microsoft.com/en-us/library/y13tek7e.aspx). – Visual Vincent Apr 14 '17 at 23:17
  • @VisualVincent I am feeding it in from a text file. If I were to just add the information i needed in the code it would defeat the purpose of the assignment. I am not really sure how to do the first initialization with the text file which is why I have nameAssignment() assigning each sub in the array. Is that not what I am supposed to do? – Grimmjow56 Apr 14 '17 at 23:31
  • You don't need to hardcode any values, but you need to initialize the array to a certain size: `output = New Team(grabNames.Length - 1) {}`. – Visual Vincent Apr 14 '17 at 23:35
  • An array is always of the same size, therefore if you haven't declared it with a specific size then the array is not initialized. Because of this, the only way to resize an array is to create a new one and copy the old contents. – Visual Vincent Apr 14 '17 at 23:40
  • @VisualVincent I changed the declaration to `Dim output((IO.File.ReadAllLines("Names.txt").Count)) As Team` and I changed the loop to `For i As Integer = 0 To grabNames.Count output(CInt(i)).name = grabNames(CInt(i)) MessageBox.Show(output(CInt(i)).name) Next` but it still does not populate the loop. I am able to assign information to the array now, and I know that I am getting the proper stopping number so what is causing the loop to fail? – Grimmjow56 Apr 14 '17 at 23:58
  • First of all, _**do not read the file twice!**_ That's just a waste of resources, see my edited comment instead. -- **Secondly**, your loop must end at `grabNames.Length - 1` or else it will go out of bounds (also `Length` is the correct property for arrays, `Count` is for collections or `List(Of T)`s). -- **Thirdly**, `CInt(i)` is redundant, `i` is already an integer. -- **Fourthly**, initialize the array when you read the file, and not before that. Doing so will ensure that it is always of the correct size when you do your operations. – Visual Vincent Apr 15 '17 at 00:08
  • @VisualVincent Alright. Thank you for your time. I finally got it working. to prevent the file form having to be read twice. I moved `Dim grabNames() As String = IO.File.ReadAllLines("Names.txt")` out of the load sub and above my output() declaration. That way I can use the .length. So now I have `Dim grabNames() As String = IO.File.ReadAllLines("Names.txt") Dim output(grabNames.Length - 1) As Team Private Sub frmScoccer_Load(sender As Object, e As EventArgs) Handles MyBase.Load` That part of my program works now. – Grimmjow56 Apr 15 '17 at 00:19
  • Glad I could help. Your issue was most likely that you were looping to `Count` instead of `Count - 1` (or which it should've been: `Length - 1`). The `Load` event has a tendency to swallow all errors that are thrown in the code executed by it, thus you most likely never saw that the loop went out of bounds. – Visual Vincent Apr 15 '17 at 00:25
  • I will admit I continually forget about things being zero base at times as well so that didn't help. – Grimmjow56 Apr 15 '17 at 00:42
  • 1
    @VisualVincent I feel the need to mention this vb exclusive, [ReDim](https://msdn.microsoft.com/en-us/library/w8k3cys2.aspx) – djv Apr 15 '17 at 05:31
  • @djv : ...`Preserve` creates a new array and copies the elements to it, just like [**`Array.Resize()`**](https://msdn.microsoft.com/en-us/library/bb348051(v=vs.110).aspx). – Visual Vincent Apr 15 '17 at 09:46

0 Answers0