Я стараюсь опережать своих учеников на 12-м курсе по программному обеспечению. Приступаем к работе с записями и массивами. Я ответил на вопрос, но решение кажется очень неуклюжим. Я надеюсь, что у кого-то есть предложения / ссылки для более эффективного выполнения этой задачи. Задача: прочитать строки из текстового файла и преобразовать их в структуру, а затем перебрать ее, заполнив четыре списка, если животное не было вакцинировано. Вот код:
Imports System.IO
Public Class Form1
'Set up the variables - customer record, total pets not vaccinated, total records in the file, and a streamreader for the file.
Structure PetsRecord
Dim custName As String
Dim address As String
Dim petType As String
Dim vacced As String
End Structure
Dim totNotVac As Integer
Dim totalRecCount As Integer
Dim PetFile As IO.StreamReader
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
End Sub
Private Sub btnLoad_Click(sender As Object, e As EventArgs) Handles btnLoad.Click
'set an array of records to store each record as it comes in. Limitation: you need to know how many records in the file. Set the array at 15 to allow for adding more in later.
Dim PetArray(15) As PetsRecord
'variables that let me read in a line and split it into sections.
Dim lineoftext As String
Dim i As Integer
Dim arytextfile() As String
'tell them what text file to read
PetFile = New IO.StreamReader("patients.txt")
totNotVac = 0
Try
totalRecCount = 0
' read each line in and split the lines into fields for the records. Then assign the fields from the array. Finally, reset the array and loop.
Do Until PetFile.Peek = -1
'read in a line of text
lineoftext = PetFile.ReadLine()
'split that line into bits separated by commas. these will go into the array.
arytextfile = lineoftext.Split(",")
'dunno whether this is the best way to do it, but stick the array bits into the record, and then clear the array to start again.
PetArray(totalRecCount).custName = arytextfile(0)
PetArray(totalRecCount).address = arytextfile(1)
PetArray(totalRecCount).petType = arytextfile(2)
PetArray(totalRecCount).vacced = arytextfile(3)
totalRecCount += 1
Array.Clear(arytextfile, 0, arytextfile.Length)
Loop
For i = 0 To PetArray.GetUpperBound(0)
If PetArray(i).vacced = "No" Then
lstVaccinated.Items.Add(PetArray(i).vacced)
lstCustomer.Items.Add(PetArray(i).custName)
lstAddress.Items.Add(PetArray(i).address)
lstPetType.Items.Add(PetArray(i).petType)
totNotVac += 1
lblVacTotal.Text = "The total number of unvaccinated animals is " & CStr(totNotVac)
End If
Next
Catch ex As Exception
MsgBox("Something went wrong with the file")
End Try
PetFile.Close()
End Sub
Private Sub btnExit_Click(sender As Object, e As EventArgs) Handles btnExit.Click
Close()
End Sub
End Class
И одна строчка из файла Patient.txt:
Richard Gere,16 Sunset Blvd,Gerbil,No
Надеюсь, это не к месту.
С уважением,
Дамиан
1 ответ
Мнение: строить такой массив бесполезно. Я согласен, что это неуклюжее использование массивов, которое я считаю ненужным (и устаревшим). Например, вам даже не нужно заранее знать, сколько записей, и вам не нужно измерять массив до заранее определенного размера. Для работы доступны более гибкие типы данных, чем массивы.
При добавлении элементов в элементы управления, например ListView или ListBox, с помощью .Items.Add
вы можете использовать BeginUpdate
в начале вашего цикла и EndUpdate
в конце, когда вы заполняете элементы из цикла.
Цель состоит в том, чтобы сделать пользовательский интерфейс более отзывчивым — если у вас большой файл и вы добавляете много элементов, интерфейс может зависнуть во время выполнения цикла.
Хотя я бы, вероятно, вместо этого привязал список к базе данных или другой структуре. Просто добавьте элементы в таблицу данных и позвольте элементу управления обновиться.
Итак, вот отредактированный пример: я преобразовал вашу структуру в класс и использую List Of
вместо массива (обратите внимание на добавление источника привязки). Чтобы это сработало, мне нужно использовать характеристики чтобы раскрыть члены класса (так я думаю), поэтому я использую класс вместо структуры, но должен быть способ сохранить структуру, если вы хотите.
Есть несколько способов чтения файла, в этом примере я использую StreamReader
. Обратите внимание на использование диспетчера контекста ( Using
block), а это значит, что мне не нужно беспокоиться о закрытии файла, в том числе в случае исключения. Это происходит автоматически после End Using
утверждение.
В вашем коде PetFile.Close()
не будет выполняться в случае возникновения исключения. Ваша процедура завершится после MsgBox. Но что вы можете сделать, так это двигаться PetFile.Close()
в раздел «Наконец» в блоке Try-Catch. Но если вы пытаетесь закрыть файл, который даже не открыт, это вызовет исключение внутри исключения. Лучшее решение — не возиться с этим и использовать диспетчер контекста.
Обратите внимание, что каждая строка в файле должна содержать как минимум 4 поля, разделенных запятыми, иначе код выйдет из строя. Поэтому рекомендуется проверять для каждой строки, что fields.Count
= 4 и пропускать строки, не соответствующие этому критерию.
Здесь я заполняю только один список, надеюсь, вы легко разберетесь с остальным.
Imports System.IO
Public Class Form1
Public Class PetsRecord
Private m_CustomerName As String
Private m_CustomerAddress As String
Private m_PetType As String
Private m_Vaccinated As String
Public Property CustomerName() As String
Get
Return Me.m_CustomerName
End Get
Set(ByVal value As String)
Me.m_CustomerName = value
End Set
End Property
Public Property CustomerAddress() As String
Get
Return Me.m_CustomerAddress
End Get
Set(ByVal value As String)
Me.m_CustomerAddress = value
End Set
End Property
Public Property PetType() As String
Get
Return Me.m_PetType
End Get
Set(ByVal value As String)
Me.m_PetType = value
End Set
End Property
Public Property Vaccinated() As String
Get
Return Me.m_Vaccinated
End Get
Set(ByVal value As String)
Me.m_Vaccinated = value
End Set
End Property
End Class 'Structure
Private Sub btnLoad_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnLoad.Click
Dim PetArray As New List(Of PetsRecord)
Dim bs As New BindingSource()
Dim PetFile As String = "C:UserstestDocumentspets.txt"
Using r As StreamReader = New StreamReader(PetFile)
Dim line As String
line = r.ReadLine
Do While (Not line Is Nothing)
' split the line into fields
Dim fields As New List(Of String)(line.Split(","c))
If fields.Count < 4 Then
Console.WriteLine("Skipping line (contains less than 4 fields): " & line)
Else
' flag this line
If fields(3) = "No" Then
Dim pet As New PetsRecord
pet.CustomerName = fields(0)
pet.CustomerAddress = fields(1)
pet.PetType = fields(2)
pet.Vaccinated = fields(3)
PetArray.Add(pet)
End If
End If
line = r.ReadLine
Loop
End Using
' bind the listbox to PetArray
bs.DataSource = PetArray
Me.lstCustomer.DisplayMember = "CustomerName"
Me.lstCustomer.DataSource = bs
End Sub
End Class