From 87e7ae89d8512ec4d07199fee194f38a172c55bc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=95=D0=B2=D0=B3=D0=B5=D0=BD=D0=B8=D0=B9=20=D0=91=D0=B0?= =?UTF-8?q?=D0=B3=D0=BE=D1=87=D1=8E=D1=81?= Date: Sat, 28 Feb 2026 10:25:53 +0700 Subject: [PATCH] Task done --- TestTask/IReadOnlyStream.cs | 7 ++-- TestTask/Program.cs | 81 ++++++++++++++++++++++++++++--------- TestTask/ReadOnlyStream.cs | 35 ++++++++++++---- TestTask/TestTask.csproj | 6 ++- TestTask/app.config | 3 ++ 5 files changed, 100 insertions(+), 32 deletions(-) create mode 100644 TestTask/app.config diff --git a/TestTask/IReadOnlyStream.cs b/TestTask/IReadOnlyStream.cs index 6946745..db8764d 100644 --- a/TestTask/IReadOnlyStream.cs +++ b/TestTask/IReadOnlyStream.cs @@ -1,12 +1,13 @@ -namespace TestTask +using System; + +namespace TestTask { /// /// Интерфейс для работы с файлом в сильно урезаном виде. /// Умеет всего 2 вещи: прочитать символ, и перемотать стрим на начало. /// - internal interface IReadOnlyStream + internal interface IReadOnlyStream : IDisposable { - // TODO : Необходимо доработать данный интерфейс для обеспечения гарантированного закрытия файла, по окончанию работы с таковым! char ReadNextChar(); void ResetPositionToStart(); diff --git a/TestTask/Program.cs b/TestTask/Program.cs index fdf048e..159326f 100644 --- a/TestTask/Program.cs +++ b/TestTask/Program.cs @@ -1,26 +1,32 @@ using System; using System.Collections.Generic; +using System.Diagnostics.Eventing.Reader; +using System.Linq; namespace TestTask { public class Program { + const string alphabet = "абвгдеёжзийклмнопрстуфхцчшщъыьэюя"; + const string vowels = "аеёиоуыэюя"; + const string consonants = "бвгджзйклмнпрстфхцчшщъь"; /// /// Программа принимает на входе 2 пути до файлов. - /// Анализирует в первом файле кол-во вхождений каждой буквы (регистрозависимо). Например А, б, Б, Г и т.д. - /// Анализирует во втором файле кол-во вхождений парных букв (не регистрозависимо). Например АА, Оо, еЕ, тт и т.д. + /// Анализирует в первом файле кол-во вхождений каждой СОГЛАСНОЙ буквы (регистрозависимо). Например А, б, Б, Г и т.д. + /// Анализирует во втором файле кол-во вхождений парных ГЛАСНЫХ букв (не регистрозависимо). Например АА, Оо, еЕ, и т.д. /// По окончанию работы - выводит данную статистику на экран. /// - /// Первый параметр - путь до первого файла. + /// Первый параметр - путь до первого файла. /// Второй параметр - путь до второго файла. static void Main(string[] args) { - IReadOnlyStream inputStream1 = GetInputStream(args[0]); - IReadOnlyStream inputStream2 = GetInputStream(args[1]); + IList singleLetterStats, doubleLetterStats; - IList singleLetterStats = FillSingleLetterStats(inputStream1); - IList doubleLetterStats = FillDoubleLetterStats(inputStream2); + using (IReadOnlyStream inputStream1 = GetInputStream(args[0])) + { singleLetterStats = FillSingleLetterStats(inputStream1); } + using (IReadOnlyStream inputStream2 = GetInputStream(args[1])) + { doubleLetterStats = FillDoubleLetterStats(inputStream2); } RemoveCharStatsByType(singleLetterStats, CharType.Vowel); RemoveCharStatsByType(doubleLetterStats, CharType.Consonants); @@ -28,6 +34,7 @@ static void Main(string[] args) PrintStatistic(singleLetterStats); PrintStatistic(doubleLetterStats); + Console.Read(); // TODO : Необжодимо дождаться нажатия клавиши, прежде чем завершать выполнение программы. } @@ -49,16 +56,25 @@ private static IReadOnlyStream GetInputStream(string fileFullPath) /// Коллекция статистик по каждой букве, что была прочитана из стрима. private static IList FillSingleLetterStats(IReadOnlyStream stream) { + List fullStat = new List(); + foreach (char c in alphabet) + { + fullStat.Add(new LetterStats { Letter = c.ToString().ToUpper(), Count = 0 }); + fullStat.Add(new LetterStats { Letter = c.ToString(), Count = 0 }); + } + var fullStat_array = fullStat.ToArray(); + + stream.ResetPositionToStart(); while (!stream.IsEof) { char c = stream.ReadNextChar(); - // TODO : заполнять статистику с использованием метода IncStatistic. Учёт букв - регистрозависимый. + int index = Array.FindIndex(fullStat_array, x => x.Letter == c.ToString()); + if (index != -1) IncStatistic(ref fullStat_array[index]); } - //return ???; - - throw new NotImplementedException(); + var result = from ls in fullStat_array where ls.Count > 0 select ls; + return result.ToList(); } /// @@ -70,16 +86,35 @@ private static IList FillSingleLetterStats(IReadOnlyStream stream) /// Коллекция статистик по каждой букве, что была прочитана из стрима. private static IList FillDoubleLetterStats(IReadOnlyStream stream) { + List fullStat = new List(); + foreach (char c in alphabet) + { + fullStat.Add(new LetterStats { Letter = c.ToString().ToUpper(), Count = 0 }); + } + var fullStat_array = fullStat.ToArray(); + + + string previousLetter = ""; stream.ResetPositionToStart(); while (!stream.IsEof) { char c = stream.ReadNextChar(); - // TODO : заполнять статистику с использованием метода IncStatistic. Учёт букв - НЕ регистрозависимый. + string readedLetter = c.ToString().ToUpper(); + if (previousLetter == readedLetter) + { + int index = Array.FindIndex(fullStat_array, x => x.Letter == readedLetter); + if (index != -1) + { + IncStatistic(ref fullStat_array[index]);//.Count++; + //чтобы не засчитать три одинаковых буквы за две пары + previousLetter = ""; + continue; + } + } + previousLetter = readedLetter; } - - //return ???; - - throw new NotImplementedException(); + var result = from ls in fullStat_array where ls.Count > 0 select ls; + return result.ToList(); } /// @@ -91,15 +126,22 @@ private static IList FillDoubleLetterStats(IReadOnlyStream stream) /// Тип букв для анализа private static void RemoveCharStatsByType(IList letters, CharType charType) { + string excludedLetters = ""; // TODO : Удалить статистику по запрошенному типу букв. switch (charType) { case CharType.Consonants: + excludedLetters = consonants; break; case CharType.Vowel: + excludedLetters = vowels; break; } - + + var modifiedLetters = letters.Where(l => !excludedLetters.Contains(l.Letter) && + !excludedLetters.Contains(l.Letter.ToLower())).ToList(); + letters.Clear(); + foreach (var l in modifiedLetters) letters.Add(l); } /// @@ -111,15 +153,14 @@ private static void RemoveCharStatsByType(IList letters, CharType c /// Коллекция со статистикой private static void PrintStatistic(IEnumerable letters) { - // TODO : Выводить на экран статистику. Выводить предварительно отсортировав по алфавиту! - throw new NotImplementedException(); + foreach (var l in letters) Console.WriteLine($"{l.Letter} : {l.Count}"); } /// /// Метод увеличивает счётчик вхождений по переданной структуре. /// /// - private static void IncStatistic(LetterStats letterStats) + private static void IncStatistic(ref LetterStats letterStats) { letterStats.Count++; } diff --git a/TestTask/ReadOnlyStream.cs b/TestTask/ReadOnlyStream.cs index a51a61e..f4ce19c 100644 --- a/TestTask/ReadOnlyStream.cs +++ b/TestTask/ReadOnlyStream.cs @@ -6,6 +6,8 @@ namespace TestTask public class ReadOnlyStream : IReadOnlyStream { private Stream _localStream; + private StreamReader _localStreamReader; + private bool _disposed = false; /// /// Конструктор класса. @@ -15,18 +17,17 @@ public class ReadOnlyStream : IReadOnlyStream /// Полный путь до файла для чтения public ReadOnlyStream(string fileFullPath) { - IsEof = true; - - // TODO : Заменить на создание реального стрима для чтения файла! - _localStream = null; + IsEof = false; + _localStream = new FileStream(fileFullPath, FileMode.Open, FileAccess.Read); + _localStreamReader = new StreamReader(_localStream); } - + /// /// Флаг окончания файла. /// public bool IsEof { - get; // TODO : Заполнять данный флаг при достижении конца файла/стрима при чтении + get; private set; } @@ -38,8 +39,11 @@ public bool IsEof /// Считанный символ. public char ReadNextChar() { - // TODO : Необходимо считать очередной символ из _localStream - throw new NotImplementedException(); + if (_disposed) throw new ObjectDisposedException("Stream is disposed"); + if (IsEof) throw new EndOfStreamException(); + char result = (char)_localStreamReader.Read(); + IsEof = (_localStreamReader.Peek() == -1); + return result; } /// @@ -56,5 +60,20 @@ public void ResetPositionToStart() _localStream.Position = 0; IsEof = false; } + + + public void Dispose() + { + if (_disposed) return; + _disposed = true; + _localStream?.Dispose(); + _localStream = null; + } + + + + + + } } diff --git a/TestTask/TestTask.csproj b/TestTask/TestTask.csproj index dc470b0..9903e02 100644 --- a/TestTask/TestTask.csproj +++ b/TestTask/TestTask.csproj @@ -8,9 +8,10 @@ Exe TestTask TestTask - v4.6.1 + v4.8 512 true + AnyCPU @@ -49,5 +50,8 @@ + + + \ No newline at end of file diff --git a/TestTask/app.config b/TestTask/app.config new file mode 100644 index 0000000..3e0e37c --- /dev/null +++ b/TestTask/app.config @@ -0,0 +1,3 @@ + + +