Наследование.Модификатор доступа protected .
Поможем в ✍️ написании учебной работы
Поможем с курсовой, контрольной, дипломной, рефератом, отчетом по практике, научно-исследовательской и любой другой работой

На практике очень часто требуется обрабатывать несколько данных одно и того же типа. Конечно, можно каждое значение этих данных хранить в отдельной переменной, но тогда с каждой из них и работать надо будет персонально. Это неудобно. Удобнее использовать такую организацию данных, при которой все данные будут находиться под одним и тем же именем, а к каждому значению можно будет обратиться, используя индекс (или номер).Это и есть массив.

Формально, в программировании массив это заранее известное количество однотипных элементовобъединенных одним именем. Очень важно, что количество элементов должно быть заранее известно. Почему? До использования массива надо под него захватить оперативную память. Чтобы знать, сколько захватить памяти, надо знать из скольких элементов состоит массив и какого типа эти элементы.

Массивы использовались в программировании и до эпохи ООП. Поэтому для начала продемонстрируем некоторые стандартные задачи при работе с одномерными массивами на уровне блок-схем. К таким задачам относятся

- поиск максимального элемента и его индекса;

- создание массива из элементов другого массива, обладающих некоторыми свойствами;

- удаление элемента с указанным индексом;

- вставка элемента на указанное место по индексу;

-сортировка массива;

- перестановка элементов массива в обратном порядке.

Здесь блок-схемы этих задач с некоторыми комментариями.

 

Ну а теперь, как с массивами работают в C#.

Для того, чтобы использовать массив в программе, потребуется выполнить два шага, ведь массивы в C# реализованы как объекты. Во-первых, надо объявить переменную, которая будет обращаться к массиву. Во-вторых, надо создать экземпляр массива, используя оператор new. Для объявления одномерного массива это может выглядеть так:

тип[] имя_массива = new тип[размер];

Здесь типопределяет конкретный тип элемента массив. Квадратные скобки указывают на то, что объявляется одномерный массив, размер определяет количество элементов массива. Например, ниже создается массив, который состоит из 10 элементов типа doubleи этот массив связываетсяс переменной ссылочного типа v:

double [] v = newdouble [10];

В переменной v хранится ссылка на область памяти, выделенная для массива оператором new.

Шаги по инициализации массива могут быть разнесены в два отдельных оператора:

int[] v;

v = new int[10];

Массив в C# инициируется один раз, это приводит к тому, чтонельзя менять размерность массива по ходу выполнения программы.

Как уже говорилось, для доступа к элементу массива используется индекс. В C# индекс начального элемента всегда равен нулю. Вмассиве v к начальному элементу «добираются» так: v[0], а доступ к последнему элементу реализуется так:v [9].

Ниже приведен фрагмента метода с инициализацией одномерного массива из 10 элементов и заполнения его числами от 1 до 10.

int[] v = new int[10];

for (inti=0; i< 10; i++)

v[i] = i+1;

Одномерный массив это объект класса Array. В этом классе есть несколько полей и методов, речь о которых будет ниже. Нам(Вам) сейчас интереснополеэтого классаlength, в которомлежит значение длины массива, то есть количество элементов в массиве. Это значит, что длину уже инициированного массива всегда можно узнать (измерить) в ходе выполнения программы.

int[] v = new int[10];

for (inti=0; i<v.lenght; i++)

v[i] = i+1;

 

Есть возможность задавать значения элементов массива в процессе его инициализации:

тип[] имя_массива = { val 1, val 2, val 3, …, valN };

где val 1,…, valN – первоначальные значения элементов массива, которые присваиваются слева направо по порядку индексирования. Память под этот массив распределяется автоматически.

Предыдущий фрагмент метода может быть записан так:

int[] v = {1, 2, 3, 4, 5, 6, 7, 8, 9};

Пример 8.1.

 

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

Итак, задача. Задан одномерный массив A из действительных чисел, в котором N элементов. Вычислить среднее арифметическое элементов этого массива. Получить новый массив Bиз положительных элементов массива A.

Обсудим содержание класса, который Нам(Вам) придется организовать для решения всей задачи. Напомним, что пока класс организовывается так, чтобыв нём решается вся задача. Однако уже скоро, на примере этой задачи,будет продемонстрирована возможность использованияочень мощного средства ООП - наследования.

Итак, класс. Какие необходимы поля?: массив A надо хранить, массив Bнадо хранить, среднее арифметическое хранить надо. Размеры массивов будем мерить с использование length, поэтому полей для этих данных организовывать не будем.

Методы: формировать массив A надо?, вычислять среднее арифметическое массива A надо?, получать массив B надо?, выводить на форму массив надо?. Хорошо бы сделать так, чтобы с помощью метода вывода на форму можно было выводить,если нужно, массив A, или, если нужно, массив B.Поля сделаем естественно закрытыми, и постараемся использовать их без организации соответствующих открытых свойств.

Сначала обсудим метод формирования массива A. Здесь возможны варианты. Сформировать массив A можно так, как описано в примере 8.1. В чем недостаток такого формирования: для того, чтобы изменить длину массива или(и) его значения надо изменять исходный текст программы, что нежелательно. Сформировать массив Aможно, читая его значения из текстового редактора. Для этого удобно использовать оконный компонент TextBox с условием, что его свойство Multiline = True. Чем он хорош? Это многострочный редактор, значитможно создавать и редактировать его строки, а используя метод Splitиз арсенала работы со строками, удастся разделить текст из редактора в массив строк. После этогоэлементы этого массив строк уже можно конвертировать в элементы исходного массива A целых чисел. Это второй вариант формирования массива A. Ну и третий вариант – сформировать массива Aс помощью датчика случайных чисел.И еще, помните, раньше (лекция 6, пример с конструкторами) говорилось о перегрузки методов,смысл которой состоит в следующем: методы имеют одинаковые имена, но разные списки параметров. Реализуем перегрузку методов здесь для разных вариантов формирования массива A.

Обсудим метод вывода массива. Выводить массив будем в оконный компонент listBox. Выводить надо каждый массив в свой listBox. Получается, что у этого метода будет два параметра: массив и оконный компонент listBox. И еще, в этом методе используем оператор цикла foreach. О том, как он работает,поясним после примера 8.2.

Пока хватит. Напишем и отладим то, что уже обсудили. Потом добавим другие методы.

usingSystem;

using System.Collections.Generic;

using System.ComponentModel;

using System.Data;

using System.Drawing;

using System.Linq;

using System.Text;

using System.Windows.Forms;

 

namespace WindowsFormsApplication1

{

publicpartialclassForm1 : Form

{

public Form1()

   {

       InitializeComponent();

   }

 

Massiv ms = null;

 

privatevoid button1_Click(object sender, EventArgs e)

     {

if (ms==null)

             ms = newMassiv();

//формирование массива ms.mass в инициализации

ms.InPutMass();

         button4.Visible = true;

     }

 

privatevoid button2_Click(object sender, EventArgs e)

     {

if (ms == null)

            ms = newMassiv();

//чтение элементов массива ms.mass из строк редактора

ms.InPutMass(textBox2);

         button4.Visible = true;

     }

 

privatevoid button3_Click(object sender, EventArgs e)

     {

int n = Convert.ToInt32(textBox1.Text);

if (ms == null)

             ms = newMassiv();

//заполнение массива с использованием датчика случайных чисел

ms.InPutMass(n);

         button4.Visible = true;

     }

 

privatevoid button4_Click(object sender, EventArgs e)

{

//вывод закрытого массива mass через открытое свойство Mass

ms.OutPut(ms.Mass, listBox1);

}

}

 

publicclassMassiv

{

privateint[] mass;

publicint[] Mass // Свойство для описания массива !!!

{

get { return mass; }

set { mass = value; }

}

publicvoidInPutMass()

   {

//формирование массива при инициализации

mass = newint[] { 7, 6, 5, 4, 3, 2, 1 };

   }

publicvoid InPutMass(int n)

{

//формирование массива с использованием датчикаслуч. чисел

mass = newint[n];

//инициализация датчика сл.чисел

Random rnd = newRandom();

     rnd.NextDouble();

for (int i = 0; i <= mass.Length - 1; i++)

     {

         mass[i] = rnd.Next(0, 100) - 50;//выдаетсл.ч. вдиапазоне (-50,50)

     }

   }

 

publicvoid InPutMass(TextBox TB)

{

//преобразование строки TB.Text в массив строк используя разделитель ‘\r’ – признак конца строки

string[] s = TB.Text.Split('\r');

int len = s.Length;

// MessageBox.Show(Convert.ToString(len));

       mass = newint[len];

for (int i = 0; i < mass.Length; i++)

       {

           mass[i] = int.Parse(s[i]);

       }

   }

 

publicvoid OutPut(int[] a, ListBox lb)

   {

if (a != null)

       {

           lb.Items.Clear();

foreach (int x in a)

{

               lb.Items.Add(x);

           }

       }

   }

}

}

Пример 8.2

Обратите внимание на то, где описан объект ms. При таком объявлении эта переменная видна во всех обработчиках события, ведь, по сути, она стала полем класса Form1 (закрытым по умолчанию), а обработчики событий – это методы класса Form1, значит, в них видны закрытые поля класса.

И еще, в классе Massiv методы формирования массива используют закрытое поле mass. Это возможно, ведь и здесь все методы с именами Input ()являются методами класса, в котором описано закрытое поле mass. Однако, в обработчике button 4_ Click ()при вызове методаOutPut() доступ к закрытому полю напрямую невозможен (классы разные), поэтому Мы(Вы) вынуждены организоватьоткрытое свойство Mass, связанное с полем mass и использовать его при вызове метода OutPut().Чуть позже Мы(Вы) откажемся от этого открытого свойства Mass.

На рис.8.2а,б,в приведены результаты работы программы с тремя вариантами формирования массива A.

Рис.8.2.а

Рис.8.2.б

Рис.8.2.в.

Они отличаются не только значениями элементов массива, но и их количеством. На рис.8.2а количество элементов определяется количеством значений в скобках {…}при инициализации массива. На рис 8.2б размер массива определяется количеством строк в редакторе. На рис 8.2в длина массива считывается из однострочного редактора textBox1.

А теперь обещанное. Поясним работу оператора цикла foreach. Когда цикл начинается, выбирается начальный элемент массива и его значение присваивается переменной циклаx. На каждом последующем шаге выбирается следующий элемент массива, который сохраняется в этой переменной. Цикл завершается, когда все элементы массива окажутся выбранными. Следовательно, оператор foreach циклически опрашивает массив по отдельным его элементам от начала и до конца. Надопонимать или помнить, что переменная цикла служит только для чтения элементов массива. Это значит, что с использованием оператора цикла foreach невозможно изменять содержание массива.

Для решения поставленной задачи осталось добавить в Наш(Ваш) класс метод нахождения среднего арифметического и метод, формирующий массив Bиз положительных элементов массиваA. Кроме этого, в класс Massiv надо добавить поля для хранения результатов:

Вот фрагмент кода, который надо добавить к классу Massiv.

. . .

   publicdouble SrAr()

   {

double s=0;

foreach (int x in mass)

           s = s + x;

       s = s / mass.Length;

return s;

   }

 

privateint[] b;//поле с положительными элементами массива A

 

publicvoid FormMassB()

   {//заполняет поле-массив b из положительных элементов массива mass

int[] a = newint[mass.Length];//вспомогательный массив такой же длины как массив mass

int k = 0;//счетчикколичества

for(int i=0;i < mass.Length;i++)

if (mass[i] > 0)

           {

               a[k] = mass[i];

k++;

           }

       b = newint[k];//инициализация поля b длиной k

//заполнениеполяb

for (int i = 0; i < k; i++)

           b[i] = a[i];

   }

   . . .

Пример 8.3.

 

 

Ну а теперь об такой парадигме ООП как наследование.

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

Наследование является мощнейшим инструментом ООП и применяется для следующих взаимосвязанных целей:

· исключения из программы повторяющихся фрагментов кода;

· упрощения модификации программы;

· упрощения создания новых программ на основе существующих.

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

Наследование позволяет создавать иерархии объектов. Иерархия представляется в виде дерева, в котором более общие объекты располагаются ближе к корню, а более специализированные— на ветвях и листьях. Наследование облегчает использование библиотек объектов, поскольку программист может взять за основу объекты, разработанные кем-то другим, и создать наследников с требуемыми свойствами.

Объект, на основании которого строится новый объект, называется родительским объектом, объектом-предком, базовым классом, или суперклассом, а унаследованный от него объект— потомком, подклассом, или производным классом.

В ООП есть еще одна парадигма, которая позволяет писать гибкие, расширяемые и читабельные программы. Это полиморфизм. Благодаря полиморфизму, под которым понимается возможность во время выполнения программы с помощью одного и того же имени выполнять разные действия или обращаться к объектам разного типа. Чаще всего понятие полиморфизма связывают с механизмом виртуальных методов. Не сказать об этом нельзя, но подробно о полиморфизме речь пойдет в следующей части лекций. Здесь можно сказать стандартную фразу:« Этот материал выходит за границы данной книги».

Подводя итог сказанному, сформулирую достоинства ООП:

· использование при программировании понятий, близких к предметной области;

· возможность успешно управлять большими объемами исходного кода благодаря инкапсуляции, то есть скрытию деталей реализации объектов и упрощению структуры программы;

· возможность многократного использования кода за счет наследования;

· сравнительно простая возможность модификации программ;

· возможность создания и использования библиотек объектов.

Эти преимущества особенно явно проявляются при разработке программ большого объема и классов программ. Однако ничто не дается даром: создание объектно-ориентированной программы представляет собой весьма непростую задачу. Чтобы эффективно использовать готовые объекты из библиотек, необходимо освоить большой объем достаточно сложной информации. Неграмотное же применение ООП способно привести к созданию излишне сложных программ, которые невозможно отлаживать и усовершенствовать.

Еще надо помнить об инкапсуляции,о которой говорилось раньше. Мощным средством инкапсуляции являются модификаторы видимости. Модификатор privateпозволяет использовать имена только внутри того класса, в котором они объявлены. Модификатор public позволяет использовать имена в любом месте программы. Есть еще модификатор protected, который позволяет работать с именами в своем классе и в классах-наследниках.

Вернемся к Нашему(Вашему) примеру. Разобьем класс, в которомрешается задача на два класса. В классе-предке оставим только то, что относится непосредственно к задаче, в класс-наследник перенесем всё, что относится к вводу-выводу данных или по-другому, всё, что относится к интерфейсу пользователя, то есть к оконной форме приложения. Чего Мы(Вы) этим добьемся? Получится, что класс-предок не зависит от интерфейса пользователя, то есть от формы и тех оконных элементов, которые используются в ней. Одному нравится одно, другому другое, а может и не нужна никакая форма – допустим, результаты надо сохранить в файле, а потом куда-то их отослать. Если Мы(Вы) так сделаем, то в дальнейшем можем распространять Наш(Ваш) класс-предок (см. приложение 2), а тому, кто его захочет использовать, останется только написать интерфейс пользователя.

Обсудим каждый из трех классов: класс-предок Massiv, класс-наследник MassivIO и классForm1 (см. пример 8.4.).

Класс Massiv: три поля – исходный массив, массив из положительных элементов исходного массива, среднее значение исходного массива. Все поле имеют модификатор protected. Два метода – для вычисления среднего значения и для формирования массива положительных элементов. Оба с модификатором public. Почему эти методы открыты? Они будут вызываться в кнопка, то есть вне класса, в котором они описаны. И всё.Именно этот класс и будем распространять!

Класс MassivIO: новых полей нет. Методы – перенесем все методы, занимающиеся формированием исходного массива из класса-предка Massivпримера 8.2 в класс класс-наследник MassivIO. Это методы с именем Input и OutPut. Так как они вызываются в кнопках формы, то придется оставить их открытыми (public). Метод, занимающийся выводом массива в оконный компонент типа listBoxOutPutимеет недостаток –у него есть параметр, в который при вызове передается массив. Это и привело в предыдущем примере к организации открытого свойства Mass, связанного с полем mass, в котороми лежит исходный массив. А параметр в этом методе нужен для того, чтобы с помощью него можно было выводить не только исходный массив, но и массив из положительных элементов исходного массива. Но было обещано, что можно организовать работу так, что открытое свойство не понадобится. Организуем в этом классе еще один методAllOutPut, в котором дважды вызовем метод Output для вывода сначала исходного массива, а затем результирующего массива. В метод AllOutPut имена массивов передавать не надо. Но так как это метод класса-наследника, то поля класса-предка, объявленные как защищенные, с нем видны и их можно передавать как параметры в метод OutPut. Далее, метод OutPutв классе MassivIOтеперь можно объявить с модификатором private.Ну и последнее, организуем в новом методе AllOutPutеще и вывод среднего значения в оконный элемент типа textBox. Получается, что в AllOutPut с качестве параметровцелесообразно передавать имена тех оконных элементов, в которые Мы(Вы) будем выводить результаты (см. пример 8.4).

Класс Form1.Сначала о форме-картинке. На форме расположены три кнопки и один маленький textBox, которые отвечают за формирование исходного массива. Здесь ничего не изменилось в предыдущего примера 8.2.

На форме появился оконный элемент «панель группирования»groupBox 1, на котором расположены несколько кнопок, два списка строк класса listBoxи один однострочный редакторклассаtextBox. После запуска приложения эту панель группирования не видна.Но как только исходный массив сформирован, сразу же панель группирования становится видимой. Как это сделано? На этапе визуального проектирования(первоначально)значение свойства, отвечающего за видимость элемента выставлено в false (groupBox 1.Visible= false). Как только нажата одна из трех кнопок (Button1.Click илиButton2.Click или Button3.Click) свойство groupBox 1.Visible= true и панель группирования становится видимой. Зачем так сделано? Чтобы нельзя было запустить решение задачи до формирования исходного массива. После этого на панели становятся видимыми две кнопки, в обработчиках события Click которых решаются поставленные задачи. Пока не будут нажаты обе эти клавиши, кнопка «Вывод результатов» не видна. Зачем так сделано? С начала получи результаты, а потом можешь их выводить. Как это сделано? В классе Form1организованы два поля типа bool – fl1, fl2. До тех пор пока оба не станут иметь значения true, кнопка Button7 не будет видимой. Да, чуть не забыли, в этом классе (Form1)есть поле ms класса MassivIO(в предыдущем примере 8.2 поле ms было объектом класса Massiv ), c которым работают во всех обработчиках событий.Исходный текст файла Form1.cs привелен в примере 8.4. На рис. 8.3, 8.4, 8.5, 8.6 приведена последовательность скриншотов решения задачи.

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

И еще, обратите внимание, сколько текста занимает описание собственно решения задачи (класс Massiv),сколько текста занимает описание класса MassivIO, и сколько - описание класса Form1. Ивсёэтоважно.

 

usingSystem;

usingSystem.Collections.Generic;

usingSystem.ComponentModel;

usingSystem.Data;

usingSystem.Drawing;

using System.Linq;

using System.Text;

using System.Windows.Forms;

 

namespace WindowsFormsApplication1

{

publicpartialclassForm1 : Form

{

public Form1()

   {

       InitializeComponent();

   }

 

MassivIO ms = null;

bool fl1 = false; bool fl2 = false;//отвечают за видимость кнопки "вывод результатов"

 

privatevoid button1_Click(object sender, EventArgs e)

   {

if (ms == null)

//ms = new Massiv();

           ms = newMassivIO();

       ms.InPutMass();

//формирование массива ms.mass в инициализации

groupBox1.Visible = true;

       fl1 = false; fl2=false;

       button7.Visible = false;

   }

 

privatevoid button2_Click(object sender, EventArgs e)

   {

if (ms == null)

           ms = newMassivIO();

ms.InPutMass(textBox2);

//чтение элементов массива ms.mass из строк многострочного редактора

//button4.Visible = true;

       groupBox1.Visible = true;

       fl1 = false; fl2 = false;

       button7.Visible = false;

   }

 

privatevoid button3_Click(object sender, EventArgs e)

   {

int n = Convert.ToInt32(textBox1.Text);

if (ms == null)

           ms = newMassivIO();

ms.InPutMass(n);

//заполнение массива с использованием датчика случайных чисел

groupBox1.Visible = true;

       fl1 = false; fl2 = false;

       button7.Visible = false;

   }

 

privatevoid button5_Click(object sender, EventArgs e)

   {

       ms.SrAr();

       fl1=true;

if (fl1 & fl2) button7.Visible = true;

   }

 

privatevoid button6_Click(object sender, EventArgs e)

   {

       ms.FormMassB();

       fl2 = true;

if (fl1 & fl2) button7.Visible = true;

   }

 

privatevoid button7_Click(object sender, EventArgs e)

   {

       ms.AllOutPut(listBox1, listBox2, textBox3);

   }

 

privatevoid button4_Click_1(object sender, EventArgs e)

   {

       Close();

   }

}

 

publicclassMassiv

{

protectedint[] mass=null;

protectedint[] massplus = null;//поле с положительными элементами массива A

protecteddouble sr;// среднеезначение

 

publicvoid SrAr()

   {

double s=0;

foreach (int x in mass)

           s = s + x;

       s = s / mass.Length;

this.sr=s;

   }

 

publicvoid FormMassB()

{//заполняет поле-массив b из положительных элементов массива mass

int[] a = newint[mass.Length];//вспомогательный массив

int k = 0;//счетчик количества

for(int i=0;i < mass.Length;i++)

if (mass[i] > 0)

           {

               a[k] = mass[i];

               k++;

           }

       massplus = newint[k];//инициализацияполя b

for (int i = 0; i < k; i++)

           massplus[i] = a[i];

   }

}

 

publicclassMassivIO:Massiv

{

publicvoid InPutMass()

   {

       mass = newint[] { 7, 6, 5, 4, 3, 2, 1 };

   }

publicvoid InPutMass(int n)

   {

       mass = newint[n];

Random rnd = newRandom();//инициализациядатчикасл.чисел

       rnd.NextDouble();

for (int i = 0; i <= mass.Length - 1; i++)

       {

           mass[i] = rnd.Next(0, 100) - 50;//выдаетсл.ч. вдиапазоне (-50,50)

}

   }

 

publicvoid InPutMass(TextBox TB)

   {

string[] s = TB.Text.Split('\r');

int len = s.Length;

// MessageBox.Show(Convert.ToString(len));

       mass = newint[len];

for (int i = 0; i < mass.Length; i++)

       {

           mass[i] = int.Parse(s[i]);

       }

   }

 

privatevoid OutPut(int[] a, ListBox lb)

   {

if (a != null)

       {

           lb.Items.Clear();

foreach (int x in a)

           {

               lb.Items.Add(x);

           }

       }

   }

publicvoid AllOutPut(ListBox lb1, ListBox lb2, TextBox tb)

   {

       OutPut(mass, lb1);

       OutPut(massplus, lb2);

       tb.Text = Convert.ToString(sr);

}

}

}

Пример 8.4.

 

Это скриншоты последовательности работы приложения.

При запуске открывается форма, с кнопками формирования массива (Рис.8.3). Всего остального не видно.

Рис.8.3.

После нажатия одной из них открывается панель «Решение задачи» с двумя кнопками – «Среднее значение» и «Формирование массива B».Кнопки «Вывод результатов» пока не видно(Рис.8.4).

Рис.8.4.

Только после нажатия обеих этих кнопок, открывается кнопка «Вывод результатов». То есть задача уже решена, но результатов пока не видно.(Рис.8.5)

Рис.8.5.

Нажатие вновь открытой кнопочки «Вывод результатов»приведет к выводу исходных данных и результатов.(Рис.8.6)

Рис.8.6.

Вcё!

 

Лекция 9

Двумерные массивы.

Класс Array.

Класс ArrayList .

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

Варианты описания двумерного массива:

 

тип[,] имя;

тип[,] имя = new тип [ разм_1, разм_2 ];

тип[,] имя = { список_инициализаторов };

тип[,] имя = new тип [,] { список_инициализаторов };

тип[,] имя = new тип [ разм_1, разм_2 ] { список_инициализаторов };

 

Примеры описаний (один пример на каждый вариант описания):

 

int[,] a;                   // элементов нет

int[,] b = newint[2, 3]; // элементы равны 0

int[,] c = {{1, 2, 3}, {4, 5, 6}}; // new подразумевается

int[,] c = newint[,] {{1, 2, 3}, {4, 5, 6}};//размерность вычисляется

int[,] d = newint[2,3] {{1, 2, 3}, {4, 5, 6}};// 5 избыточное описание

 

К элементу двумерного массива обращаются, указывая номера строки и столбца, на пересечении которых он расположен, например:

 

a[1, 4]   b[i, j]   b[j, i]

Ну а теперь нужен пример работы с двумерными массивами.

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

Для решения этой задачи создана иерархия двух классах: в классе-предке class CMatrорганизованы закрытые поля и соответствующие открытые свойства для хранения размерностей матрицы, самой матрицы и вектора из номеров максимальных элементов в строках матрицы. Обратите внимание, как описываются свойства, связанные с закрытыми полями-массивами. Кроме этого написаны два метода: метод publicvoid FindIndMax()для иницилизации и заполнения значениями одномерногомассива из номеров максимальных элементов строк матрицы и метод

publicdouble [,] ChangeMatr()

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

В классе-наследнике class MatrIO : CMatrнаписаны методы формирования исходной матрицы с именами InputMatr, метод вывода OutPutMatr(ListBox lb)матрицы в оконный элемент класса ListBoxи метод вывода одномерного массива OutPutVekt(ListBox lb)в ListBox.

Дата: 2019-11-01, просмотров: 155.