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

Объектно-ориентированное программирование.-6

.pdf
Скачиваний:
8
Добавлен:
05.02.2023
Размер:
4.5 Mб
Скачать

 

White, AllowTrailingWhite и AllowHexSpecifier

 

 

Number (0x006f)

Используется комбинация стилей AllowLeading-

 

White, AllowTrailingWhite, AllowLeadingSign, Allow-

 

TrailingSign, AllowDecimalPoint и AllowThousands

 

 

Float (0x00a7)

Используется комбинация стилей AllowLeading-

 

White, AllowTrailingWhite, AllowLeadingSign, Allow-

 

Exponent и AllowDecimalPoint

 

 

Currency (0x017f)

Используется комбинация всех стилей, за исключе-

 

нием AllowExponent и AllowHexSpecifier

 

 

Any (0x01ff)

Используется комбинация всех стилей, за исключе-

 

нием AllowHexSpecifier

 

 

Пример:

string str; int v1; double v2;

NumberFormatInfo nfi = new NumberFormatInfo();

CultureInfo ru = CultureInfo.CreateSpecificCulture("ru-RU"); CultureInfo us = CultureInfo.CreateSpecificCulture("en-US");

str = "A";

v1 = int.Parse(str, NumberStyles.HexNumber); Console.WriteLine("'0x{0}' = '{1}'", str, v1);

str = "

-45

";

 

v1 = int.Parse(str,

NumberStyles.AllowLeadingSign |

NumberStyles.AllowLeadingWhite |

NumberStyles.AllowTrailingWhite); Console.WriteLine("'{0}' = '{1}'", str, v1); str = " (37) ";

v1 = int.Parse(str, NumberStyles.AllowParentheses | NumberStyles.AllowLeadingSign | NumberStyles.AllowLeadingWhite | NumberStyles.AllowTrailingWhite);

Console.WriteLine("'{0}' = '{1}'", str, v1); str = "123,456";

v1 = int.Parse(str, NumberStyles.AllowThousands, us); Console.WriteLine("'{0}' = '{1}' ({2})", str, v1, us.Name); v2 = double.Parse(str, NumberStyles.AllowDecimalPoint, ru); Console.WriteLine("'{0}' = '{1}' ({2})", str, v2, ru.Name);

if (int.TryParse(str, NumberStyles.AllowThousands, ru, out v1))

{

Console.WriteLine("'{0}' = '{1}'", str, v1);

}

else

{

Console.WriteLine("'{0}': не удалось преобразовать в тип int

({1})", str, ru.Name);

}

Вывод на консоль:

161

'0xA' = '10'

'-45 ' = '-45'

'(37) ' = '-37'

'123,456' = '123456' (en-US) '123,456' = '123,456' (ru-RU)

'123,456': не удалось преобразовать в тип int (ru-RU)

3.2.3.2. Разбор строк со значениями bool и char

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

static <тип> Parse(string value);

static bool TryParse(string value, out <тип> result);

Для логического типа разбор будет успешен, если строка содержит значение Boolean.FalseString или Boolean.TrueString (регистр символов не важен). Для символьного типа – если строка содержит один символ Unicode.

Пример:

bool v3; char v4;

str = "true";

v3 = bool.Parse(str); Console.WriteLine("'{0}' = '{1}'", str, v3); str = "истина";

if (bool.TryParse(str, out v3))

{

Console.WriteLine("'{0}' = '{1}'", str, v3);

}

else

{

Console.WriteLine("'{0}': не удалось преобразовать в тип bool",

str);

}

str = "Ё";

v4 = char.Parse(str); Console.WriteLine("'{0}' = '{1}'", str, v4); str = "!!!";

if (char.TryParse(str, out v4))

{

Console.WriteLine("'{0}' = '{1}'", str, v4);

}

else

{

Console.WriteLine("'{0}': не удалось преобразовать в тип char",

str);

}

Вывод на консоль:

'true' = 'True'

'истина': не удалось преобразовать в тип bool

162

'Ё' = 'Ё'

'!!!': не удалось преобразовать в тип char

3.2.3.3.Разбор строк со значениями перечисляемого типа

Вклассе System.Enum есть два варианта метода Parse:

static object Parse(Type enumType, string value);

static object Parse(Type enumType, string value, bool ignoreCase);

Метод TryParse не предусмотрен. Параметр ignoreCase позволяет игнорировать регистр символов. Если искомая символическая константа в указанном перечислении не найдена, генерируется исключительная ситуация

System.ArgumentException.

Пример:

DayOfWeek v5;

Console.WriteLine("Разбор перечисляемого типа"); str = "Friday";

v5 = (DayOfWeek)Enum.Parse(typeof(DayOfWeek), str); Console.WriteLine("'{0}' = '{1}'", str, v5);

str = "MonDAY";

v5 = (DayOfWeek)Enum.Parse(v5.GetType(), str, true); Console.WriteLine("'{0}' = '{1}'", str, v5);

str = "zzz";

try

{

v5 = (DayOfWeek)Enum.Parse(v5.GetType(), str, true); Console.WriteLine("'{0}' = '{1}'", str, v5);

}

catch (ArgumentException e)

{

Console.WriteLine(e);

}

Вывод на консоль:

'Friday' = 'Friday' 'MonDAY' = 'Monday'

System.ArgumentException: Запрошенное значение "zzz" не найдено

3.2.3.4. Разбор строк с датой и временем

Для разбора даты и времени предусмотрены следующие методы:

static DateTime Parse(string s);

static DateTime Parse(string s, IFormatProvider provider);

static DateTime Parse(string s, IFormatProvider provider, DateTimeStyles styles);

static DateTime ParseExact(string s, string format, IFormatProvider provider);

static DateTime ParseExact(string s, string format, IFormatProvider

163

provider, DateTimeStyles style);

static DateTime ParseExact(string s, string[] formats, IFormatProvider provider, DateTimeStyles style);

static bool TryParse(string s, out DateTime result);

static bool TryParse(string s, IFormatProvider provider, DateTimeStyles styles, out DateTime result);

static bool TryParseExact(string s, string format, IFormatProvider provider, DateTimeStyles style, out DateTime result);

static bool TryParseExact(string s, string[] formats, IFormatProvider provider, DateTimeStyles style, out DateTime result);

Методы Parse пытаются преобразовать строку к значению даты и времени, основываясь на указанной реализации интерфейса IFormatProvider и дополнительных опций, задаваемых перечислением DateTimeStyles (табл. 3.15).

 

Табл. 3.15 – Константы перечисления DateTimeStyles

 

 

 

Константа

 

Описание

 

 

 

None (0x0000)

 

Используются параметры форматирования по

 

 

умолчанию

 

 

 

AllowLeadingWhite

 

Начальные знаки-разделители не следует учиты-

(0x0001)

 

вать при разборе

 

 

 

 

 

AllowTrailingWhite

 

Конечные знаки-разделители не следует учиты-

(0x0002)

 

вать при разборе

 

 

 

 

 

AllowInnerWhite

 

Лишние знаки-разделители в середине строки не

(0x0004)

 

следует учитывать при разборе

 

 

 

 

 

AllowWhiteSpaces

 

Лишние знаки-разделители в любом месте строки

(0x0007)

 

не следует учитывать при разборе (комбинация

 

 

 

 

AllowLeadingWhite, AllowTrailingWhite и Allow-

 

 

InnerWhite)

 

 

 

NoCurrentDateDefault

 

Если в разбираемой строке содержится только

(0x0008)

 

время и отсутствует дата, подразумевается дата

 

 

 

 

1.1.1. Если это значение не используется, подра-

 

 

зумевается текущая дата

 

 

 

AdjustToUniversal

 

Дата и время возвращаются в формате универ-

(0x0010)

 

сального времени (UTC)

 

 

 

 

 

AssumeLocal (0x0020)

 

Если часовой пояс не указан в строке разбора,

 

 

подразумевается, что используется локальное

 

 

время

 

 

 

AssumeUniversal

 

Если часовой пояс не указан в строке разбора,

 

 

 

 

164

(0x0040)

подразумевается, что используется формат UTC

 

 

RoundtripKind

Поле даты DateTimeKind сохраняется при преоб-

(0x0080)

разовании в строку с помощью стандартного

 

 

описателя формата «o» или «r» и преобразования

 

строки обратно

 

 

Методы ParseExact делают то же самое, но требуют точного совпадения строки даты и времени с указанным форматом или массивом форматов.

Методы TryParse и TryParseExact отличаются от Parse и ParseExact тем же – при ошибке преобразования не выдают исключительную ситуацию, а возвращают false.

Пример:

DateTime v6;

Console.WriteLine("Разбор даты и времени:"); str = " Friday, August 20, 2010 18:30 ";

v6 = DateTime.Parse(str); Console.WriteLine("'{0}' = '{1}'", str, v6);

try

{

v6 = DateTime.ParseExact(str, "D", us); Console.WriteLine("'{0}' = '{1}'", str, v6);

}

catch (FormatException)

{

Console.WriteLine("'{0}' не является датой в формате '{1}'", str, us.DateTimeFormat.LongDatePattern);

}

str = " Friday, August 20, 2010 ";

v6 = DateTime.ParseExact(str, "D", us, DateTimeStyles.AllowWhiteSpaces); Console.WriteLine("'{0}' = '{1}'", str, v6);

Вывод на консоль:

'Friday, August 20, 2010 18:30 ' = '20.08.2010 18:30:00'

'Friday, August 20, 2010 18:30 ' не является датой в формате 'dddd, MMMM dd, yyyy'

'Friday, August 20, 2010 ' = '20.08.2010 0:00:00'

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

165

3.2.4. Ввод с консоли

Для чтения данных с консоли в классе System.Console предназначены следующие методы:

static int Read();

static string ReadLine();

static ConsoleKeyInfo ReadKey();

static ConsoleKeyInfo ReadKey(bool intercept);

Пример: Samples\3.2\3_2_4_read.

3.2.4.1. Метод Read

Метод Read читает один символ из потока ввода. Он возвращает значение типа int, равное коду прочитанного символа, либо –1, если в буфере ввода нет символов. Может показаться, что этот метод похож на функцию getch из консольной библиотеки языка C++ (conio.h). Однако, это не так. Когда выполнение программы доходит до вызова метода Read, пользователь может ввести не один символ, а сразу целую строку, завершив ее ввод нажатием клавиши «Enter». Метод Read вернет первый символ введенной строки, следующий вызов данного метода вернет второй символ, и т.д.

Что интересно, в режиме чтения действуют некоторые функции командной строки Windows. Так, нажатие клавиш «↑» и «↓» будет помещать в позицию ввода строки, расположенные в истории ввода ранее или позже, и т.д.

Чтобы метод Read вернул –1, необходимо на консоли ввести символ окончания ввода (комбинация клавиш Ctrl+Z или F6, затем Enter).

Приведем пример программы:

int i; string str; char c;

Console.WriteLine("Вводите любые строки текста.");

Console.WriteLine("Можно использовать клавиши 'Вверх'");

Console.WriteLine("и 'Вниз' для перемещения по истории");

Console.WriteLine("ввода. Для выхода из режима ввода");

Console.WriteLine("нажмите Ctrl+Z или F6, затем Enter");

do

{

i = Console.Read();

if (i != -1)

{

166

c = Convert.ToChar(i);

Console.Write("Символ с кодом U+{0:X4}", i);

if (Char.IsControl(c)) Console.WriteLine(" [управляющий]"); else Console.WriteLine(" = '{1}'", i, c);

}

} while (i != -1);

Результаты работы программы:

привет!

Символ с кодом U+043F = 'п' Символ с кодом U+0440 = 'р' Символ с кодом U+0438 = 'и' Символ с кодом U+0432 = 'в' Символ с кодом U+0435 = 'е' Символ с кодом U+0442 = 'т' Символ с кодом U+0021 = '!'

Символ с кодом U+000D [управляющий] Символ с кодом U+000A [управляющий]

^Z

В данном примере сначала была введена строка «привет!». В буфер клавиатуры попали символы этой строки, а также символы «\r» (0x0d) и «\n» (0x0a), которыми завершился ее ввод. Затем информация об этих символах была выведена на консоль. При следующем запросе на ввод строки была нажата комбинация клавиш Ctrl+Z и Enter, завершившая ввод.

3.2.4.2. Метод ReadLine

Метод ReadLine читает из потока ввода строку текста, которая завершается символом перевода строки и/или возврата каретки («\r» и/или «\n»). Метод возвращает объект типа string или null, если ввод осуществить не удалось (т.е. если в буфере клавиатуры или другого потока ввода был символ окончания ввода):

Console.WriteLine("Вводите любые строки текста.");

Console.WriteLine("Для выхода из режима ввода нажмите");

Console.WriteLine("Ctrl+Z или F6, затем Enter");

do

{

str = Console.ReadLine(); if (str != null)

{

Console.WriteLine("Введена строка '{0}'", str);

}

} while (str != null);

Результаты работы программы:

привет!

Введена строка 'привет!'

^Z

167

После считывания строки со значениями можно осуществлять ее разбор различными модификациями метода Parse.

3.2.4.3. Метод ReadKey

Метод ReadKey, как и метод Read, позволяет прочитать из буфера клавиатуры или потока ввода один символ, но работает уже как аналог функции getch. Т.е. можно считывать не только обычные символы, но и сочетания клавиш.

Метод имеет две разновидности. Вторая позволяет управлять отображением введенного символа (если параметр intercept равен true, символ не отображается, иначе отображается на консоли). Первый вариант метода всегда отображает введенный символ.

Информация о нажатых клавишах возвращается в виде экземпляров структуры ConsoleKeyInfo (табл. 3.16).

Табл. 3.16 – Основные члены структуры ConsoleKeyInfo

Член

 

Описание

 

 

Конструкторы

 

 

 

ConsoleKeyInfo(char keyChar,

 

Инициализирует новый экземпляр

ConsoleKey key, bool shift,

 

структуры ConsoleKeyInfo с использо-

bool alt, bool control)

 

 

ванием заданного символа, клавиши

 

 

 

 

консоли и управляющих клавиш

 

 

Операторы

 

 

 

static bool operator ==

 

Указывает, равны ли заданные объекты

(ConsoleKeyInfo a,

 

 

ConsoleKeyInfo b)

 

 

 

 

 

static bool operator !=

 

Указывает, являются ли заданные объ-

(ConsoleKeyInfo a,

 

екты неравными

 

 

ConsoleKeyInfo b)

 

 

 

 

 

 

Свойства

 

 

 

ConsoleKey Key

 

Возвращает клавишу консоли, пред-

 

 

ставленную текущим объектом

 

 

 

char KeyChar

 

Возвращает символ Unicode, представ-

 

 

ленный текущим объектом

 

 

 

ConsoleModifiers Modifiers

 

Возвращает состояние управляющих

 

 

клавиши (Shift, Alt или Ctrl) – нажаты

 

 

 

 

168

они или нет

Перечисление ConsoleModifiers содержит именованные константы Alt, Shift и Control. Левые и правые управляющие клавиши не различаются. Свойство KeyChar позволяет получить доступ к коду нажатой клавиши, если это обычный символ. Свойство Key – если была нажата любая клавиша клавиатуры. Перечисление ConsoleKey содержит именованные константы для каждой клавиши. Их несколько десятков, полный список можно посмотреть в библиотеке MSDN.

Как мы помним, в библиотеках языка C++ также была функция kbhit(), позволяющая узнать, есть ли во входном потоке данные о нажатых клавишах. В языке C# ее аналогом является следующее свойство класса Console:

static bool KeyAvailable;

Пример:

Console.WriteLine("Нажимайте любые комбинации клавиш,");

Console.WriteLine("чтобы увидеть их интерпретацию.);

Console.WriteLine("Выход по Ctrl+Пробел");

ConsoleKeyInfo exit = new ConsoleKeyInfo(' ', ConsoleKey.Spacebar, false, false, true);

ConsoleKeyInfo key;

do

{

key = Console.ReadKey(true);

Console.Write("Вы нажали ");

if (((int)key.Modifiers & (int)ConsoleModifiers.Alt) != 0) Console.Write("Alt+");

if (((int)key.Modifiers & (int)ConsoleModifiers.Shift) != 0) Console.Write("Shift+");

if (((int)key.Modifiers & (int) ConsoleModifiers.Control) != 0) Console.Write("Ctrl+");

Console.WriteLine(Enum.GetName(typeof(ConsoleKey), key.Key)); } while (key != exit);

Результаты работы программы:

Вы нажали Shift+Ctrl+F

Вы нажали Alt+F5 Вы нажали Shift+Z Вы нажали R

Вы нажали Shift+Ctrl+Insert Вы нажали Ctrl+Spacebar

Результаты работы зависят от того, какие клавиши будут нажаты.

169

§3.3. Вычисление выражений

Вданном параграфе мы рассмотрим вычисление выражений – это одна из трех основ структурного программирования. Две другие – организация в программе ветвлений и циклов, рассмотрены в следующем параграфе. Вычисление выражений состоит в применении операций языка по отношению к данным (аргументам операций).

При вычислении выражений используются операторы выражений. Также существуют операторы языка C#, рассмотренные в § 3.4. В дальнейшем мы как операторы выражений, так и операторы языка будем называть просто операторами. О том, какие именно операторы имеются в виду, будет ясно из контекста.

Итак, оператор выражения – это символ, указывающий, какую операцию необходимо выполнить над одним или несколькими аргументами. При выполнении оператора получается результат. Синтаксис применения операторов несколько отличен от вызова методов, поэтому необходимо знать формат выражений, содержащих операторы языка C#. Как и в большинстве других языков, семантика операторов в C# соответствует правилам и нотациям, знакомым нам из математики и из языка C++.

3.3.1.Набор операторов языка C#

Стандартные операторы, определенные в языке C#, перечислены в табл. 3.17.

 

Табл. 3.17 – Операторы языка C# (по категориям)

 

 

 

Категория

 

Операторы

 

 

 

Арифметические

 

+ – * / %

 

 

 

Инкремента и декремента

 

++ ––

 

 

 

Логические

 

&& || ! true false

 

 

 

Побитовые

 

& | ^ ~ << >>

 

 

 

Сравнения

 

== != < > <= >=

 

 

 

Присваивания

 

= *= /= %= += –= <<= >>= &= ^= |=

 

 

 

Доступа

 

. ::

 

 

 

Индексирования

 

[]

 

 

 

Преобразования типа

 

() as

 

 

 

 

170