#vb.net
Вопрос:
Может кто-нибудь помочь мне с этим, я застрял без понятия, что делать дальше
дайте текстовый файл в любом месте компьютера, он содержит 15 различных целых чисел, которые можно повторить, сделайте программу так, чтобы несколько повторений одного числа не печатались отдельно, но каждое число печаталось ровно один раз и рядом с ним записывалось, в каких местах он появился
Imports System.IO
Public Class form1
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Dim povratnaVrijednost As DialogResult
Dim nazivDatoteke As String
Try
OpenFileDialog1.AddExtension = True
OpenFileDialog1.Multiselect = False
OpenFileDialog1.Filter = "Tekst datoteke (*.txt)|*.txt;"
povratnaVrijednost = OpenFileDialog1.ShowDialog()
If povratnaVrijednost = Windows.Forms.DialogResult.OK Then
If OpenFileDialog1.CheckFileExists = True And
OpenFileDialog1.CheckPathExists = True Then
nazivDatoteke = OpenFileDialog1.FileName
TextBox1.Text = nazivDatoteke
Dim citac As New StreamReader(nazivDatoteke)
Dim redTeksta As String = ""
Do
redTeksta = citac.ReadLine()
If Not redTeksta Is Nothing Then
RichTextBox1.Text = RichTextBox1.Text redTeksta
End If
Loop Until redTeksta Is Nothing
citac.Close()
End If
End If
Catch ex As Exception
MsgBox("Greska prilikom otvaranja" ex.StackTrace.ToString)
End Try
End Sub
End Class
Комментарии:
1. Вам необходимо на самом деле предоставить подробное объяснение конкретной проблемы, с которой вы столкнулись. Недостаточно сказать: «Вот мое задание, вот мой код» и ожидать, что мы возьмем его оттуда. Вам нужно отладить свой код и быть в состоянии ТОЧНО объяснить, как и где он ведет себя не так, как ожидалось, и каковы эти ожидания.
Ответ №1:
Требование № 1:
предоставьте текстовый файл в любом месте компьютера, он содержит 15 различных целых чисел, которые можно повторить
Это требование подразумевает несколько других требований. Во-первых, вы должны прочитать текстовый файл. Во-вторых, ожидается, что вы проанализируете значения в числа (предположительно целые числа).
Вы можете использовать OpenFileDialog (документация) и указать, что он может принимать только текстовые файлы:
Using browseFileDialog = New OpenFileDialog()
With browseFileDialog
.Filter = "*.txt|*.txt"
If (.ShowDialog() = DialogResult.Ok) Then
'.FileName will be the text file that the user picked
End If
End With
End Using
Чтобы прочитать текстовый файл, предполагая, что вам нужна каждая строка, используйте файл.Метод ReadAllLines (документация):
Using browseFileDialog = New OpenFileDialog()
With browseFileDialog
.Filter = "*.txt|*.txt"
If (.ShowDialog() = DialogResult.Ok) Then
Dim lines = IO.File.ReadAllLines(.FileName)
End If
End With
End Using
Для анализа значений используйте массив.Метод ConvertAll (документация) и внутри предиката используют целое число.Метод анализа (документация):
Using browseFileDialog = New OpenFileDialog()
With browseFileDialog
.Filter = "*.txt|*.txt"
If (.ShowDialog() = DialogResult.Ok) Then
Dim lines = IO.File.ReadAllLines(.FileName)
Dim values = Array.ConvertAll(lines, Function(line) Integer.Parse(line))
End If
End With
End Using
Имейте в виду, что если бы вы хотели проверить, что все строки являются допустимыми числами, вместо того, чтобы предполагать, что это так, этот шаг был бы другим. Однако вы не указали это требование в своем первоначальном сообщении, поэтому я не включаю, как это сделать.
Требование № 2:
сделайте программу так, чтобы несколько повторений одного числа печатались не отдельно, а каждое число печаталось ровно один раз
Вы можете использовать Случайный.Следующий метод (документация) для генерации случайных значений. Обязательно объявите новый экземпляр случайного объекта один раз, чтобы начальное значение было установлено только один раз. Чтобы случайным образом упорядочить значения, используйте метод OrderBy (документация), передающий случайное значение в предикате:
Private ReadOnly _random As New Random()
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Using browseFileDialog = New OpenFileDialog()
With browseFileDialog
.Filter = "*.txt|*.txt"
If (.ShowDialog() = DialogResult.Ok) Then
Dim lines = IO.File.ReadAllLines(.FileName)
Dim values = Array.ConvertAll(lines, Function(line) Integer.Parse(line))
Dim randomlyOrderedValues = values.OrderBy(Function(value) _random.Next())
RichTextBox1.Text = String.Join(", ", randomlyOrderedValues.ToArray())
End If
End With
End Using
End Sub
Комментарии:
1. При
Integer.Parse
сбое возникает исключение, которое не обрабатывается. Это ваше намерение?2. @Mary — У меня есть это в моем посте: Имейте в виду, что если бы вы хотели проверить, что все строки являются действительными числами, вместо того, чтобы предполагать, что это так, этот шаг был бы другим. Однако вы не указали это требование в своем первоначальном посте, поэтому я не включаю, как это сделать.
3. Это не мой пост. В таком случае не
Function(line) CInt(line)
было бы проще?4. @Mary — это более лаконично, но мне не нравится использовать ключевые слова VB. Джилхинни уже объяснил, почему он использует их в определенных ситуациях, но я уткнулся головой в землю, как птица-дронт.
5. «Функции Visual Basic предназначены для оптимального взаимодействия с кодом Visual Basic, а также делают ваш исходный код короче и проще для чтения. «См. MS Docs по адресу docs.microsoft.com/en-us/dotnet/visual-basic/language-reference/…
Ответ №2:
Значение по умолчанию .AddExtension
равно True
. Значение по умолчанию .Multiselect
равно False
. Я упростил If
утверждение, сравнив возвращаемое значение .Showdialog
напрямую с желаемым DialogResult
. Если путь к файлу не существует, в диалоговом окне появится предупреждение.
Всегда охватывайте переменные как можно более узко. Я перемещаю Dim nazivDatoteke
значение «кому» внутрь «Если», так как оно больше нигде не используется. StreamReader
s требуют Using
блока, так как их необходимо утилизировать.
Почему a RichTextBox
для текстового файла?
Как вы можете видеть, получить отличительные элементы в массиве легко, достаточно одной строки кода. Что еще сложнее, так это найти индексы в исходном массиве, lines
.
Я перебрал все элементы в distinct
массиве (на самом деле это IEnumerable(Of String)
так, но это не важно для этого кода, просто в моем объяснении проще ввести массив). Я создал a List(Of Integer)
для хранения индексов каждого элемента в исходном массиве, lines
. startIndex
Где FindIndex
метод an Array
-это местоположение первого вхождения строки.
На каждой итерации Do
цикла я ищу совпадения с элементом из lines
массива. FindIndex
Принимает параметры (исходный массив, индекс для начала, то, что мы ищем). Он останавливается, как только находит совпадение, и возвращает -1, если совпадения не найдены. Вы можете видеть, как этот метод работает, устанавливая точку останова и проверяя значения переменных.
Если совпадение найдено, я добавил это значение в список и изменил startIndex
его на позицию, следующую за найденным индексом.
Затем я использовал a StringBuilder
для создания строки для отображения. Я выбрал немедленное окно для целей тестирования, но вы можете отобразить sb.ToString
его в текстовом поле или добавить в ListBox
.
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
OpenFileDialog1.Filter = "Tekst datoteke (*.txt)|*.txt;"
If DialogResult.OK = OpenFileDialog1.ShowDialog Then
Dim nazivDatoteke = OpenFileDialog1.FileName
TextBox1.Text = nazivDatoteke
Dim lines = File.ReadAllLines(nazivDatoteke)
Dim distinct = lines.Distinct
For Each item In distinct
Dim lst As New List(Of Integer)
Dim startIndex = Array.IndexOf(lines, item)
Do
Dim FoundIndex = Array.FindIndex(lines, startIndex, Function(line) line = item)
If FoundIndex = -1 Then
Exit Do
Else
lst.Add(FoundIndex)
startIndex = FoundIndex 1
End If
Loop
Dim sb As New StringBuilder
sb.Append(item)
For Each i In lst
sb.Append($" ({i})")
Next
Debug.Print(sb.ToString)
Next
End If
End Sub
Этот код отображает отдельные элементы в списке и следует за ними с позициями (индексами) в исходном списке.