ЛабРаб_ООП
.pdfParse |
Перетворить рядок в |
символ. Природно, рядок повинен складатися |
|
з одного символу, інакше виникне помилка |
|
ToLower |
Приводить символ до |
нижнього регістра |
ToUpper |
Приводить символ до |
верхнього регістра |
MaxValue, MinValue |
Властивості, що повертають символи з максимальним і |
|
|
мінімальним кодом. Символи, що повертаються, не мають видимого |
|
|
образу |
|
Клас String
Тип даних string (рядки Unicode) – це вбудований тип даних C#. Всі рядки в C# і .NET походять від єдиного базового класу System.String. Цей базовий клас забезпечує ряд методів, які покликані виконати за вас всю чорнову роботу: повернути кількість символів в рядку, знайти підрядки, перетворити всі символи в рядкові або прописні і т.д. Найбільш використовувані члени класу System.String представлені в таблиці 4.
Таблиця 4. Деякі члени класу System.String.
Ім'я члена класу |
Призначення |
Length |
Ця властивість повертає довжину вказаного рядка |
Concat() |
Цей статичний метод класу String повертає новий рядок, «склеєний» з |
|
двох даних рядків |
CompareTo() |
Порівнює два рядки |
Copy() |
Цей статичний метод створює нову копію існуючого рядка |
Format() |
Використовується для форматування рядка |
Insert() |
Використовується для вставки рядка всередину рядка |
PadLeft() PadRight() |
Дозволяють наповнити («набити») рядок вказаними символами |
Remove() Replace() |
Дозволяють створити копію рядка з внесеними змінами |
int IndexOf(string str) |
Виконує в рядку пошук підрядка, заданого параметром str. Повертає |
|
індекс першого входження шуканого підрядка або -1, якщо підрядок не |
|
буде виявлений |
string Substring(int |
Повертає рядок, який містить задану частину рядка |
start, int len) |
|
ToUpper() ToLower() |
Для отримання копії рядка, в якому всі символи стануть рядковими або |
|
прописними |
Постійність рядків
Наступне твердження, ймовірно, вас здивує: вміст string-об'єктів незмінний. Іншими словами, послідовність символів, складових рядка, змінити не можна. Так, всі методи, перераховані в таблиці 2, повертають новий рядок з необхідними змінами.
Приклад.
using System;
class SubStr {
public static void Main() {
string orgstr = “C# спрощує роботу з рядками.”; //Створення підрядка.
string substr = orgstr.Substring(3,16); Console.WriteLine(“orgstr: “ + orgstr); Console.WriteLine(“substr: “ + substr);
}
}
А ось як виглядають результати роботи цієї програми:
31
orgstr: C# спрощує роботу з рядками. substr: спрощує роботу
Клас StringBuilder - будівник рядків
Клас string не дозволяє змінювати існуючі об'єкти. Рядковий клас StringBuilder дозволяє компенсувати цей недолік. Цей клас належить до змінних класів і його можна знайти в просторі імен System.Text. Розглянемо клас StringBuilder докладніше.
Оголошення рядків. Конструктори класу StringBuilder
Об'єкти цього класу оголошуються з явним викликом конструктора класу. Конструктор класу перевантажений, і разом з конструктором без параметрів, що створює порожній рядок, складає набір конструкторів, яким можна передати дві групи параметрів. Перша група дозволяє задати рядок або підрядок, значенням якого ініціалізується створюваний об'єкт класу StringBuilder. Друга група параметрів дозволяє задати місткість об'єкту - об'єм пам'яті, що відводиться даному екземпляру класу StringBuilder. Кожна з цих груп не є обов'язковою і може бути опущена. Прикладом може служити конструктор без параметрів, який створює об'єкт, що ініціалізований порожнім рядком, і з деякою місткістю, заданою за умовчанням, значення якої залежить від реалізації. Приведемо як приклад синтаксис трьох конструкторів:
public StringBuilder (string str, int cap). Параметр str задає рядок ініціалізації, cap - місткість об'єкту;
public StringBuilder (int curcap, int maxcap). Параметри curcap і maxcap задають початкову і максимальну місткість об'єкту;
public StringBuilder (string str, int start, int len, int cap). Параметри str, start, len задають рядок ініціалізації, cap - місткість об'єкту.
Операції над рядками
Над рядками цього класу визначені практично ті ж операції з тією ж семантикою, що і над рядками класу String: привласнення (=); дві операції перевірки еквівалентності (= =) і (!=); узяття індексу ([]).
Операція конкатенації (+) не визначена над рядками класу StringBuilder, її роль грає метод Append, що дописує новий рядок в хвіст що вже існує.
З рядком цього класу можна працювати як з масивом, але, на відміну від класу String, тут вже все робиться як треба: допускається не тільки читання окремого символу, але і його зміна. Розглянемо приклад:
public void TestStringBuilder()
{
//Рядки класу StringBuilder //операції над рядками
StringBuilder s1 =new StringBuilder("ABC") s2 =new StringBuilder("CDE");
StringBuilder s3 = new StringBuilder(); //s3= s1+s2;
s3= s1.Append(s2); bool b1 = (s1==s3);
char ch1 = s1[0], ch2=s2[0]; Console.WriteLine("s1={0}, s2={1}, b1={2}" +
"ch1={3}, ch2={4}", s1,s2,b1,ch1,ch2); s2 = s1;
b1 = (s1!=s2); ch2 = s2[0];
Console.WriteLine("s1={0}, s2={1}, b1={2}" + "ch1={3}, ch2={4}", s1,s2,b1,ch1,ch2); StringBuilder s = new StringBuilder("Zenon");
s[0]='L';
Console.WriteLine(s);
32
}//TestStringBuilder
Цей приклад демонструє можливість виконання над рядками класу StringBuilder тих же операцій, що і над рядками класу String. В результаті привласнення створюється додаткове посилання на об'єкт, операції перевірки на еквівалентність працюють із значеннями рядків, а не з посиланнями на них. Конкатенацію можна замінити викликом методу Append. З'являється нова можливість - змінювати окремі символи рядка. (Для того, щоб ім'я класу StringBuilder стало доступним, в проект додана пропозиція using System.Text, що посилається на відповідний простір імен.)
Робота з файлами
Будь-яке введення і виведення інформації в .NET Framework включає використання потоків – абстрактних представлень послідовних пристроїв.
У просторі імен System.IO зберігаються класи, призначені для прочитування даних з файлів і запису даних у файли; для того, щоб дістати в програмі доступ до цих класів, необхідно послатися на цей простір імен. Найчастіше використовуються наступні класи.
•File – широко використовуваний на практиці клас, який володіє великою кількістю
статичних методів, що дозволяють переносити, копіювати і видаляти файли.
•Directory – клас, який володіє великою кількістю статичних методів, що дозволяють
переносити, копіювати і видаляти директорії.
•Path – клас, що дозволяє виконувати маніпуляції над іменами шляхів.
•FileInfo – представляє фізичний файл, розташований на диску, і володіє методами, що
дозволяють виконувати маніпуляції над цим файлом. Для будь-яких операцій читання/запису, що виконуються над файлом, необхідно створити об'єкт Stream.
•DirectoryInfo – представляє фізичну директорію, розташовану на диску, і володіє
методами, що дозволяють виконувати маніпуляції над цією директорією.
•FileStream – представляє файл, який допускає або прочитування, або запис, або і те і
інше одночасне. Цей файл може прочитуватися як синхронно, так і асихронно.
•StreamReader – прочитує символьну інформацію з потоку і може створюватися на базі
класу FileStream.
•StreamWriter – записує символьну інформацію в потік і може створюватися на базі класу
FileStream.
Класи File і Directory
Обидва класи надають велику кількість методів для здійснення маніпуляцій над самою файловою системою, а також над файлами і директоріями. Ці методи є статичними і дозволяють переміщати файли, запрошувати і вносити зміни до атрибутів, а також створювати об'єкти FileStream. Нагадаємо, що статичні методи можуть викликатися класами без створення їх екземплярів.
Клас FileInfo
На відміну від класу File, клас FileInfo не володіє статичними методами і може використовуватися тільки за допомогою створення екземплярів об'єктів. Об'єкт FileInfo представляє файл, розташований на диску або за деякою мережевою адресою. Відмітьте, що цей клас не є потоком. Для того, щоб здійснити запис у файл або читання з файлу, необхідно створити об'єкт Stream. Об'єкт FileInfo дозволяє вирішити цю задачу, надаючи декілька методів, які повертають створені екземпляри об'єктів Stream. Проте, перш за все, для того, щоб створити об'єкт FileInfo, необхідно вказати шлях до файлу або директорії:
FileInfo aFile = new FileInfo(“C:/log.txt”);
33
Багато методів, що надаються класом FileInfo, аналогічні відповідним методам класу File, проте, оскільки клас File є статичним класом, він вимагає завдання рядкового параметра з місцеположенням файлу при кожному виклику методу.
Об'єкт FileStream
Об'єкт FileStream представляє потік, вказуючий на який-небудь файл на диску або на місцеположення в мережі. Хоча цей клас і володіє методами для читання з файлів і запису у файли байтів, частіше для виконання цих функцій вам доведеться звертатися до класів StreamReader і StreamWriter. Це відбувається тому, що клас FileStream оперує байтами і масивами байтів, тоді як класи Stream оперують символьними даними. Мати справу з символьними даними виявляється простішим, проте нам доведеться зіткнутися з деякими операціями, наприклад, з довільним доступом до файлів, які можуть здійснюватися тільки за допомогою об'єкту FileStream.
Існує декілька способів створення об'єкту FileStream. Його конструктор володіє великою кількістю перевантажень/версій, проте в найпростішому випадку він вимагає передачі двох аргументів – імені файлу і значення типа перераховного FileMode:
FileStream aFile = new FileStream(“Log.txt”, FileMode.OpenOrCreate);
У перераховного типа FileMode є декілька членів, які дозволяють задавати те, яким чином файл відкривається або створюється: Append, Create, CreateNew, Open, OpenOrCreate, Truncate. Допускається їх використання в різних поєднаннях.
Приведений вище приклад конструктора за умовчанням відкриває файл в режимі читання/запису. Для того, щоб задати інший рівень доступу, слід використовувати додатковий параметр – FileAccess:
FileStream aFile = new FileStream(“Log.txt”, FileMode.OpenOrCreate, FileAccess.Write);
Цей рядок коду відкриє файл з дозволом доступу на запис. Будь-яка спроба прочитати вміст цього файлу приведе до виникнення виняткової ситуації. Перераховний тип FileAccess володіє всього трьома значеннями: Read, Write і ReadWrite. Отже, є можливість відкрити файл тільки на читання, тільки на запис і на читання і запис одночасно.
Обидва класи File і FileInfo надають методи OpenRead() і OpenWrite(), які полегшують створення об'єктів FileStream. Перший метод відкриває файл з режимом доступу “тільки читання”, а другий, крім того, дозволяє здійснювати запис. Це дозволяє спростити звернення до файлу, так що вам тепер не доведеться указувати всю інформацію, як в попередніх прикладах. Наприклад, наступний рядок відкриває файл Data.txt у режимі “тільки читання”:
FileStream aFile = File.OpenRead(“Data.txt”);
Звернете увагу на те, що наступний код виконує ті ж самі дії:
FileInfo aFile = new FileInfo(“Data.txt”);
FileStream aFile = aFile.OpenRead();
Позиція усередині файлу
Клас FileStream підтримує внутрішній покажчик файлу, що посилається на те місце у файлі, в якому проводитиметься чергова операція читання або запису. В більшості випадків при відкритті файлу покажчик встановлюється в початок файлу, проте така поведінка покажчика може бути змінена, що дозволяє здійснювати читання або запис в будь-якій точці файлу. Можна також організувати довільний доступ до файлу і здійснювати пошук конкретної позиції у файлі.
Метод, який реалізує дану функціональну можливість, носить назву Seek():
public long Seek(long offset, SeekOrigin origin);
Перший параметр визначає, наскільки далеко уперед в байтах повинно пересунути покажчик. Другий параметр визначає, з якої точки вести відлік. Перераховний тип SeekOrigin складається з
34
трьох значень: Begin (початок), Current (поточна позиція) End (кінець). Наступний рядок пересуває покажчик файлу на восьмий байт, рахуючи з найпершого байта даного файлу:
aFile.Seek(8, SeekOrigin.Begin);
Існує також можливість указувати негативні значення для визначення необхідної позиції. Наприклад, наступний рядок дозволить перейти до п'ятого з кінця байта файлу:
aFile.Seek(-5, SeekOrigin.End);
Файли, доступ до яких може здійснюватися таким чином, часто називають файлами з довільним доступом, оскільки у застосування є можливість дістати доступ до будь-якої позиції у файлі. Класи Stream дозволяють здійснювати послідовний доступ до файлів, і в них не передбачена можливість роботи з покажчиками.
Читання даних
Читання даних з використанням класу FileStream виявляється не таким простим, як з використанням класів StreamReader і StreamWriter, до розгляду яких ми повернемося нижче. Це відбувається тому, що клас FileStream має справу виключно з байтами, що робить клас корисним при роботі з файлами довільного типу, а не тільки з текстовими файлами. Побайтне прочитування даних дозволяє використовувати цей клас при роботі з графічними і звуковими файлами. Проте платою за подібну гнучкість є неможливість за допомогою класу FileStream прочитувати дані безпосередньо змінні типу рядка. Це дозволяють здійснювати класи StreamWriter і StreamReader. Існує проте декілька конверсійних класів, які істотно полегшують виконання перетворення масиву байтів в символьні масиви і назад.
Метод FileStream.Read() є основним засобом, що дозволяє здійснювати доступ до даних, що містяться у файлі, на який посилається об'єкт FileStream.
public int Read(byte[] array, int offset, int count);
Перший параметр є масив байтів, що передається для розміщення в нім даних, отримуваних від об'єкту FileStream. Другий параметр визначає ту позицію в масиві байтів, починаючи з якої повинна здійснюватися операція запису даних. Зазвичай цей параметр має значення, рівне нулю. Останній параметр визначає, яка кількість байтів повинна бути прочитана з файлу.
Вказівки до завдання 1.
Треба дати компонентам, поміщеним на форму, наприклад такі імена: openFile – для кнопки (Button), filename – для однорядкового текстового поля (TextBox), source – для багаторядкового текстового поля (TextBox), openFileDialog – для діалогу відкриття файлів (невізуальний компонент OpenFileDialog).
У властивості Filter компоненту openFileDialog прописати, наприклад “All files | *.*”.
В обробнику натиснення на кнопку openFile активізувати діалог відкриття файлу наступною командою:
openFileDialog.ShowDialog();
Створити обробник події FILEOK для компоненту openFileDialog. У цьому обробнику отримати ім'я файлу і відобразити це ім'я в текстовому полі:
string fullPathname = openFileDialog.FileName; FileInfo src = new FileInfo(fullPathname); filename.Text = src.Name;
source.Text = "";
Далі працювати з об'єктом типа TextReader, прочитуючи рядки з файлу в циклі while і відображаючи їх в багаторядковому текстовому полі.
35
Лабораторна робота №3. Обробка виключень в C#.
Мета роботи: засвоїти основи обробки виключень в мові C#, набути практичних навичок обробки виключень.
Завдання.
Удосконалити простий калькулятор (Лабораторна робота №1, завдання 3), ввівши в нього обробку виключень, пов'язаних з неправильним введенням даних.
Хід роботи.
1.Виконати Вправу 1.
2.Виконати Вправу 2.
3.Виконати завдання.
Вправа 1.
Нижче приведений простий приклад, що демонструє як відстежити і перехопити виключення. Відомо, що спроба індексувати масив за межами його меж викликає помилку порушення діапазону. В цьому випадку C#-система динамічного управління генерує виключення типа IndexOutOfRangeException, яке є стандартним виключенням, визначеним мовою C#. У наступній програмі таке виключення навмисно генерується, а потім перехоплюється.
// Демонстрація обробки виключень.
using System;
class ExcDemo1 {
public static void Main(){ int[] nums = new int[4];
try { Console.WriteLine(
“Перед генеруванням виключення.”); // генеруємо виключення, пов'язане з попаданням індексу поза діапазоном. for(int i=0; i<10; i++){
nums[i]= i;
Console.WriteLine(“nums[{0}]: {1}”, i, nums[i]);
36
}
Console.WriteLine(“Цей текст не відображається.”);
}
catch (IndexOutOfRangException) { //Перехоплюємо виключення.
Console.WriteLine(“Індекс поза діапазоном!”);
}
Console.WriteLine(“Після catch-інструкції.”);
}
}
Вправа 2.
Демонстрація блоків try ... catch ... finally. У циклі користувачеві пропонують ввести число із заданого діапазону, і потім це число виводиться на екран. Якщо введене число не належить заданому діапазону, то генерується виключення.
using System;
namespace AdvancedCSharp
{
public class MainEntryPoint
{
public static void Main()
{
string userInput; while(true)
{
try
{
Console.Write("Input а number between 0 and 5 " + "(or just hit return to exit)> ");
userInput = Console.ReadLine(); if(userInput == "")
break;
int index = Convert.ToInt32(userInput); if(index < 0 || index > 5)
throw new IndexOutOfRangeException ( "You typed in " + userInput); Console.WriteLine("Your number was " + index);
}
catch (IndexOutOfRangeException e)
{
Console.WriteLine("Exception: " +
"Number should be between 0 and 5. " + e.Message);
}
catch (Exception e)
{
Console.WriteLine("An exception was thrown. Message was " + e.Message);
}
catch
{
Console.WriteLine("Some other exception has occurred");
}
finally
{
Console.WriteLine("Thank you");
}
}
}
}
}
37
Методичні вказівки та теоретичні відомості.
Виняткова ситуація (або виключення) – це помилка, яка виникає під час виконання програми. Використовуючи C#-подсистему обробки виняткових ситуацій, з такими помилками можна справлятися. Можливо, найпростішим прикладом є спроба звернутися до елементу масиву, що виходить за його межі:
int[] myArray = {1,2,3,4}; int myElem = myArray[4];
В результаті з'явиться приведене нижче повідомлення про виняткову ситуацію, а виконання застосування буде припинено:
An unhandled exception of type ‘System.IndexOutOfRangeException’ occurred in <file>.exe
Тут <file> – це ім'я файлу, в якому міститься дана виняткова ситуація.
Клас System.Exception
У C# виключення представляються класами. Всі класи виключень повинні бути виведені з вбудованого класу виключень Exception, який є частиною простору імен System.
Основи обробки виключень
У мові програмування C# передбачений спеціальний синтаксис для Structured Exception Handling (SEH – структурованої обробки виключень). Існують спеціальні ключові слова, що дозволяють позначати ділянки коду як ділянки, в яких допустима обробка виняткових ситуацій, і розміщувати інструкції, вказуючі, що слід робити при виникненні виняткової ситуації. Для цих цілей використовуються чотири ключові слова: try, catch, throw і finally. Кожному з них відповідає якийсь блок коду, і всі вони повинні поміщатися в послідовно розташованих рядках коду. Основна інструкція має наступний вигляд:
try{
. . .
}
catch (<типВинятковоїСитуації> e)
{
. . .
}
finally{
. . .
}
Існує також можливість використовувати блоки try та finally без блоку catch, а також блок try з декількома блоками catch. Якщо є один або декілька блоків catch, то блок finally є необов'язковим, інакше він обов'язковий.
Ці блоки використовуються таким чином:
•try містить код, який може привести до виникнення виняткової ситуації.
•catch містить код, який повинен виконуватися у разі виникнення виняткової ситуації. Блоки catch можуть бути настроєні так, щоб реагувати тільки на один конкретний тип виняткової ситуації (наприклад, на System.IndexOutOfRangeException), для чого використовується параметр <типВинятковоїСитуації>, оскільки існує можливість одночасно встановити декілька блоків catch. Але можна і взагалі опустити цей параметр, тоді вийде загальний блок catch, який реагуватиме на всі види виняткових ситуацій.
•finally містить блок коду, який виконується завжди: або після виконання блоку try, якщо не виникло ніяких виняткових ситуацій, або після блоку catch, якщо проводилася обробка
38
виняткової ситуації, або безпосередньо перед тим, як застосування буде завершено із-за виникнення необроблюваної виняткової ситуації.
Події, що відбуваються після виникнення виняткової ситуації в блоці коду try, мають таку послідовність:
•Виконання блоку try припиняється в тій точці, в якій виникла виняткова ситуація.
•Якщо існує блок catch, то проводиться перевірка на предмет того, чи співпадає його параметр з типом виниклої виняткової ситуації. Якщо блок catch відсутній, то виконується блок finally (який в цьому випадку є обов'язковим).
•Якщо блок catch існує, але значення його параметра не співпадає з типом виниклої виняткової ситуації, перевірка проводиться в інших блоках catch.
•Якщо параметр блоку catch співпадає з типом виниклої виняткової ситуації, то спочатку виконується код, що міститься в блоці, а потім – у випадку, якщо він присутній, - виконується блок finally.
•Якщо жоден з блоків catch не відповідає типу виниклої виняткової ситуації, то виконується блок finally (якщо він існує).
Щоб згенерувати виключення вручну, використовується ключове слово throw. Синтаксис його використання такий:
throw exceptOb;
Елемент – це об'єкт класу виключень, похідного від класу Exception.
Розглянемо приклад, який демонструє використання інструкції throw для генерування виключення типа DivideByZeroException уручну.
using System; class ThrowDemo {
public static void Main(){ try {
Console.WriteLine(“До генерування виключення.”); throw new DivideByZeroException();
}
catch (DivideByZeroException){ //Перехоплюємо виключення
Console.WriteLine(“Виключення перехоплене.”);
}
Console.WriteLine(“Після try/catch-блока.”);
}
}
І ще один приклад.
using System; class TestMain
{
private static void Test() // Run time error
{
for(int i=-10;i<=10;++i) int y=100/i; }
}
public static void Main( )
{
try
{
Test();
}
catch
{
39
Console.WriteLine("Got an exception....");
}
}
}
Лабораторна робота №4. Використання масивів і колекцій. Класи ArrayList, Queue, Stack, Hashtable, SortedList.
Мета роботи: засвоїти основи використання масивів і колекцій в мові C#, набути практичних навичок роботи з двовимірними масивами.
Варіанти завдання.
Варіант 1. Дана цілочисельна прямокутна матриця. Визначити:
1)кількість рядків, що не містять жодного нульового елементу;
2)максимальне з чисел, що зустрічаються в заданій матриці більше одного разу.
Варіант 2. Дана цілочисельна прямокутна матриця. Визначити кількість стовпців, що не містять жодного нульового елементу.
Характеристикою рядка цілочисельної матриці назвемо суму її позитивних парних елементів. Переставляючи рядки заданої матриці, розташувати їх відповідно до зростання характеристики.
Варіант 3. Дана цілочисельна квадратна матриця. Визначити:
1)добуток елементів в тих рядках, які не містять негативних елементів;
2)номер рядка, в якому знаходиться найдовша серія однакових елементів.
Варіант 4. Серед тих рядків цілочисельної матриці, які містять тільки непарні елементи, знайти рядок з максимальною сумою модулів елементів.
Варіант 5. Підрахувати кількість рядків заданої цілочисельної матриці NхN, що є перестановкою чисел 1,2...N (тобто що містять кожне з чисел 1,2...N рівно один раз).
Варіант 6. Серед стовпців заданої цілочисельної матриці, що містять тільки такі елементи, які по модулю не більше 10, знайти стовпець з мінімальним добутком елементів.
Варіант 7.
Масивом char а[M][N] кодується поле, на якому розташовано декілька прямокутників. Кожен складається з цілого числа кліток, різні прямокутники не накладаються один на одного і не стикаються. Різні прямокутники можуть складатися з різних символів. Один і той же прямокутник не може складатися з різних символів. Порожні квадрати поля кодується символом '.'. Підрахувати число прямокутників різних типів. Поле вводиться з клавіатури або читається з файлу. Приклад:
###...??..+.
###.=.??..+.
###.......+.
.....???....
???.......==
???...####..
Для цього поля програма повинна видати відповідь:
#-прямоугольников: 2 ?-прямоугольников: 3 +-прямоугольников: 1 =-прямоугольников: 2
40