Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions TestTask/IReadOnlyStream.cs
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
namespace TestTask
using System;

namespace TestTask
{
/// <summary>
/// Интерфейс для работы с файлом в сильно урезаном виде.
/// Умеет всего 2 вещи: прочитать символ, и перемотать стрим на начало.
/// </summary>
internal interface IReadOnlyStream
internal interface IReadOnlyStream : IDisposable
{
// TODO : Необходимо доработать данный интерфейс для обеспечения гарантированного закрытия файла, по окончанию работы с таковым!
char ReadNextChar();

void ResetPositionToStart();
Expand Down
2 changes: 1 addition & 1 deletion TestTask/LetterStats.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
/// <summary>
/// Статистика вхождения буквы/пары букв
/// </summary>
public struct LetterStats
public class LetterStats
{
/// <summary>
/// Буква/Пара букв для учёта статистики.
Expand Down
118 changes: 98 additions & 20 deletions TestTask/Program.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Linq;

namespace TestTask
{
Expand All @@ -16,6 +17,14 @@ public class Program
/// Второй параметр - путь до второго файла.</param>
static void Main(string[] args)
{
if (args == null || args.Length < 2)
{
Console.WriteLine("Нужно передать 2 параметра: <путь_к_файлу_1> <путь_к_файлу_2>");
Console.WriteLine("Пример: TestTask.exe \"C:\\temp\\1.txt\" \"C:\\temp\\2.txt\"");
Console.ReadKey();
return;
}

IReadOnlyStream inputStream1 = GetInputStream(args[0]);
IReadOnlyStream inputStream2 = GetInputStream(args[1]);

Expand All @@ -28,7 +37,7 @@ static void Main(string[] args)
PrintStatistic(singleLetterStats);
PrintStatistic(doubleLetterStats);

// TODO : Необжодимо дождаться нажатия клавиши, прежде чем завершать выполнение программы.
Console.ReadKey();
}

/// <summary>
Expand All @@ -49,16 +58,32 @@ private static IReadOnlyStream GetInputStream(string fileFullPath)
/// <returns>Коллекция статистик по каждой букве, что была прочитана из стрима.</returns>
private static IList<LetterStats> FillSingleLetterStats(IReadOnlyStream stream)
{
var dict = new Dictionary<string, LetterStats>();

stream.ResetPositionToStart();

while (!stream.IsEof)
{
char c = stream.ReadNextChar();
// TODO : заполнять статистику с использованием метода IncStatistic. Учёт букв - регистрозависимый.
}
char c;

try { c = stream.ReadNextChar(); }
catch { break; }

if (!char.IsLetter(c))
continue;

string key = c.ToString();

//return ???;
if (!dict.TryGetValue(key, out var stat))
{
stat = new LetterStats { Letter = key };
dict[key] = stat;
}

throw new NotImplementedException();
IncStatistic(stat);
}

return dict.Values.ToList();
}

/// <summary>
Expand All @@ -70,16 +95,44 @@ private static IList<LetterStats> FillSingleLetterStats(IReadOnlyStream stream)
/// <returns>Коллекция статистик по каждой букве, что была прочитана из стрима.</returns>
private static IList<LetterStats> FillDoubleLetterStats(IReadOnlyStream stream)
{
var dict = new Dictionary<string, LetterStats>();

stream.ResetPositionToStart();

char? prev = null;

while (!stream.IsEof)
{
char c = stream.ReadNextChar();
// TODO : заполнять статистику с использованием метода IncStatistic. Учёт букв - НЕ регистрозависимый.
}
char c;

try { c = stream.ReadNextChar(); }
catch { break; }

if (!char.IsLetter(c))
{
prev = null;
continue;
}

//return ???;
if (prev.HasValue &&
char.ToUpperInvariant(prev.Value) == char.ToUpperInvariant(c))
{
char up = char.ToUpperInvariant(c);
string key = new string(new[] { up, up });

throw new NotImplementedException();
if (!dict.TryGetValue(key, out var stat))
{
stat = new LetterStats { Letter = key };
dict[key] = stat;
}

IncStatistic(stat);
}

prev = c;
}

return dict.Values.ToList();
}

/// <summary>
Expand All @@ -91,15 +144,22 @@ private static IList<LetterStats> FillDoubleLetterStats(IReadOnlyStream stream)
/// <param name="charType">Тип букв для анализа</param>
private static void RemoveCharStatsByType(IList<LetterStats> letters, CharType charType)
{
// TODO : Удалить статистику по запрошенному типу букв.
switch (charType)
for (int i = letters.Count - 1; i >= 0; i--)
{
case CharType.Consonants:
break;
case CharType.Vowel:
break;
var item = letters[i];

bool match = item.Letter.All(c =>
charType == CharType.Vowel ? IsVowel(c) : !IsVowel(c));

if (match)
letters.RemoveAt(i);
}

}

private static bool IsVowel(char c)
{
c = char.ToUpperInvariant(c);
return "AEIOUYАЕЁИОУЫЭЮЯ".Contains(c);
}

/// <summary>
Expand All @@ -111,8 +171,26 @@ private static void RemoveCharStatsByType(IList<LetterStats> letters, CharType c
/// <param name="letters">Коллекция со статистикой</param>
private static void PrintStatistic(IEnumerable<LetterStats> letters)
{
// TODO : Выводить на экран статистику. Выводить предварительно отсортировав по алфавиту!
throw new NotImplementedException();
if (letters == null)
{
Console.WriteLine("ИТОГО : 0");
return;
}

var ordered = letters
.Where(x => x != null && !string.IsNullOrEmpty(x.Letter))
.OrderBy(x => x.Letter, StringComparer.CurrentCulture)
.ToList();

int total = 0;

foreach (var item in ordered)
{
Console.WriteLine($"{item.Letter} : {item.Count}");
total += item.Count;
}

Console.WriteLine($"ИТОГО : {total}");
}

/// <summary>
Expand Down
45 changes: 30 additions & 15 deletions TestTask/ReadOnlyStream.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ namespace TestTask
{
public class ReadOnlyStream : IReadOnlyStream
{
private Stream _localStream;
private readonly FileStream _fileStream;
private readonly StreamReader _reader;

/// <summary>
/// Конструктор класса.
Expand All @@ -15,18 +16,18 @@ public class ReadOnlyStream : IReadOnlyStream
/// <param name="fileFullPath">Полный путь до файла для чтения</param>
public ReadOnlyStream(string fileFullPath)
{
IsEof = true;
_fileStream = File.OpenRead(fileFullPath);
_reader = new StreamReader(_fileStream);

// TODO : Заменить на создание реального стрима для чтения файла!
_localStream = null;
ResetPositionToStart();
}

/// <summary>
/// Флаг окончания файла.
/// </summary>
public bool IsEof
{
get; // TODO : Заполнять данный флаг при достижении конца файла/стрима при чтении
get;
private set;
}

Expand All @@ -38,23 +39,37 @@ public bool IsEof
/// <returns>Считанный символ.</returns>
public char ReadNextChar()
{
// TODO : Необходимо считать очередной символ из _localStream
throw new NotImplementedException();
if (IsEof)
throw new EndOfStreamException();

int value = _reader.Read();

if (value == -1)
{
IsEof = true;
throw new EndOfStreamException();
}

if (_reader.Peek() == -1)
IsEof = true;

return (char)value;
}

/// <summary>
/// Сбрасывает текущую позицию потока на начало.
/// </summary>
public void ResetPositionToStart()
{
if (_localStream == null)
{
IsEof = true;
return;
}
_fileStream.Position = 0;
_reader.DiscardBufferedData();
IsEof = _reader.Peek() == -1;
}

_localStream.Position = 0;
IsEof = false;
public void Dispose()
{
_reader?.Dispose();
_fileStream?.Dispose();
}
}
}
6 changes: 5 additions & 1 deletion TestTask/TestTask.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,10 @@
<OutputType>Exe</OutputType>
<RootNamespace>TestTask</RootNamespace>
<AssemblyName>TestTask</AssemblyName>
<TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion>
<TargetFrameworkVersion>v4.8</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
<TargetFrameworkProfile />
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
Expand Down Expand Up @@ -49,5 +50,8 @@
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="ReadOnlyStream.cs" />
</ItemGroup>
<ItemGroup>
<None Include="app.config" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>
3 changes: 3 additions & 0 deletions TestTask/app.config
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.8"/></startup></configuration>