317.50K
Категория: ПрограммированиеПрограммирование

Структуры и перечисления

1.

Структуры и перечисления
Лекция №9

2.

Структуры
Это «облегченная» альтернатива класса.
Структура – это значимый тип данных, экземпляр
структуры размещается в стеке, а не в динамической
памяти. При выходе экземпляра структуры из области
видимости, он немедленно удаляется из памяти.
Синтаксис структуры:
[спецификаторы]
struct
<имя> [: интерфейсы]
{тело структуры}
Спецификаторы – public, internal, для вложенных структур
можно private.
Тело может содержать константы, поля, методы, свойства,
события, индексаторы, операции, конструкторы. Их
описание и использование аналогично соответствующим
элементам класса.

3.

Правила описания структур:
• Структуры не могут участвовать в иерархиях наследования,
но может реализовывать интерфейсы ( однако, структуры
наследуют класс object).
• В структуре нельзя определять конструктор без параметров.
Конструктор по умолчанию автоматически определяется для
всех структур, и его изменить нельзя.
• В структуре нельзя определять деструкторы.
• Структуры не могут быть абстрактными.
• Структура не может содержать абстрактные
виртуальные методы.
или
• Переопределяться со спецификатором override могут
только методы, унаследованные от класса object.

4.

• Нельзя задавать значения полей по умолчанию.
Например,
struct Student
{ public string fam;
public string dat_r;
public int stip;
public Student(string f, string dr,int st)
{ fam = f; dat_r = dr; stip = st; }
}

5.

Объект структуры можно создать с помощью операции new,
подобно любому объекту класса:
<имя структуры> <имя экземпляра> = new <имя структ.>( );
В этом случае будет вызван конструктор по умолчанию,
который инициализирует все поля нулями.
<имя структуры> <имя экземпляра> =
new <имя структ.>(<параметры> );
В этом случае будет вызван конструктор определенный в
структуре.
Например, Student St1 = new Student( );
Student St2 = new Student("Иванов","12.03.87",200);

6.

Можно объявить структуру, не используя new:
<имя структуры>
<имя экземпляра>;
В этом случае придется выполнить инициализацию вручную.
Например,
Student St3; St3.fam = "Петров";
При присваивании одной структуры другой создается копия
этого объекта.
Пример из Шилдта:

7.

struct MyStruct { public int x; }
public static void Main( ) {
MyStruct a;
MyStruct b;
a.x = 10;
b.x = 20;
Console .WriteLine ("a.x {0}, b.x {1} ", a.x, b.x);
a = b;
b.x = 30;
Console.WriteLine("a.x {0}, b.x {1}", a.x, b.x);}

8.

Результаты:
а .х 10, b.x 20
a .x 20, b.x 30
Если бы a и b были объектами класса , результат был бы
следующим:
a . x 10, b.x 20
a . x 30, b.x
30
Преимущества использования структур:
Структуры обрабатываются напрямую, а не через ссылки.
Таким образом, структура не требует отдельной ссылочной
переменной. Т.е. при использовании структур расходуется
меньший объем памяти.

9.

Благодаря прямому доступу к структурам, при работе с ними
не снижается производительность, что имеет место при
доступе к объектам классов.
Итак, если нужно хранить небольшую группу связанных
данных, но не нужно обеспечивать наследование и
использовать другие достоинства ссылочных типов,
предпочтительно использовать структуру.
Особенно эффективным может быть использование массивов
структур вместо массивов классов. Ведь для массива из 100
экземпляров класса создается 101 объект, а для массива
структур – 1 объект.
Все значимые типы в C# являются структурами.

10.

В пространстве имен System определены такие структуры:
Boolean
DateTime
Int64
UInt64
Byte
Decimal
Char
Double
Int32
TimeSpan
UInt32
Intl6
Single
UIntl6
и др.

11.

Структура DateTime
Определена в пространстве имен System. Используется
для представления даты и времени.
Конструктор перегружен 12 раз, поэтому существует несколько
способов создания экземпляра этой структуры.
DateTime <имя экземпляра> =
new DateTime(year, month, day);
Параметры должны иметь тип int.
Например,
DateTime myDateTime = new DateTime(2010, 2, 8);
При использовании неверных параметров, например 35 в качестве
номера
месяца,
генерируется
исключение
ArgumentOutOfRangeException с сообщением:
Year, Month, and Day parameters describe an un-representable
DateTime.

12.

DateTime <имя экземпляра> =
new DateTime(year, month, day, hour, minute, second);
Параметры должны иметь тип int.
Например,
DateTime myDateTime = new DateTime(2010, 2, 8,22,15,10);
DateTime <имя экземпляра> = new DateTime(year, month,
day, hour, minute, second, millisecond);
DateTime <имя экземпляра> = new DateTime();
Создается объект, представляющий дату 01.01.0001 0:00:00

13.

DateTime <имя экземпляра> = new DateTime(ticks);
Параметр ticks имеет тип long и означает количество тиков (100наносекундных интервалов), прошедших с полуночи 01.01.0001.
Например, оператор
DateTime myDateTime2 = new DateTime(1000000000);
Создает экземпляр, представляющий объект
01.01.0001 0:01:40
К экземпляру структуры DateTime можно добавлять промежуток
времени (временной интервал) – объект класса TimeSpan.
При вычитании одной структуры DateTime из другой структуры
DateTime получается объект класса TimeSpan.

14.

Экземпляр
структуры
DateTime
можно
получить
преобразованием строки, содержащей дату и время, используя
статический метод Parse(str) структуры DateTime или метод
Convert.ToDateTime(str).
Например,
DateTime myDateTime2 = DateTime.Parse("02.10.2010");
DateTime myDateTime3 = Convert.ToDateTime("29/12/2009 23:10:30");
Метод Parse перегружен 3 раза. Другие его версии позволяют
задавать форматы, характерные для разных культур.

15.

Свойства структуры DateTime
Статическое свойство Now (тип DateTime)
возвращает
текущую дату и время, установленные в компьютере.
Обращение к этому свойству:
DateTime.Now
Статическое свойство Today (тип DateTime) возвращает
текущую дату, время устанавливается равным 0:00:00.
Обращение к этому свойству:
DateTime.Today

16.

Day (тип int) возвращает число, соответствующее дню месяца.
Например,
DateTime myDateTime2 = DateTime.Parse("02.10.2010");
Console.WriteLine(myDateTime2.Day); Результат: 2
Свойство Date (тип DateTime) возвращает дату экземпляра
структуры, время устанавливается равным 0:00:00.
Например,
Console.WriteLine(myDateTime2.Date);
Результат: 02.10.2010 0:00:00

17.

DayOfWeek (тип DayOfWeek) возвращает день недели в
диапазоне от 0(воскресенье) до 6(суббота).
Например,
DateTime myDateTime2 = DateTime.Parse("10.02.2010");
Console.WriteLine(myDateTime2.DayOfWeek);
Результат: Wednesday
DayOfYear (тип int) возвращает номер дня в году (1-366).
Например,
Console.WriteLine(myDateTime2.DayOfYear);
Результат: 41

18.

Year (тип int) возвращает год
Hour (int) – часы (диапазон от 0 до 23)
Minute (int) – минуты (диапазон от 0 до 59)
Month (int) – номер месяца (диапазон от 1 до 12)
Second (int) – секунды (диапазон от 0 до 59)
TimeOfDay (тип TimeSpan)
прошедшее от полуночи.
возвращает
время
суток,

19.

Сравнение экземпляров структуры DateTime
Статический метод Compare(datetime1,datetime2) возвращает
1 , если datetime1 больше datetime2
0 , если datetime1 равно datetime2,
-1, если datetime1 меньше datetime2 .
Например,
DateTime myDateTime1 = DateTime.Parse("10.02.2010");
DateTime myDateTime2 = DateTime.Parse("05.02.2010");
Console.WriteLine(DateTime.Compare(myDateTime1,myDateTime2));
Результат: 1

20.

Для сравнения можно использовать операции сравнения:
<,>,<=,>=,==,!=.
Например,
DateTime
godenDo = DateTime.Parse("05.02.2010");
if (DateTime.Now > godenDo)
Console.WriteLine("Срок годности истек");
else
Console.WriteLine("Продукт годен к употреблению");
Статический метод Equals(datetime1,datetime2) возвращает
true, если даты равны, и false, если нет.
Есть также нестатическая версия этого метода с одним
параметром.

21.

Проверка года на високосность
Для проверки, является ли заданный год високосным, можно
использовать статический метод структуры DateTime
IsLeapYear(year)
Этот метод возвращает логическое значение .
Например,
if (DateTime.IsLeapYear(DateTime.Now.Year))
Console.WriteLine("Этот год високосный");
else
Console.WriteLine("Этот год не високосный");

22.

Добавление к экземплярам структуры DateTime и вычитание
из них промежутков времени.
Метод Add(timeSpan1) возвращает новый экземпляр DateTime,
у которого дата и время на временной интервал timeSpan1
больше чем у вызывающего этот метод экземпляра.
В качестве аргумента в метод передается объект класса
TimeSpan.
Например,
DateTime myDateTime6 = DateTime.Parse("05.02.2010");
TimeSpan tm1 = new TimeSpan(1, 5, 30, 0);
Console.WriteLine(myDateTime6.Add(tm1));
Результат: 06.02.2010 5:30:00

23.

Аналогично метод Subtract(timeSpan1) используется для
вычитания временного интервала из экземпляра структуры
DiteTime.
Промежутки времени можно добавлять и вычитать при помощи
перегруженных в структуре DateTime операций сложения и
вычитания.
Например,
DateTime myDateTime6 = DateTime.Parse("10.02.2010");
TimeSpan tm1 = TimeSpan.FromDays(5);
DateTime newDate = myDateTime6 + tm1;
Console.WriteLine(newDate);
Результат: 15.02.2010 0:00:00

24.

Можно также добавлять различные интервалы времени,
используя методы
AddMonth(i), AddYears(i),
AddMinutes(d).
AddDays(d),
AddHours(d),
Здесь i – число типа int, означающее число месяцев или лет.
d – число типа Double, означающее интервал времени в днях,
часах и минутах соответственно.
Все эти методы возвращают экземпляр структуры DateTime.
Например,
DateTime myDateTime6 = DateTime.Parse("10.02.2010");
DateTime newDate = myDateTime6.AddYears(1);
Console.WriteLine(newDate);
Результат: 10.02.2011 0:00:00

25.

Определение промежутка времени между датами
Чтобы определить временной интервал между датами, нужно
из одного экземпляра DateTime вычесть другой.
Результат будет иметь тип TimeSpan.
Например,
DateTime date1 = Convert.ToDateTime("15/02/2010 23:10:30");
DateTime date2 = Convert.ToDateTime("10/02/2010 13:10:00");
TimeSpan ts = date1 - date2;
Console.WriteLine(ts);
Результат: 5.10:00:30

26.

ts.Days - количество дней в промежутке времени ts. Тип int
Для примера равно 5.
ts.Hours - количество часов в промежутке времени ts.
Для примера равно 10.
ts.TotalHours - общее количество часов в промежутке
времени ts. Тип double.
Для примера равно 130,008333333333.
ts.TotalDays
Тип double.
- количество дней в промежутке времени ts.
DateTime dt = Convert.ToDateTime("13.02.2011");
DateTime dt1 = Convert.ToDateTime("10.02.2011 5:30:00");
TimeSpan t = dt - dt1;
Console.WriteLine(t.TotalDays);
Результат:
2,77083333333333

27.

Перечисления
Перечисление (enumeration) — это множество именованных
целочисленных констант.
Синтаксис перечисления:
[спецификаторы]
enum
<имя> [: базовый тип]
{тело перечисления}
Допускаются спецификаторы new, public, protected, internal,
private.
Базовый тип – это тип элементов, из которых построено
перечисление. По умолчанию int.

28.

Тело перечисления состоит из имен констант, которым может
быть присвоено значение, разделенных запятыми.
Если значение не указано, оно вычисляется прибавлением
единицы к предыдущей константе.
По умолчанию константам присваиваются последовательные
значения начиная с нуля.
Например,
public enum god {Январь, Февраль, Март, Апрель, Май, Июнь,
Июль, Август, Сентябрь, Октябрь, Ноябрь, Декабрь }
Описывать перечисление можно как в пространстве имен, так
и внутри класса или структуры.

29.

Например, дополним структуру студент:
double[ ] x; // поле с оценками за сессию
public enum Экзамен
{ Информатика, Математика, Физика, История};
public double this[Экзамен i]
{ get { return x[(int) i]; }
set { x[(int) i] = value; } }
Тогда допустимы следующие операторы:

30.

Student St2 = new Student("Иванов","12.03.87",200);
St2[Student.Экзамен.Математика] = 9;
St2[Student.Экзамен.Физика] = 10;
Console.WriteLine(Student.Экзамен.Физика + "....." +
St2[Student.Экзамен.Физика]);
При использовании переменных перечисляемого типа в
целочисленных операциях и выражениях требуется явное
преобразование типа.

31.

С переменными перечисляемого типа можно выполнять
арифметические
операции,
логические
поразрядные
операции, сравнивать их с помощью операций отношения.
Например,
for (god g = god.Март; g < god.Сентябрь; g++)
Console.WriteLine(g);
Результат:
Март
Апрель
Май
Июнь
Июль
Август

32.

Все перечисления являются потомками базового класса
System.Enum.
Приведем описание некоторых методов этого класса:
Статический метод
GetName(Type t, object v )
возвращает строку - имя константы по ее значению (t – тип
перечисления, v- значение).
Например,
Enum.GetName(typeof(god), 5)
Результат: Июнь

33.

Статический метод
GetNames(Type t)
возвращает строковый массив
составляющих перечисление.
из
имен
констант,
Например, пусть имеется перечисление
public enum KodTovara
{ Стол =104, Стул=203, Шкаф, Диван=378 };
Тогда результатом оператора
string[ ] nt = Enum.GetNames(typeof(KodTovara));
будет массив строк nt из четырех элементов:
Стол
Стул
Шкаф
Диван

34.

Статический метод
GetValues(Type t)
возвращает массив значений констант,
перечисление. Результат имеет тип Array.
составляющих
Например, выполнение оператора
Array kt = Enum.GetValues(typeof(KodTovara));
или оператора
int[ ] kt =(int[ ]) Enum.GetValues(typeof(KodTovara));
приведет к формированию массива kt из четырех элементов:
104
203
204
378
В первом операторе формируется массив с типом элементов
KodTovara.

35.

Статический метод
IsDefined(Type t, object v )
возвращает значение true, если параметр v содержит
значение константы, входящей в перечисление,
или
• символическое имя константы, входящей в перечисление
и false в противном случае.
Например,
Enum.IsDefined(typeof(KodTovara),"Стол")
Enum.IsDefined(typeof(KodTovara),104)
Enum.IsDefined(typeof(KodTovara),"Трюмо")
true
true
false

36.

Статический метод
Enum.Parse(Type t, string s)
конвертирует строку, представляющую имя константы из
перечисления типа t или значение константы, в
соответствующий объект перечисления.
Например,
KodTovara tovar =
(KodTovara) Enum.Parse(typeof(KodTovara), "104");
Console.WriteLine(tovar);
или
KodTovara
tovar=
(KodTovara) Enum.Parse(typeof(KodTovara), "Стол");

37.

Можно так:
KodTovara
tovar1 = (KodTovara) 104;
Переменной перечисляемого типа можно присвоить не только
одно из значений из перечисления, а любое значение, представимое
с помощью базового типа.
Например,
KodTovara
tovar1 = (KodTovara) 100;
Оператор
Console.WriteLine(Enum.IsDefined(typeof(KodTovara),tovar1));
выведет false
а оператор
Console.WriteLine(Enum.GetName(typeof(KodTovara), 100));
выведет пустую строку.

38.

В пространстве имен System определены
перечисления ConsoleColor и ConsoleKey.
стандартные
ConsoleColor
содержит константы, определяющие цвет
выводимых символов и цвет фона.
Например, ConsoleColor.Gray .
Используется для установки цвета фона:
Console.BackgroundColor = ConsoleColor.Red;
или цвета выводимых символов:
Console.ForegroundColor = ConsoleColor.White;

39.

Перечисление ConsoleKey содержит
определения стандартных клавиш.
Например:
константы
для
ConsoleKey.Enter, ConsoleKey.PageUp
Используется для определения, какая была нажата клавиша.
Метод
Console.ReadKey( ) возвращает результат типа
ConsoleKeyInfo. Это структура, содержащая информацию о
нажатой клавише.
Свойство Key этой структуры имеет тип ConsoleKey
содержит константу, определяющую нажатую клавишу.
и
Следующий пример показывает, как можно проанализировать,
была ли нажата клавиша Номе.

40.

ConsoleKeyInfo k = Console.ReadKey( );
if (k.Key = = ConsoleKey.Home)
Console.WriteLine(" Нажата клавиша Home ");
else
Console.WriteLine(" Нажата другая клавиша ");
Свойство
KeyChar
возвращает Unicode-символ,
представляющий текущий объект типа ConsoleKeyInfo.
ConsoleKeyInfo
k1 = Console.ReadKey(true);
if (k1.KeyChar == 'A')
Console.WriteLine("нажата клавиша с буквой А");

41.

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

42.

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

43.

Факультет: ЭФ
Фамилия

1
Иванов
Средний
балл
9
2
Петров
5
Возраст
18
15
Факультет: ФАИС
Фамилия

1
2
Сидоров
Ребров
Средний
балл
6.5
5
Возраст
19
20

44.

Если информации по какому-то факультету нет,
в файл
записывается заголовок с факультетом и вместо таблицы фраза
«данных нет».
Информация в каждой таблице должна быть отсортирована по
возрастанию возраста.
Добавляем в программу инструкцию using System.IO;
public enum Facultet
{ ГЭФ, ЭФ, ФАИС, МТФ, МСФ };

45.

struct Student : IComparable
{
public string
fam;
public Facultet fcltt;
public string
dat_r;
public double
sr_ball;
public double vozrast
{ get
{ return (DateTime.Now.Year - Convert.ToDateTime(dat_r).Year);}
}

46.

public int CompareTo(Object obj)
{ Student st = ( Student) obj ;
if (vozrast > st.vozrast) return 1;
else { if (vozrast < st.vozrast) return -1; else return 0; }
}
}
class Program
{
static void Main(string[ ] args)
{

47.

StreamReader f = new StreamReader("baza.dat");
string s = f.ReadLine( ); int j = 0;
while (s != null)
{
s = f.ReadLine( );
j++;
}
f.Close( );
Student[ ]
students = new Student[j];

48.

string[ ] dano=new string[4];
f = new StreamReader("baza.dat");
s = f.ReadLine( ); j = 0;
while (s != null)
{
dano = s.Split(';');
students[j].fam=dano[0];
students[j].fcltt =(Facultet) Enum.Parse(typeof(Facultet), dano[1]);

49.

students[j].dat_r = dano[2];
students[j].sr_ball = Convert.ToDouble(dano[3]);
s = f.ReadLine( );
j++;
}
f.Close( );
string[ ]
F = Enum.GetNames(typeof(Facultet));
int v = -1, p=0;
Console.Title = "Студенты";
Console.Clear( );

50.

for (int i = 0; i < F.Length; i++) Console.WriteLine(F[i]);
bool
ff = true;
while (ff)
{Console.ForegroundColor = ConsoleColor.Gray;
if ( !(v == 0 && p == 0))
{
Console.SetCursorPosition(0, p);
Console.WriteLine(F[p]);
}

51.

Console.SetCursorPosition(0, F.Length);
ConsoleKeyInfo k = Console.ReadKey();
if (v = = -1) p = 0; else
p = v;
if (k.Key = = ConsoleKey.Enter) ff = false;
else
{if (Char.GetNumericValue(k.KeyChar) >= 0 &&
Char.GetNumericValue(k.KeyChar) < F.Length)
{
v = Convert.ToInt32(Char.GetNumericValue(k.KeyChar));

52.

Console.SetCursorPosition(0, v);
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine(F[v]);
}
else v = -1;
}
}
if (v != -1)
{
Console.Clear();
Console.WriteLine(" Факультет: " + F[v]);

53.

// шапка таблицы…..
j=0;
for (int i = 0; i < students.Length; i++)
{
if (Enum.GetName(typeof(Facultet), students[i].fcltt) == F[v])
{ j++;
Console.WriteLine("║{0,2} ║ {1,15} ║ {2,15} ║ {3,11} ║",
j, students[i].fam, students[i].dat_r, students[i].sr_ball);
}
}
}

54.

else
Console.WriteLine(" Факультет не выбран ");
Array.Sort(students);
Console.ReadKey( );
StreamWriter
f1 = new
StreamWriter("baza1.txt");
for (int ii = 0; ii < F.Length; ii++)
{
f1.WriteLine(" Факультет: " + F[ii]);
int q = 0;

55.

for (int i = 0; i < students.Length; i++)
{
if (students[i].fcltt.ToString( ) = = F[ii])
{
if (q = = 0)
{// шапка таблицы…..
}
q++;
f1.WriteLine("║{0,2} ║ {1,15} ║ {2,15} ║ {3,11} ║",
q, students[i].fam, students[i].sr_ball, students[i].vozrast);
}
}

56.

if (q = = 0)
f1.WriteLine("данных нет.");
f1.Close( );
}
}

57.

Вертикальное световое меню:
string[] menu ={ "Вывод
",
"Поиск в хеш-таблице
",
"Поиск по бинарному дереву",
"Выход
bool vv = true;
int vybor = 0, pvyb = 0;
"};

58.

while (vv)
{
Console.BackgroundColor = ConsoleColor.Black;
Console.Clear();
Console.BackgroundColor = ConsoleColor.Black;
Console.ForegroundColor = ConsoleColor.White;
Console.CursorVisible = false;
for (int i = 0; i < menu.Length; i++)
{ Console.SetCursorPosition(25, 8 + i);
Console.Write(menu[i]);
}

59.

bool ff = true;
while (ff)
{ Console.BackgroundColor = ConsoleColor.Black;
Console.ForegroundColor = ConsoleColor.White;
Console.SetCursorPosition(25, 8 + pvyb);
Console.Write(menu[pvyb]);
Console.BackgroundColor = ConsoleColor.Red;
Console.ForegroundColor = ConsoleColor.White;
Console.SetCursorPosition(25, 8 + vybor);
Console.Write(menu[vybor]);

60.

ConsoleKeyInfo k = Console.ReadKey(true);
switch (k.Key)
{
case ConsoleKey.Enter: { ff = false; break; }
case ConsoleKey.UpArrow:
{ pvyb = vybor; if (vybor != 0) vybor = vybor - 1; break; }
case ConsoleKey.DownArrow:
{ pvyb = vybor;
if (vybor != menu.Length - 1) vybor = vybor + 1; break;
}
}
if (k.Key == ConsoleKey.Enter) ff = false;
}

61.

Console.CursorVisible = true;
switch (vybor)
{
case 3: { vv = false; break; }
case 0: {}
case 1: {}
case 2: {}
}
} //while (vv)
English     Русский Правила