maran program engineering (830029), страница 21
Текст из файла (страница 21)
Заодно покажем использование в элементах списка динамических структур данных и стандартного интерфейса IComparable<elem>. Поправилам C# в нашем классе elem должна быть реализация функции intCompareTo(elemy). При этом эта функция должна обеспечить возвращение всех значений -1, 0 и 1.namespace ListClass{class elem : IComparable<elem>{ // элемент списка, структура и функции обслуживанияpublic string s;public double[] mas;int kol;public elem(int n){mas = new double[n];}public void inpt(){Console.Write("String ");s = Console.ReadLine();for (int i = 0; i < mas.Length; i++){Console.Write(i + " ");mas[i] = Double.Parse(Console.ReadLine());}}public void otpt(){Console.WriteLine(s);foreach (double x in mas)Console.WriteLine(x.ToString("F2"));}public int KolPol(){kol = 0;foreach (double x in mas)121if (x > 0) kol++;return kol;}}public int CompareTo(elem y){ // реализация унаследованной из интерфейса функцииif (this.KolPol() == y.KolPol()) return 0;if (this.KolPol() > y.KolPol()) return 1;else return -1;}class Program{static bool pred(elem x){return(x.KolPol() == 0);}static void Main(string[] args){List<elem> lst1;elem el;int m;lst1 = new List<elem>();// Создание спискаfor (int i = 0; i < 3; i++){Console.Write("Количествочиселвмассиве "+i+" ");m = Convert.ToInt32(Console.ReadLine());el = new elem(m); //должен всегда быть в циклеel.inpt();lst1.Add(el);}lst1.Sort();// сортировка элементов списка по заданному в// int CompareTo(elem y) критериюlst1.RemoveAll(pred);// удаление элементов по условиюfor (inti = 0; i<lst1.Count; i++){ // Обработка элементов в циклеel = lst1.ElementAt(i);if (el.s.Length > 5) lst1.RemoveAt(i);}122bool b1 = lst1.Exists(pred);// Проверка наличия элементов по условию// Обработка элементовforeach (elem z in lst1){z.otpt();Console.WriteLine("" + z.KolPol());}Console.ReadLine();}}}Обратим внимание еще раз на то обстоятельство, что список этого примера состоит из указателей на экземпляры класса.
Поэтому оператор выделенияпамяти el = new elem(m) должен быть в теле цикла (Почему?). Кроме того, неработают функции класса List, аргументами которых являются элементы списка(IndexOf, Remove, Contains …). Функции, аргументами которых являются индексы и/или оформленные функциями предикаты, работают без проблем.5.6.2. Работа со словарем — классом DictionaryКласс Dictionary состоит из пар «ключ — значение». Ключом может бытьлюбой простой тип данных, значение может иметь сложную структуру, в такомслучае должны быть предварительно созданы класс и/или структура.Словарь из простых данныхБудем работать с классом Dictionary, где ключ имеет тип string, а значение int.
По существу, это массив с символьными индексами, но возможностямиобработки списка.namespace DictInt{class Program{static void Main(string[] args){Dictionary<string, int> dic1 =new Dictionary<string, int>();// Объявление словаря://ключ имеет тип string, значение тип intstring s;int k;for (int i = 0; i < 5; i++)123{ // Создание словаряConsole.Write("Key "); s = Console.ReadLine();Console.Write("Value "); k = Convert.ToInt32(Console.ReadLine());try{dic1.Add(s, k);// Добавление элемента, повторение ключа//вызывает прерывание}catch{Console.WriteLine("Duplicate Key");i--;}}dic1["abc"] = 25;// Если такого ключа нет - добавит, если ключ уже//имеется - меняет соответствующее ему значениеdic1.Remove("xyz");// Элемент с заданным ключом удаляется, если такого// ключа нет - ничего не делается и сообщение не выдаетсяs="aaa";bool b1 = dic1.ContainsKey(s);bool b2 = dic1.ContainsValue(25);// Проверка наличия заданного ключа и/или значенияs = "bbb";try{// Поиск значения по ключу,//отсутствие ключа вызывает прерываниеk = dic1[s];Console.WriteLine("Key " + s + " Value " + k);}catch (KeyNotFoundException){Console.WriteLine("Key not find");}// Организация цикла по ключам, например,// для изменения значенийstring[] keys1 = new string[dic1.Count];dic1.Keys.CopyTo(keys1, 0);124for (int i = 0; i < keys1.Length; i++){dic1[keys1[i]] += 100;}// Цикл по ключам, не забудьте об особенностях foreach!foreach (KeyValuePair<string, int> x in dic1)Console.WriteLine(x.Key + " " + x.Value);Console.ReadLine();} }}С помощью класса Dictionary можно легко решить следующую классическую задачу: на ввод поступает последовательность слов.
Вывести списоквведенных слов с указанием того, сколько раз каждое из них встречалась. Таким же образом можно обрабатывать результаты социологического опроса: каждый опрашиваемый назвал 3 любимых животных (артистов, деревьев и т. д.).Вывести список названных животных с указанием количества полученных голосов.
При создании такой программы обработки надо решить вопрос о вводе ипроверке корректности данных, а это выходит за рамки данного пособия.SortedDictionary<string, int> dic2;dic2 = new SortedDictionary<string, int>();// В SortedDictionary словарь всегда упорядочен// по возрастанию ключейfor (int i = 0; i < 24; i++){Console.Write(" Input a name ");s = Console.ReadLine();if (dic2.ContainsKey(s)) dic2[s]++;else dic2[s] = 1;// Добавили очередной голос или получили первый голос}foreach (KeyValuePair<string, int> x in dic2)Console.WriteLine(x.Key + " " + x.Value);Словарь из данных со сложной структуройПусть ключ по-прежнему имеет тип string. В качестве данных используеммассив и в качестве примера обработки — функцию нахождения суммы.
Почтивсе остается без изменений, но обратите внимание на то, что выполнять какиелибо операции только со значением (value) невозможно, потому что оно имееттеперь внутреннюю структуру; необходимо всегда указывать имя функции, которая и будет выполнена на компонентах значения.125namespace DictClass{class elem{public double[] mas;public elem(int n){mas = new double[n];}public void inpt(){for (int i = 0; i < mas.Length; i++){Console.Write(i + " ");mas[i]=Double.Parse(Console.ReadLine());}}public void otpt(){Console.WriteLine("Output ");for (int i = 0; i < mas.Length; i++)Console.WriteLine(i + " " +mas[i].ToString("F2"));}public double sum(double c){double temp = 0;foreach (double x in mas)if (x > +c) temp += x;return temp;}}class Program{static void Main(string[] args){Dictionary<string, elem> dic1;dic1 = new Dictionary<string, elem>();elem el1;string kl;for (int i = 0; i < 5; i++){ // Создание словаря126}//Console.Write("Key ");kl = Console.ReadLine();el1 = new elem(i + 2);el1.inpt();dic1.Add(kl, el1); //повторение ключей недопустимо// Добавление элементаel1 = new elem(4);el1.inpt();dic1.Add("abc", el1);dic1["abc"] = el1; // Добавление или заменаtry{ // Поиск элемента по ключуel1 = dic1["xyz"];el1.otpt();}catch (KeyNotFoundException){Console.WriteLine("Not found");}//Использование функции на элементах словаряConsole.WriteLine("Summa");foreach (KeyValuePair<string, elem> w in dic1)Console.WriteLine(w.Key + " " +w.Value.sum(1.4));// Вывод словаряConsole.WriteLine("Dictionary");foreach (KeyValuePair<string, elem> u in dic1){Console.WriteLine("Key "+u.Key);u.Value.otpt();}Console.ReadLine();}}}5.6.3.
Список из списковВозможен и случай, когда список тоже состоит из списков. Рассмотрим вкачестве примера список, который, в свою очередь, состоит из списков из целых чисел.127namespace LstLst{class Program{static void Main(string[] args){List<List<int>> lst1=new List<List<int>>();// Список, элементами которого являются спискиList<int> temp;// Вспомогательный списокint k1, k2, k3;for (int i = 0; i < 3; i++){ // Пусть во внешнем списке будет 3 элементаConsole.Write("Elements in list "+i+" ");k1=Convert.ToInt32(Console.ReadLine());// k1 - количество элементов в i-м подспискеtemp = new List<int>();// Создаем вспомогательный списокfor (int j = 0; j < k1; j++){Console.Write("Enter a number for element " + i + " ");k2=Convert.ToInt32(Console.ReadLine());temp.Add(k2);}lst1.Add(temp);// Добавлеям вспомогательный список в основной// в качестве элемента}// Вывод (или обработка) всего спискаk3=0;foreach (List<int>x in lst1){ // Цикл по внешнему спискуConsole.WriteLine("Elements of List " + k3);k3++;foreach (int z in x)// Цикл по внутреннему спискуConsole.WriteLine("" + z);}Console.WriteLine();// Второй вариант цикла по спискуfor(int i=0; i<lst1.Count;i++)128{ // Цикл по внешнему спискуConsole.WriteLine("*************************");/* Этот цикл по внутреннему списку тоже работаетforeach (int y in lst1[i])Console.WriteLine(y);Второй вариант цикла по внутреннему списку*/temp = lst1[i];for (int j = 0; j < lst1[i].Count; j++)Console.WriteLine("" + temp[j]);}Console.ReadLine();} }}5.6.4.
Использование диалоговых окон для работысо стандартными классамиРассмотрим SDI-приложение, в котором выполняется создание и обработка класса List с использованием диалоговых окон. Создание SDI-приложений рассмотрено выше.Элементы списка имеют следующую структуру:public class elem{public string s;public int[] mas;public elem(string s,int[]mas){this.s = s;this.mas = new int[mas.Length];for (int i = 0; i < mas.Length; i++)this.mas[i] = mas[i];}public int sumpolr(int c){return mas.Where(q => q > c).Sum();}public int KolVo(){return mas.Where(p => p > 0).Count();} }129Пусть меню имеет следующую структуру:ФайлОбработкаПомощьВыходСоздание спискаО программеОбработка спискаИзменение спискаОкно «О программе» имеет традиционную структуру, и мы на нем останавливаться не будем.Создание спискаДля создания списка используется окно на рис.