Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

lec

.pdf
Скачиваний:
40
Добавлен:
24.03.2015
Размер:
3.43 Mб
Скачать

данного выражения. Вторая игнорирует переполнение, которое возможно в блоке инструкций.

Формат:

unchecked (выражение)

или unchecked

{

// Инструкции, для которых переполнение игнорируется.

}

В случае переполнения выражение усекается: byte a=127, b=127, result;

try {

 

result = checked ( (byte)(a*b) );

// инструкция вызовет

}

// исключение.

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

Вариант 1. Для большого количества вводимых данных. Один блок try и один блок catch на все операции ввода. После обработки исключения повторяется весь выполненный ввод, включая правильный, заново. Этот вариант хорош для отладки, но не для итоговой программы.

using System; class TestTryCatch

{

public static void Main()

{

double a, b, c;

while (true)

{

try

{

Console.Write("Введи первое вещественное число:"); a = double.Parse(Console.ReadLine());

Console.Write("Введи второе вещественное число:"); b = double.Parse(Console.ReadLine());

Console.Write("Введи третье вещественное число:"); c = double.Parse(Console.ReadLine());

break;

}

catch

{

151

Console.WriteLine("\nВведено неверное данное! " +

"Повторите весь ввод заново.\n");

//continue; //нужен, если после catch в этом

//цикле следует какая-либо обработка

}

} // while-end

Console.WriteLine("Ввод закончен!\n");

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

. . .

}

}

Вариант 2. Блоки try и catch на каждый оператор ввода. Самый простой вариант, но при большом количестве вводимых данных – самый длинный.

using System; class TestTryCatch

{

public static void Main()

{

double a, b;

while (true)

{

Console.Write("Введи первое вещественное число:"); try

{

a = double.Parse(Console.ReadLine()); break;

}

catch

{

Console.WriteLine("\nВведено неверное данное!\n");

}

}

while (true)

{

Console.Write("Введи второе вещественное число:"); try

{

b = double.Parse(Console.ReadLine()); break;

}

catch

{

Console.WriteLine("\nВведено неверное данное!\n");

}

}

152

Console.WriteLine("Ввод закончен!\n"); // далее основная часть программы

. . .

}

}

Вариант 3. Для большого количества вводимых данных. Один блок try и один блок catch на все операции ввода. Запоминается номер ошибочного ввода. После обработки исключения повторяется только последний ошибочный ввод.

using System; class TestTryCatch

{

public static void Main()

{

double a, b, c;

 

bool

rep=true;

 

int

n=1;

// номер неудачного ввода

while (rep==true)

 

{

 

 

try

 

 

{

 

 

switch (n)

 

{

 

 

case 1:

 

 

Console.Write("Введи первое вещественное число:");

 

a = double.Parse(Console.ReadLine());

 

n = 2;

// N следующего ввода

 

break;

 

case 2:

 

 

Console.Write("Введи второе вещественное число:");

 

b = double.Parse(Console.ReadLine());

 

n = 3;

 

 

break;

 

case 3:

 

 

Console.Write("Введи третье вещественное число:");

 

c = double.Parse(Console.ReadLine());

 

n = 1;

// для повтора программы

 

rep = false;

// для выхода из цикла while

 

break;

 

}

}

 

 

 

catch

{

Console.WriteLine("\nВведено неверное данное!\n"); //continue; //если после catch в этом цикле следует обработка

}

} // while-end

153

rep=true;

// для повтора программы

Console.WriteLine("Ввод закончен!\n"); // далее основная часть программы

. . .

}

}

154

БАЙТОВЫЕ И СИМВОЛЬНЫЕ ПОТОКИ

1. Организация С#-системы ввода-вывода

Понятие потока Внешние устройства делятся на:

Устройства ввода-вывода (дисплей, клавиатура, принтер, последовательный порт, мышь, сканер и т.д.)

Запоминающие устройства последовательного доступа (стример)

Запоминающие устройства прямого доступа (МД, CD-ROM, DVDROM);

С#-программы выполняют операции ввода-вывода посредством потоков. С точки зрения концепции ввода/вывода, поток (stream) — это абстракция, которая определяется как последовательность байтов, участвующих в операции ввода/вывода и независящая от устройства.

С точки зрения реализации, поток – это объект, используемый для передачи данных.

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

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

ПОТОК

 

ПОТОК

?

Обработка

?

данных

рис.1

На самом низком уровне все С#-системы ввода-вывода оперируют байтами. На физическом уровне Windows используется буферизация и кэширование записей. Их целью является:

согласование ввода/вывода с характеристиками внешнего устройства;

повышение эффективности системы, за счет уменьшения количества операций ввода/вывода с внешними устройствами, например, с диском.

155

Буферизованный ввод-вывод:

 

 

Windows

 

 

 

буфер ОС

ПП

NTFS

блок

строка

 

 

Файл

 

блок

символ

 

 

 

 

 

рис.2

 

Буфер заполняется блоками (кластерами): первый раз при открытии файла для чтения.

Буферов может быть несколько.

Программа

Буферы

• • •

Файл

• • •

см. Flush

рис. 3

Синхронный и асинхронный ввод/вывод Как правило, после запуска операции ввода-вывода программа пере-

ходит в состояние ожидания и выходит из него только после завершения обмена. Такой способ выполнения операций ввода-вывода называется

синхронным.

Однако продолжительный ввод-вывод целесообразно выполнять в асинхронном режиме, когда программа не блокируется, а продолжает выполняться. Асинхронный режим реализуется с помощью подпрограммы обратного вызова (на рис.4 – ПОВ). Об этом пойдет речь в других лекциях.

рис.4

156

0

ПП

 

 

Read()

 

О

 

ж

 

и

 

д

 

а

 

н

 

и

 

е

ПП

BeginRead (ПОВ)

ПОВ

EndRead()

Синхронный в/в

Асинхронный в/в

t

Стандартные потоки В С# определен ряд классов, которые преобразуют байтовый поток в

символьный, и наоборот, выполняя byte-char- и char-byte-перевод автоматически.

Наряду с байтовыми и символьными потоками существуют двоичные потоки.

Кроме потоков, создаваемых программами, в Windows существуют несколько встроенных (стандартных) потоков.

Эти потоки не надо создавать, они всегда доступны программам.

2. Классы потоков

Все классы потоков (кроме стандартных) определены в пространстве имен System.IO.

Центральную часть байтовой потоковой С#-системы занимает класс

System.IO.Stream.

public abstract class Stream

: MarshalByRefObject, IDisposable

public

class

FileStream

: Stream

public

class

MemoryStream

: Stream

157

public abstract

class

TextReader : MarshalByRefObject, Idisposable

public abstract

class

TextWriter : MarshalByRefObject, Idisposable

public class StreamReader : TextReader public class StreamWriter : TextWriter

public class StringReader : TextReader public class StringWriter : TextWriter

public class BinaryReader : Idisposable public class BinaryWriter : Idisposable

Основные классы.

потоковые: FileStream, StreamReader, StreamWriter, BinaryReader, BinaryWriter, Console.

непотоковые: File.

abstract TextReader

abstract TextWriter

StreamReader

 

StringReader

 

StreamWriter

 

StringWriter

 

 

 

 

 

 

 

abstract Streem

FileStream MemoryStream

рис. 5

158

Другие классы: MemoryStream, NetworkStream, BufferedStream, CryptoStream.

3. Консольный ввод-вывод данных

C#-программы в пространстве имен System могут использовать:

стандартный входной поток Console.In, в который вводится информация с клавиатуры;

стандартный выходной поток Console.Out, в который выводится информация, направляемая в консоль (на экран);

стандартный выходной поток Console.Error сообщений об ошибках, в который выводится информация, направляемая в консоль (на экран).

Console.In, Console.Out и Console.Error – это свойства класса Console,

значением которых являются соответствующие символьные потоки (объекты).

Примеры ввода-вывода:

Console.ReadLine(…) и Console.WriteLine(…).

Console.Out и Console.Error — объекты типа TextWriter. Поток Console.In - объект типа TextReader.

Для доступа к этим потокам можно использовать методы и свойства, определенные в классах TextWriter и TextReader соответственно. Однако это целесообразно делать только для потока Console.Error:

public static void Main()

{

int a, b=7, c=0;

try

{

a = b / c;

// Деление на нуль: генерируем исключение.

}

catch (DivideByZeroException exc)

{

Console.Error.WriteLine (exc.Message);

}

}

У стандартных потоков можно, не переделывая программу, менять источник и приемник информации (т.е. перенаправлять поток).

Перенаправить стандартный поток можно двумя способами.

1)средствами Windows (внешними);

2)из программы (внутренними средствами) с помощью методов

SetIn(), SetOut() и SetError(), которые являются членами класса Console.

159

Способ 1. Средствами Windows все стандартные потоки, кроме потока ошибок, могут быть перенаправлены при запуске программы (то есть временно) на любое совместимое устройство ввода-вывода.

Для этого при запуске программы из командной строки можно использовать оператор "<", чтобы перенаправить поток Console.In и операторы ">" и ">>" для перенаправления потока Console.Out.

Примеры.

 

 

example.exe

>

NewFile.txt

example.exe

>> OldFile.txt

example.exe

<

OldFile.txt

example.exe

>

NewFile.txt < OldFile.txt

Способ 2. Перенаправление осуществляется с помощью методов

SetIn(), SetOut() и SetError(), которые являются членами класса Console:

Формат:

 

static void SetIn

(TextReader input)

static void SetOut

(TextWriter output)

static void SetError (TextWriter output)

Такое перенаправление имеет постоянное действие и его нельзя отменить или повторно перенаправить при запуске программы.

Пример.

using System; using System.IO;

class Redirect

{

public static void Main()

{

StreamWriter log_out = new StreamWriter("C:\\logfile.txt");

// Направляем стандартный выходной поток в системный журнал. Console.SetOut(log_out);

Console.WriteLine ("Это начало системного журнала.");

for (int i = 0; i < 10; i++) Console.WriteLine(i);

Console.WriteLine ("Это конец системного журнала."); log_out.Close();

}

}

Можно указывать любой поток, если он является производным от класса TextReader или TextWriter.

4. Чтение и запись двоичных файлов

160

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