How to check empty array - arrays

I am working in VB.net where i have class like below:
Public Class vertex
Public wasVisited As Boolean
Public name, type As String
Public x_pos, y_pos As Double
Public Sub New(ByVal x_pos As Double, ByVal y_pos As Double, ByVal name As Integer, ByVal type As String)
Me.x_pos = x_pos
Me.y_pos = y_pos
Me.name = name
Me.type = type
wasVisited = False
End Sub
End Class
I have object of some other class named as "graph" where in constructor of graph class I am calling constructor of vertex class.
I have array of vertex class: Public vertices() As vertex
And redim vertices(2000): resizing array again for some reason.
Now, when i loop the array to check empty value it throws an error:
Object reference not set to an instance of an object. (Since value contains "nothing")
even though i am checking like this,
If (vertices(i).name) Is Nothing Then
Exit For
End If
How can i check empty element of array?

Since you seem to want your collection be dynamic, a List(Of vertex) would serve you better. that along with a default New() constructor and you can add, remove, sort, search, whatever you need. To check for any empty value you can use If Vertices(i).name = "" then
Public Class vertex
Public wasVisited As Boolean
Public name, type As String
Public x_pos, y_pos As Double
Public Sub New()
wasVisited = False
name = ""
type = ""
x_pos = 0
y_pos = 0
End Sub
Public Sub New(ByVal x_pos As Double, ByVal y_pos As Double, ByVal name As String, ByVal type As String)
Me.x_pos = x_pos
Me.y_pos = y_pos
Me.name = name
Me.type = type
wasVisited = False
End Sub
End Class
Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
Dim Vertices As New List(Of vertex)
For I = 0 To 99
Vertices.Add(New vertex())
Vertices(I).name = "Test" + I.ToString
Next
End Sub

What's the size of vertices() before the redim operation ? If it's less than 2000, then the added elements will be Nothing right after the array enlargement, therefore when you try to access the name property of vertices(i) for values of i that go beyond the initial array size you're actually trying to dereference a null object reference.
You either need to check that vertices(i) IsNot Nothing before testing for the value of its properties or make sure every element of the array is assigned a new vertex object.
If vertices(i) Is Nothing OrElse vertices(i).name Is Nothing Then
Exit For
End If
Here's a thread on vbforums about a similar problem: http://www.vbforums.com/showthread.php?546668-RESOLVED-Redim-array-of-objects

Have you tried:
If Not vertices Is Nothing AndAlso Not vertices(i) Is Nothing _
AndAlso Not vertices(i).name Is Nothing Then
Dim value as string= vertices(i).name
End If

Related

How do I read and write this array of structure to/from a file?

I'm trying to write the array persons to a file and read it and have no clue on how to go about it. Here's my code:
Public Class Form1
Structure Person
Public name As String
Public height As Integer
Public weight As Double
End Structure
Dim persons(49) As Person
Dim arraySize As Integer = 0
Private Sub submitBtn_Click(sender As Object, e As EventArgs) Handles submitBtn.Click
If arraySize < 50 Then
Dim Name As String
Dim Height As Integer
Dim Weight As Double
Name = nameTxt.Text
Height = CInt(heightTxt.Text)
Weight = CDbl(weightTxt.Text)
nameTxt.Text = Nothing
heightTxt.Text = Nothing
weightTxt.Text = Nothing
arraySize += 1
persons(arraySize).name = Name
persons(arraySize).height = Height
persons(arraySize).weight = Weight
Else
MsgBox("The list of people is full now. You may no longer enter new people.")
End If
End Sub
Private Sub saveBtn_Click(sender As Object, e As EventArgs) Handles saveBtn.Click
End Sub
Private Sub readBtn_Click(sender As Object, e As EventArgs) Handles readBtn.Click
End Sub
End Class
Any help on how to code this would be appreciated. Thank you!
I tried coding it to save the array persons (which is linked to the structure Person) to a file, but the app freezes, and i am not sure how to get around it.
try to use list :
Public Class Form1
<Serializable()> Structure Person
Public name As String
Public height As Integer
Public weight As Double
End Structure
dim persons As List(Of Person)
Private Sub submitBtn_Click(sender As Object, e As EventArgs) Handles submitBtn.Click
If persons.length < 50 Then
Dim Name As String
Dim Height As Integer
Dim Weight As Double
Name = nameTxt.Text
Height = CInt(heightTxt.Text)
Weight = CDbl(weightTxt.Text)
nameTxt.Text = Nothing
heightTxt.Text = Nothing
weightTxt.Text = Nothing
person.name = Name
person.height = Height
person.weight = Weight
persons.add(person)
Else
MsgBox("The list of people is full now. You may no longer enter new people.")
End If
End Sub
Private Sub saveBtn_Click(sender As Object, e As EventArgs) Handles saveBtn.Click
Using fs As New IO.FileStream("d:\backup\persons.dat", IO.FileMode.Create)
Dim formatter As New BinaryFormatter
formatter.Serialize(fs, persons)
End Using
End Sub
Private Sub readBtn_Click(sender As Object, e As EventArgs) Handles readBtn.Click
Using fs As New IO.FileStream("d:\backup\persons.dat", IO.FileMode.Open)
Dim formatter As New BinaryFormatter
persons = DirectCast(formatter.Deserialize(fs), List(Of person))
End Using
End Sub
dont forget to add <Serializable()> in front of struc definition.

What is the type of JSON Array in JSON.Net?

I have following json data:
{
"cgFinishing": {
"a3colorfn": [{
"type": "Cacah",
"kode": "CCH"
},
{
"type": "Cutting",
"kode": "CUT"
}
]
}
}
And my JSON Class:
Public Class A3colorfn
Public Property type As String
Public Property kode As String
End Class
Public Class CgFinishing
Public Property a3colorfn As A3colorfn()
End Class
Public Class CGSave
Public Property cgFinishing As CgFinishing
End Class
I want to write a method in VB.NET that pull values from this JSON array using JSON.NET. This code works for me:
Public Sub fillCBfromJson(ByVal cb As ComboBox, json As Object, Optional ByVal value As String = "", Optional display As String = "")
....
End Sub
But I'd like to replace json As Object with something that are more specific, because I'd like to retrieve the count of items in the array (something like Count or GetLength, I cannot expose those property with Object type)
For your reference this code works for me...
Dim count As Integer = jsonObj.cgFinishing.a3colorfn.GetLength(0)
But I have no idea to turn it as a method.
Any help is appreciated.
More code listing:
Private Sub PublishDigital_Load(sender As Object, e As System.EventArgs) Handles MyBase.Load
jsonPath = Application.StartupPath + "\Addons\CG_Tools\cgSave.json"
jsonObj = JsonConvert.DeserializeObject(Of CGSave)(File.ReadAllText(jsonPath))
initfinishingA3()
End Sub
Public Sub initfinishingA3() 'I want to make this as a method, so I'll only need to input the Array object as argument.
Dim cbdata As Object = jsonObj.cgFinishing.a3colorfn '<- I want to put this line as argument instead
Dim count As Integer = jsonObj.cgFinishing.a3colorfn.GetLength(0)
Dim myCb As New List(Of CheckBox)
For Each cur In cbdata
Dim cb = New CheckBox()
tb_finishinga3.Controls.Add(cb)
Dim txt As JObject = JsonConvert.DeserializeObject(Of JObject)(JsonConvert.SerializeObject(cur))
...
cb.Text = txt("type")
...
Next
End Sub
Following method I wrote does not work..
Public Sub fillTabwithCB(ByVal cbdata As JArray, XOffset As Integer, YOffset As Integer, maxRow As Integer)
Dim count As Integer = cbdata.Count
Dim loopIndex As Integer
Dim i As Integer = 0
Dim myCb As New List(Of CheckBox)
For Each cur In cbdata
Dim cb = New CheckBox()
tb_finishinga3.Controls.Add(cb)
Dim txt As JObject = JsonConvert.DeserializeObject(Of JObject)(JsonConvert.SerializeObject(cur))
.........
cb.Text = txt("type")
..........
Next
End Sub
Then I tried it in this line...
fillTabwithCB(jsonObj.cgFinishing.a3colorfn, 7, 7, 5)
It generates following error:
Value of type '1-dimensional array of
CG_FileManagement.A3colorfn' cannot be converted to
'Newtonsoft.Json.Linq.JArray'.

Why is the index out of range when the size is defined by a variable?

When I define the size of an integer array using a variable I get the error: "IndexOutOfRangeException was unhandled". However, if I just put the same value as the variable that I used, it works.
I'll explain it in comments better below:
Public Class Form1
Dim test As Test
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
test = New Test(5) 'the length property is test is 5
test.AddToList()
End Sub
End Class
Public Class Test
Dim _length As Integer
Public Property length() As Integer
Get
Return _length
End Get
Set(ByVal value As Integer)
_length = value
End Set
End Property
Dim _magnitude(length, 2) As Integer 'Size is length, which should be equal to 5. If I remove length and just put 5, it works fine.
Public Property magnitude As Integer(,)
Get
Return _magnitude
End Get
Set(ByVal value As Integer(,))
_magnitude = value
End Set
End Property
Public Sub New(ByVal lengthp As Integer)
length = lengthp 'Sets 5 to the length property.
End Sub
Public Sub AddToList()
magnitude(4, 0) = 4 'Operates on the magnitude property. This is where the error is located.
Debug.Print(magnitude(4, 0))
End Sub
End Class
Hopefully you guys understand what I'm asking.
Private fields are initialized prior to the constructor. When you instantiate the class, _magnitude is initialized before length is set, so what you get is the equivalent of Dim _magnitude(0, 2) As Integer.
Try changing your declaration to something like:
Dim _magnitude(,) As Integer
'...
Public Sub New(ByVal lengthp As Integer)
length = lengthp
ReDim _magnitude(lengthp, 2) As Integer
End Sub
You also talk about length, so you should keep in mind that you're specifying the upper bound of the array, not the length.
The Dim statement for the _magnitude member variable occurs before the constructor. Change your code as follows:
Dim _magnitude(,) As Integer '<<Changed. Don't set the bounds here, just declare the variable
Public Property magnitude As Integer(,)
Get
Return _magnitude
End Get
Set(ByVal value As Integer(,))
_magnitude = value
End Set
End Property
Public Sub New(ByVal lengthp As Integer)
length = lengthp 'Sets 5 to the length property.
ReDim _magnitude(length, 2) '<<Added. Set the bounds AFTER the length property has been set
End Sub

Need help searching an array... very hard for me

Got a small problem. I don't know how to search one array so I can pull that same array number from the other 2 arrays. I know how to test for a lot of stuff so that won't be a problem.
The end result on this project is the user will place the amount they are willing to pay for a make of the car and the page will display the data. HOWEVER I don't know how to search the carArray() to find the index number and use that index number to find the other stuff. I did find something that did this (somewhat) earlier but I don't know how to modify it for me to keep that index number as a int and use it to search and display the other arrays.
I will need this in future projects later.
Public Class paymentPage
Private Sub car_TextChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles car.TextChanged
End Sub
Private Sub price_TextChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles price.TextChanged
End Sub
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Dim carArray() As String = {"Ford", "Chevy", "Mazda"}
Dim sellAmount() As Decimal = {32700, 35625, 24780}
Dim leaseAmount() As Decimal = {425, 505, 385}
End Sub
End Class
Why not make this a class object? Easier to reuse later.
Public Class Car
Public Property Make As String
Public Property Value As Double
Public Property Lease As Double
End Class
Then make a collection of them:
Private cars As New List(Of Car)
cars.Add(New Car With {.Make = "Ford", .Value = 32700, .Lease = 425})
cars.Add(New Car With {.Make = "Chevy", .Value = 35625, .Lease = 505})
cars.Add(New Car With {.Make = "Mazda", .Value = 24780, .Lease = 385})
For your requirements:
Private Function getIndexByName(make As string) As Integer
Dim result As Integer = -1
For i As Integer = 0 To carArray.Length -1
If carArray(i) = make Then
result = i
Exit for
End If
Next
Return Result
End Function
Usage:
Dim mazdalease = leaseAmt(getIndexByName("Mazda"))
Dim cars as new List(Of Car)({car1,car2,car3})
Dim indexOfCar2 = Array.IndexOf(cars.ToArray(),car2)
Since its dirt simple to convert to an array then you can use the built in function. Keep in mind that you need to override GetHash and Equals to get this to work properly.

WinForm: Obtain values from selected items in a List Box

How do I obtain the values (not displayed text) of all the selected items in a List Box?
My intention is to use the values (which represent primary and foreign keys in my databases) to assemble a sql query.
Specs: Using WinForm with a .Net Framework v.4
You can also use any object you like in a list box. Small example below, but to test you'll have to create a form with a ListBox and button on it.
Same idea as the dictionary but this will work with more complex objects.
Public Class Form1
Dim tests As New List(Of Test)
Class Test
Private _Key As Integer
Public Property Key() As Integer
Get
Return _Key
End Get
Set(ByVal value As Integer)
_Key = value
End Set
End Property
Private _value As String
Public Property Value() As String
Get
Return _value
End Get
Set(ByVal value As String)
_value = value
End Set
End Property
End Class
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
With tests
.Add(New Test With {.Key = 1, .Value = "Val1"})
.Add(New Test With {.Key = 2, .Value = "Val2"})
.Add(New Test With {.Key = 3, .Value = "Val3"})
End With
ListBox1.SelectionMode = SelectionMode.MultiSimple
ListBox1.DisplayMember = "Value"
For Each t In tests
ListBox1.Items.Add(t)
Next
End Sub
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
For Each t As Test In ListBox1.SelectedItems
Debug.WriteLine(t.Key)
Next
End Sub
End Class

Resources