2014-09-23 64 views
2

我一直在开发一个使用文本文件来存储问题的测验应用程序。使用ArrayList将文本文件拆分并存储到数组中

的问题是这种格式"QUESTION##CHOICE_A##CHOICE_B##CHOICE_C##CHOICE_D##ANSWER" 我希望它读取每一行拆分成使用"##"作为分割字符串6个不同的部分,它如Questions, CHOICE_A,CHOICE_B,CHOICE_C,CHOICE_D

我的代码不循环存入数组格式化。它只是存储第一线

的图解如下所示的问题

enter image description here enter image description here

这里是我的代码

Dim sr As StringReader = New StringReader(My.Resources.ResourceManager.GetObject(globalVariables.currSubject)) 

    Dim questions As String 

    Dim splitquestions(6) As String 

    Dim Unsplitquestions(6) As String 




    Dim i As Integer = 0 

    Do Until sr.Peek = -1 

     questions = sr.ReadLine 

     Unsplitquestions(i) = questions 

     splitquestions = Unsplitquestions(i).Split(New String() {"##"}, StringSplitOptions.RemoveEmptyEntries) 

     ' Splits and Stores Into Various 
     ' 
     ' 


     globalVariables.ArrayQuestions.Add(splitquestions(0)) 

     globalVariables.optionA.Add(splitquestions(1)) 

     globalVariables.optionB.Add(splitquestions(2)) 

     globalVariables.optionC.Add(splitquestions(3)) 

     globalVariables.optionD.Add(splitquestions(4)) 

     globalVariables.Answer.Add(splitquestions(5)) 

    Loop 
+0

为什么仍然使用ArrayList?现在有更好的选择。列表(问题)例如 – Steve 2014-09-23 13:41:10

+0

要用更明显的语句回答您的具体问题,请在第一次运行后sr.peek = -1。你必须达到弦乐的结束或停止。如果我是你,我会尝试一种不同的循环方法。 – Kat 2014-09-23 13:42:19

+0

你会为此更好地创建一个'Quiz'类,而不是在几个数组中存储相关数据 – Plutonix 2014-09-23 13:43:40

回答

3

不,不要使用ArrayList操纵一组这样的对象。你应该尝试以面向对象的方式进行思考。 QuestionEntry是一个包含QuestionText的实体,4个可能的问题答案和一个QuestionAnswer。

让我们试试这个代码

Public Class QuestionEntry 
    Public QuestionText as String 
    Public ChoiceA as String 
    Public ChoiceB as String 
    Public ChoiceC as String 
    Public ChoiceD as String 
    Public QuestionAnswer as String 
End Class 

Dim questions = new List(Of QuestionEntry)() 
Dim line As String 
Do While sr.Peek() >= 0 
    line = sr.ReadLine 
    Console.WriteLine(line) 
    Dim parts = line.Split(New String() {"##"}, StringSplitOptions.RemoveEmptyEntries) 
    Dim q = new QuestionEntry() 
    With q 

      .QuestionText = parts(0) 
      .ChoiceA = parts(1) 
      .ChoiceB = parts(2) 
      .ChoiceC = parts(3) 
      .ChoiceD = parts(4) 
      .QuestionAnswer = parts(5) 

    End With 
    questions.Add(q) 
Loop 

当然这只是一个例子,错误检查的位将需要使代码更安全。例如,在创建新的问题条目之前,您应该检查分组返回的数组是否有6个元素。 (parts.Length = 6)

现在所有的文字都是由一个List(中QuestionEntry)的实例处理,你可以使用它像一个正常的阵列

Dim qe = questions(0) 
Console.WriteLine("Question: " & qe.QuestionText) 
Console.WriteLine("Choice A: " & qe.ChoiceA) 
Console.WriteLine("Choice B: " & qe.ChoiceB) 
Console.WriteLine("Choice C: " & qe.ChoiceC) 
Console.WriteLine("Choice D: " & qe.ChoiceD) 
Console.ReadLine("Enter your answer:") 
1

最好的方式做到这一点是依靠现有的定界数据解析器。 .Split()方法通常是非常糟糕的:性能低于标准,并且所有边缘情况下的国王(比你想象的要多),它在哪里工作不好。甚至有一个解析器已经内置到.Net中:Microsoft.VisualBasic.FileIO.TextFieldParser

此外,ArrayLists真的只存在于.Net 2.0兼容性。没有任何理由再使用一个。至少,使用通用的List(Of String)。在这种情况下,虽然,你最好的选择是建立一个快速的类:

Public Class Question 
    Public Property QuestionText As String 
    Public Property OptionA As String 
    Public Property OptionB As String 
    Public Property OptionC As String 
    Public Property OptionD As String 
    Public Property Answer As String 
End Class 

现在你读你的文件是这样的:

Dim results As New List(Of Question)() 
Using rdr As New TextFieldParser(My.Resources.ResourceManager.GetObject(globalVariables.currSubject)) 
    rdr.Delimiters = new String() {"##"} 
    Dim row() As String 

    While Not rdr.EndOfData 
     row = rdr.ReadFields() 
     results.Add(New Question() { 
      QuestionText = row(0), 
      OptionA = row(1), 
      OptionB = row(2), 
      OptionC = row(3), 
      OptionD = row(4), 
      Answer = row(5) 
     }) 
    End While 
End Using 

即使类的定义,这是一个整个代码比原始代码少,而且维护起来也容易得多。

我还很想写这为Iterator

Public Iterator Function ReadQuestions(ByVal FileName As String) As IEnumerable(Of Question) 
    Using rdr As New TextFieldParser(FileName) 
     rdr.Delimiters = new String() {"##"} 
     Dim row() As String 

     While Not rdr.EndOfData 
      row = rdr.ReadFields() 

      Yield New Question() { 
       QuestionText = row(0), 
       OptionA = row(1), 
       OptionB = row(2), 
       OptionC = row(3), 
       OptionD = row(4), 
       Answer = row(5) 
      } 
     End While 
    End Using 
End Function 

我有两个最后的修改建议。第一个将构造函数添加到接受字符串数组的Question类型。这将从代码中移除一点高级语法(对象初始值设定项),并简化通过实际读取数据的代码部分的读取。第二种方法是使ReadQuestions()方法成为Question类型的共享成员。最后的结果是这样的:

Public Class Question 
    Public Property QuestionText As String 
    Public Property OptionA As String 
    Public Property OptionB As String 
    Public Property OptionC As String 
    Public Property OptionD As String 
    Public Property Answer As String 

    Public Sub New(ByVal data() As String) 
     'Add error handling here 
     QuestionText = data(0), 
     OptionA = data(1), 
     OptionB = data(2), 
     OptionC = data(3), 
     OptionD = data(4), 
     Answer = data(5) 
    End Sub 

    Public Shared Iterator Function ReadFromFile(ByVal FileName As String) As IEnumerable(Of Question) 
     Using rdr As New TextFieldParser(FileName) 
      rdr.Delimiters = new String() {"##"} 

      While Not rdr.EndOfData         
       Yield New Question(rdr.ReadFields()) 
      End While 
     End Using 
    End Function 
End Class 

你从你现有的代码中调用这一切都像这样:

Dim Questions = Question.ReadFromFile(My.Resources.ResourceManager.GetObject(globalVariables.currSubject)) 
For Each q As Question in Questions 
    '... 
Next 
相关问题