Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Osnovy_C# Yakimova.docx
Скачиваний:
6
Добавлен:
12.11.2019
Размер:
758.74 Кб
Скачать

Задания для лабораторной работы № 3

1. Даны натуральные n, m, целые числа a1, …, an и b1, …, bm. Внутри каждой из данных последовательностей нет повторяющихся членов. Построить пересечение данных последовательностей.

2. Даны натуральные n, m, целые числа a1, …, an и b1, …, bm. Внутри каждой из данных последовательностей нет повторяющихся членов. Получить все члены последовательности a1, …, an, которые не входят в последовательность b1, …, bm.

3. Дан массив x[1] ≤ x[2] ≤ …≤ x[n] целых чисел и число y. Выяснить, содержится ли y в этом массиве, то есть существует ли x[i] = y, i из 1..n. Число действий в программе порядка log n.

4. Дан массив x[1…n] целых чисел и число y. Переставить числа в массиве таким образом, чтобы слева от некоторой границы стояли числа, меньшие или равные y, а справа – большие или равные y.

5. Даны натуральное n, целые числа a1, …, an. Если в данной последовательности ни одно четное число не расположено после нечетного, то вывести на экран все отрицательные члены последовательности в обратном порядке, иначе – все положительные.

Лабораторная работа № 4: Обработка последовательностей символов

Цель работы. Решить задачу на обработку текста, используя функции работы со строками. Всюду ниже, если это не оговорено особо, предполагается, что исходным является текстовый файл. В текст могут входить слова из латинских букв, цифры, знаки арифметических операций, точка, запятая, пробел. Требуется считать текст из файла, вывести его на экран, после решения задачи вывести на экран результат.

Для обработки текста нам потребуются три типа данных: char (символ), string (строка), stringbuilder ( тоже строка). Рассмотрим каждый из них поподробнее.

Тип Char. Прежде всего приведем пример описания и присвоения значения переменной этого типа:

char chA = 'A';

char ch1 = '1';

Переменные типа char можно сравнивать и, с помощью встроенных методов, определять их вид, а именно:

Console.WriteLine(chA.CompareTo('B')); // Output: "-1"

// что означает, что 'A' на единицу меньше, чем 'B'

Console.WriteLine(Char.IsControl('\t')); // Output: "True"

Console.WriteLine(Char.IsDigit(ch1)); // Output: "True"

Console.WriteLine(Char.IsNumber(ch1)); // Output: "True"

Console.WriteLine(Char.IsPunctuation('.')); // Output: "True"

Методы IsControl, IsDigit, IsLetter, IsLetterOrDigit, IsLower, IsNumber, IsPunctuation, IsSeparator, IsSymbol, IsUpper и IsWhiteSpace служат для определения того, принадлежит ли символ к определенной категории Юникода, такой как цифра, буква, знак препинания, управляющий символ и т. д. Метод GetNumericValue служит для преобразования объекта Char, представляющего число, к числовому типу значения.

Тип string. Значением переменной типа string является либо текст, либо NULL, что означает неопределенное значение.

// Объявление строки без инициализации

string message1;

// Инициализация неопределенным значением.

string message2 = null;

// Строка объявлена как пустая

string message3 = String.Empty;

// Строка инициализирована конкретной фразой.

string oldPath = "c:\\Program Files\\Microsoft Visual Studio 8.0";

// причем символ \ удваивается для правильного прочтения

Инициализация строки значением константы Empty приводит к созданию нового объекта String, строка которого имеет нулевую длину. Пустые строки часто используются в различных сценариях программирования, для них можно вызывать любые методы. Для строк со значениями null любая попытка вызвать метод приведет к ошибке. Однако такие строки можно использовать в операциях объединения и сравнения с другими строками, что проиллюстрировано следующими примерами:

string str = "hello";

string nullStr = null;

string emptyStr = string.Empty;

string tempStr = str + nullStr; // tempStr = "hello"

bool b = (emptyStr == nullStr); // b = false;

string newStr = emptyStr + nullStr; // creates a new empty string

int len = nullStr.Length; // throws NullReferenceException

Строковые объекты являются неизменяемыми: после создания их нельзя изменить. Все методы String и операторы C#, которые, как можно было бы представить, изменяют строку, в действительности возвращают результаты в новый строковый объект. В следующем примере, когда содержимое строк s1 и s2 объединяется в одну строку, две исходные строки не изменяются. Оператор += создает новую строку с объединенным содержимым. Этот новый объект присваивается переменной s1, а исходный объект, который был присвоен строке s1, освобождается для сборки мусора, поскольку ни одна переменная не содержит ссылку на него.

string s1 = "A string is more ";

string s2 = "than the sum of its chars.";

// Слияние s1 и s2. Это, в действительности, создает новую строку // и помещает ссылку на нее в s1, предыдущая ссылка теряется

s1 += s2;

Console.WriteLine(s1);

// Output: A string is more than the sum of its chars.

Поскольку "изменение" строки в действительности является созданием новой строки, необходима осторожность при создании ссылок на строки. Если создать ссылку на строку, а затем "изменить" исходную строку, то ссылка будет по-прежнему указывать на исходный объект, а не на новый объект, который был создан при изменении строки. Это поведение демонстрируется в следующем коде.

string s1 = "Hello ";

string s2 = s1;

s1 += "World";

Console.WriteLine(s2); //Output: Hello

 Подстроки. Подстрокой является последовательность символов, содержащихся в строке. Метод Substring используется для создания новой строки на основании части исходной строки. Одно или несколько вхождений подстроки можно найти с использованием метода IndexOf. Метод Replace используется для замены всех вхождений заданной подстроки новой строкой. Так же, как и метод Substring, метод Replace фактически возвращает новую строку и не изменяет исходную строку.

string s3 = "Visual C# Express";

System.Console.WriteLine(s3.Substring(7, 2));

// Output: "C#"

System.Console.WriteLine(s3.Replace("C#", "Basic"));

// Output: "Visual Basic Express"

// Нумерация символов в строке начинается с нуля

int index = s3.IndexOf("C"); // index = 7

 Доступ к отдельным символам в строке. Для получения доступа только для чтения к каждому символу поотдельности в строке можно использовать нотацию аналогичную массивам, как показано в следующем примере:

string s5 = "Printing backwards";

for (int i = 0; i < s5.Length; i++)

{

System.Console.Write(s5[s5.Length - i - 1]);

} // Output: "sdrawkcab gnitnirP"

Тип StringBuilder. Операции со строками в .NET в высокой степени оптимизированы и в большинстве случаев значительно не снижают производительность. Однако в некоторых случаях, например, в непрерывных циклах, выполняющихся сотни и тысячи раз, операции со строками могут влиять на производительность. Класс StringBuilder создает строковый буфер, который позволяет повысить производительность, если в программе обрабатывается много строк. Этот тип также позволяет заново присваивать отдельные знаки, что не поддерживается типом string. Например, данный код заменяет содержимое строки без создания новой строки:

StringBuilder sb = new StringBuilder("Rat: the ideal pet");

sb[0] = 'C';

Console.WriteLine(sb.ToString()); //Outputs Cat: the ideal pet

В этом примере объект StringBuilder используется для создания строки из набора числовых типов:

static void Main()

{

StringBuilder sb = new StringBuilder();

// Создание строки, состоящей из цифр 0 - 9

for (int i = 0; i < 10; i++)

{

sb.Append(i.ToString());

}

Console.WriteLine(sb); // displays 0123456789

// Копирование одного символа (невозможно для типа String)

sb[0] = sb[9];

Console.WriteLine(sb); // displays 9123456789

}

}

В следующем примере предположим, что необходимо изменить исходную строку определенным образом, а затем сохранить результаты для дальнейшего использования.

string qstn = "hOW DOES mICROSOFT wORD DEAL WITH THE cAPS lOCK KEY?";

StringBuilder sb = new StringBuilder(qstn);

for (int j = 0; j < sb.Length; j++)

{

if ( Char.IsLower(sb[j]) == true) // если буква маленькая,

sb[j] = Char.ToUpper(sb[j]); // то заменим ее большой

else if (Char.IsUpper(sb[j]) == true) // и наоборот большую -

sb[j] = Char.ToLower(sb[j]); // маленькой

}

// Сохраним результат в новую строку

string corrected = sb.ToString();

Console.WriteLine(corrected);

// Output: How does Microsoft Word deal with the Caps Lock key?

Пример 4.1. Дан текст, состоящий из английских букв, цифр и символов. Надо вывести на печать такие последовательности букв и цифр, где на втором месте стоит буква 'd'. Посчитать их количество. Например, для текста, состоящего из двух строк: 1der, 6789, gdq34 +09 -dad....

tyda ne00xodi 90 su 6da idi!

ответом будет: kolvo= 4 1der gdq34 6da idi!

Ввод данных( текста) в этой лабораторной работе будет производиться из файла. Для этого необходимо

1) подключить библиотеку ввода-вывода:

using System.IO;

2) создать объект- читатель файла:

StreamReader MyFile = new StreamReader("text.txt");

здесь MyFile – имя переменной, закрепленной за файлом text.txt. После этого методом ReadLine() мы можем читать из входного файла строки.

Обсудим общую схему решения данной задачи. Для вывода результата нам нужна переменная-счетчик, в которой будет хранится число искомых последовательностей( int counter) и строка ( StringBuilder otvet), в которую мы будем заносить сами искомые последовательности. После прочтения строки из входного файла необходимо разбить ее на «слова», состоящие из букв и цифр. Границей слова будет пробел, знак препинания или арифметической операции. Это разбиение можно сделать вручную посимвольно рассматривая содержимое строки, а можно воспользоваться методом Split, на входе которого массив символов-разделителей, а на выходе – массив слов. Нам останется лишь проверить в цикле все элементы этого массива на наличие буквы «d» на втором месте и при выполнении условия добавить к счетчику единицу, а это слово в строку-ответ.

static void Main(string[] args)

{

int counter = 0; // счетчик слов, где d стоит на 2м месте

string line; // вспомогательная строка

char[] separator = { ' ', '.', '*', '+', ';', ',', '?', '!', '-', '/' };

StringBuilder otvet = new StringBuilder(); // строка-ответ

using (StreamReader MyFile = new StreamReader("text.txt"))

{

// чтение строки из файла, пока это возможно

while ((line = MyFile.ReadLine()) != null)

{

Console.WriteLine(line); // печатаем, что прочитали

// выделяем слова

string[] words = line.Split(separator);

foreach (string slovo in words) // цикл по словам

{

if ((slovo.Length >= 2) && (slovo[1] == 'd'))

{

counter++;

otvet.Append(slovo);

otvet.Append(" ");

}

}

}

}

Console.WriteLine("There were {0} sequences.", counter);

Console.WriteLine(otvet.ToString());

Console.ReadLine();

}

Пример 4.2. Дан текст; найти наибольшее количество цифр, идущих в нем подряд.

Наиболее простой способ решения этой задачи состоит в следующем: будем посимвольно просматривать каждую прочитанную строчку и, если встретилась группа цифр, сравнивать ее длину с максимальной на данный момент.

static void Main()

{

byte counter = 0, // счетчик текущей группы цифр

max =0; // длина максимальной группы цифр

string stroka;

int i;

using (StreamReader MyFile = new StreamReader("test.txt"))

{

// пока файл не пуст, читаем строку

while ((stroka = MyFile.ReadLine()) != null)

{

Console.WriteLine(stroka); // печатаем, что прочитали

i=0; // индекс символа в строке

while( i < stroka.Length)

{

// цикл, пока не встретится цифра или конец строки

while( (i< stroka.Length)&& !(char.IsDigit(stroka,i)))

{

i++;

}

// встретилась цифра или строка закончилась

counter = 0;

// цикл пока очередной символ - цифра

while( (i< stroka.Length)&& (char.IsDigit(stroka,i)))

{

counter ++;

i++;

}

// изменяем максимальную длину, если необходимо

if( counter > max )

max = counter;

}

}

}

Console.WriteLine("Длина максим. посл-ти цифр = {0}.", max);

Console.ReadLine();

}

Следует отметить, что существует несколько различных алгоритмов решения этой задачи( да и почти любой другой). Так, можно было занести в массив разделителей все допустимые в тексте символы, кроме цифр и воспользоваться методом Split для выделения всех «слов», состоящих из цифр. Затем просто найти максимальную длину «слова».

Проверкой правильности реализованного алгоритма является тестирование программы. Причем для каждой задачи составляется набор тестов, проверяющих все возможные варианты данных. Например, для примера 4.2, целесообразно сформировать следующий набор тестов:

  • в тексте нет ни одной группы цифр( ответ -0);

  • несколько групп цифр, причем максимальная находится в начале строки (12345, вышел зайчик погулять 12 5, ответ -5);

  • несколько групп цифр, но максимальная находится в конце строки;( 1-2, 3-4, 3-4, 12, ответ - 2)

  • текст состоит из нескольких строк с группами цифр в хаотичном порядке.

Каждый тестовый пример записывается в отдельный файл( например, test1.txt, … test4.txt) и работа программы проверяется на каждом тесте. Если обнаружена ошибка, то, после ее исправления, тестирование начинается опять с первого теста.

Пример 4.3. Дан текст, каждый символ которого может быть латинской буквой, цифрой или одним из знаков арифметических операций. Группой букв будем называть такую совокупность последовательно расположенных букв, которой непосредственно не предшествует и за которой непосредственно не следует буква. Аналогично определяется группа цифр и группа знаков. Выяснить, верно ли, что в данном тексте больше групп букв, чем групп цифр.

Алгоритм решения этой задачи состоит в следующем: заведем два счетчика для групп букв и цифр соответственно, затем в каждой прочитанной строке будем выделять группы букв и цифр и увеличивать значения соответствующих счетчиков.

static void Main(string[] args)

{

byte dcounter = 0, // счетчик груп цифр

wcounter= 0; // счетчик групп букв

string stroka;

int i;

using (StreamReader MyFile = new StreamReader("test.txt"))

{

// пока файл не пуст, читаем строку

while ((stroka = MyFile.ReadLine()) != null)

{

Console.WriteLine(stroka);

i = 0; // индекс символа в строке

while (i < stroka.Length)

{

// цикл, пока не встретится цифра или буква или конец строки

while ((i < stroka.Length) && !(char.IsLetterOrDigit(stroka, i)))

{

i++;

}

// встретилась цифра и строка не закончилась

if ((i < stroka.Length) && (char.IsDigit(stroka, i)))

dcounter++;

// цикл пока очередной символ - цифра

while ((i < stroka.Length) && (char.IsDigit(stroka, i)))

{

i++;

}

// встретилась буква и строка не закончилась

if ((i < stroka.Length) && (char.IsLetter(stroka, i)))

wcounter++;

// цикл пока очередной символ - буква

while ((i < stroka.Length) && (char.IsLetter(stroka, i)))

{

i++;

}

}

}

}

// сравнение счетчиков и вывод результата

if (wcounter > dcounter)

{

Console.Write("Групп букв больше: ");

Console.WriteLine("{0}>{1}", wcounter, dcounter);

}

else if (dcounter > wcounter)

{

Console.Write(" Групп цифр больше: ");

Console.WriteLine(" {0}>{1}.", dcounter, wcounter);

}

else

{

Console.Write(" Групп цифр и букв равное кол-во: ");

Console.WriteLine(" {0} = {1}.", wcounter, dcounter);

}

Console.ReadLine();

}

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]