Студопедия

КАТЕГОРИИ:

АвтоАвтоматизацияАрхитектураАстрономияАудитБиологияБухгалтерияВоенное делоГенетикаГеографияГеологияГосударствоДомЖурналистика и СМИИзобретательствоИностранные языкиИнформатикаИскусствоИсторияКомпьютерыКулинарияКультураЛексикологияЛитератураЛогикаМаркетингМатематикаМашиностроениеМедицинаМенеджментМеталлы и СваркаМеханикаМузыкаНаселениеОбразованиеОхрана безопасности жизниОхрана ТрудаПедагогикаПолитикаПравоПриборостроениеПрограммированиеПроизводствоПромышленностьПсихологияРадиоРегилияСвязьСоциологияСпортСтандартизацияСтроительствоТехнологииТорговляТуризмФизикаФизиологияФилософияФинансыХимияХозяйствоЦеннообразованиеЧерчениеЭкологияЭконометрикаЭкономикаЭлектроникаЮриспунденкция

Работа со ступенчатыми массивами




 

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

Рассмотрим это на примере. Дан ступенчатый массив. Вывести номера его строк, в которых доля положительных элементов максимальна.

static void Main(string[] args)

{

float[][] b; //объявим неровный массив

int n, m;

Console.Write("Строк ");

n = Convert.ToInt32(Console.ReadLine());

b = new float[n][]; //определим количество строк

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

{

    Console.Write("Элементов в строке"+i+" ");

    m = Convert.ToInt32(Console.ReadLine());

    b[i] = new float[m]; // определим количество

                                                                    // элементов в i-ой строке

}

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

for (int j = 0; j < b[i].Length; j++)

   {

      Console.Write("b[" + i + "," + j + "]=");

              

b[i][j] = Convert.ToSingle(Console.ReadLine());

   }

float []dol=new float[n]; // массив для долей

                                              // положительных элементов в строке

int kol;

float maxdol=0; //максимальная доля

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

{

   kol=0;

   for (int j = 0; j < b[i].Length; j++)

     if(b[i][j]>0)kol++;

   if (b[i].Length!=0)

               dol[i]=(float)kol/b[i].Length;

          else

               dol[i]=0;

   if(maxdol<dol[i])maxdol=dol[i];

}

if (maxdol == 0)

     Console.WriteLine

       ("Нет положительных элементов в массиве");

     else

{     

string s=""; //в эту переменную соберем номера строк

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

   if (dol[i]==maxdol) s+=" "+i;

     

       Console.WriteLine

        ("Максимальная доля в строках "+s);

}

Console.ReadLine();

   }

Примечания.

  1. Если b неровный массив, то b.Length возвращает количество строк, а b[i].Length количество элементов в i–й строке.
  2. Нулевое количество элементов в строке не является ошибкой, в таком случае b[i].Length=0.
  3. присваивание string s=""; обязательно, даже для пустой строки.

 

 

Контрольные вопросы

1. Допустим, что в программе имеются объявления:

int i = 10, j = 9;

float x;

и оператор x = i / j; Какое знгачение получит х? Почему?

2. В каких случаях целесооюразно использовать ступенчатые массивы?

3. Когда целесообразно использовать оператор цикла foreach ?

4. К чему равно значение свойства массива Length (для одномерных,   

двумерных и ступенчатых массивов)?

5. Какое значение возвращает функция GetUpperBound(i) в  

зависимости от значения i ?

 

Работа с функциями

Общие принципы

 

В C#, как и в других языках, функции используют для двух целей:

- Для написания алгоритмов, которые должны выполняться многократно с разными исходными данными.

- Как средство структурирования программы: большие задачи целесообразно разделить на подзадачи, которые затем будут реализованы функциями.

    В C# функция может иметь тип возвращаемого значения или не иметь его (иметь тип void). Формальные параметры-переменные могут быть переданы как по значению, так и по ссылке.

    По умолчанию – по значению.

    Для организации передачи по ссылке используют ключевые слова:

 ref   позволяет изменить в функции переданный параметр, но параметр должен иметь значение при обращении к функции.

оut   позволяет получить в функции новое значение для параметра.

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

Проиллюстрируем сказанное несколькими примерами.

Пример 1.

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

void Nom1(out int k, int []mas)

    {

    int i;

     k=-8;

    for(i=0;i<mas.Length;i++)

         if(mas[i]<0){k=i;break;}

    }

Параметр k получает значение в результате выполнения функции.

  Второй вариант:

int Nom2(int []mas)

    {

    int i;

     k=-8;

    for(i=0;i<mas.Length;i++)

         if(mas[i]<0){k=i;break;}

         return k;

       }

Пример 2.

Найти номер первого элемента одномерного массива в заданном интервале после заданного элемента. При его отсутствии – вернуть в качестве ответа заданный номер.

 void Number(ref int k,double c1,double c2,double[]mas)

 {

for(int i=k;i<mas.Length;i++)

if (mas[i] > c1 && mas[i] < c2) { k = i; break; }

 }

Параметр k должен иметь значение до обращения к функции (отсутствие значения – синтаксическая ошибка!) и может менять своё значение в результате выполнения функции. Параметры с1 и с2 передаются по значению и могут быть лишь исходными данными в функции.

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

 

 

2.2. Процедурное программирование в C#

 

  Рассмотрим в этом параграфе компоновку программы с функциями. Вспомните структуру программы, описанной в § 1.1. Рассмотрим сначала, как можно использовать приведенные выше функции.

    Функция из примера 1.

namespace ConApp3

{

class Program

{

   static void Nom1(out int k, int[] mas)

   {

       int i;

       k = -8;

       for (i = 0; i < mas.Length; i++)

           if (mas[i] < 0) { k = i; break; }

   }

       

   static void Main(string[] args)

   {

       int[] m ={5,9,2,6,7,56,-100};

       int p;

       Nom1(out p, m);

       if (p < 0) Console.WriteLine("Нет отрицательных");

       else

       Console.WriteLine("Номер элемента "+p);           

       Console.ReadLine();

   }

}      }

Главная функция Main находится внутри класса Program и, поэтому имеет полное право работать его функциями с любым атрибутом доступа. Чтобы можно было вызывать функцию без создания экземпляра класса необходимо объявить функцию статической static. Обратите внимание на то, что и при вызове функции присутствует атрибут out.

    Функция из примера 2.

namespace ConApp3

{

class Program

{

    void Number(ref int k, double c1, double c2, 

                                    double[] mas)

   {

       for (int i = k; i < mas.Length; i++)

           if (mas[i] > c1 && mas[i] < c2)

                             { k = i; break; }

   }

       

static void Main(string[] args)

{

   double[] m ={5.1,9.4,2.7,6.8,7.1,56.8,100.0};

       int q=2;

       Program myclass = new Program();     //1

       myclass.Number(ref q, 8.0, 15.0, m); //2

       Console.WriteLine("Номер элемента "+q);           

       Console.ReadLine();

   } } }

 

В этом примере описатель static отсутствует, поэтому перед вызовом функции необходимо создать экземпляр класса (строка // 1). После этого вызовы всех функций из класса Program выполняют через квалификатор (строка // 2). Обратите внимание на то, что и при вызове функции присутствует атрибут ref.

В завершение параграфа приведем пример, содержащий функции:

- ввода массива,

- обработки массива – нахождение среднего арифметического.

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

namespace ConApp4

{

class Program

{

static int t1 = 0;

            //объявление глобальной переменной для функций

 

static void Inpt(int[][] k)

{ //ввод массива

int n, m;

t1++; //работа с глобальной переменной

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

  for (int j = 0; j < k[i].Length; j++)

  {

     Console.Write("massiv[" + i + "," + j + "]=");

    k[i][j] = Convert.ToInt32(Console.ReadLine());

  }

}

static float Proc(int[][] d)

{ // обработка массива

float sr = 0;

int kol = 0;

t1+=5; //работа с глобальной переменной

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

   for (int j = 0; j < d[i].Length; j++)

   {

     sr += d[i][j];

     kol++;

   }

     return sr / kol;

}

 

static void Main(string[] args)

{

  int[][] mas;

  int n, m;

  Console.Write("Строк ");

  n = Convert.ToInt32(Console.ReadLine());

  mas = new int[n][]; //определим количество строк

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

   {

Console.Write("Элементов в строке " + i + " ");

m = Convert.ToInt32(Console.ReadLine());

mas[i] = new int[m]; // определим количество

                                                             // элементов в i-ой строке

   }

  Inpt(mas);

Console.WriteLine("Среднее арифметическое " +  

                                    Proc(mas)+

        +” t1=”+t1); //работа с глобальной переменной

Console.ReadLine();

}   }  }

 

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

 

 

namespace ConApp6

{

class Program

{

   static int[] fun1(int[] k)

   { // результат функции - массив

       int kol = 0;

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

           if (k[i] > 0) kol++;

       int []res=new int[kol]; //объявление результата - массива

       kol = 0;

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

           if (k[i] > 0) res[kol++] = k[i];

       return res; //возвращение массива в качестве результата

   }

   static void Main(string[] args)

   {

       int[] mas,arr; // mas исходный массив arr - результат

       int n;

       Console.Write("Count of Elements ");

       n = Convert.ToInt32(Console.ReadLine());

       mas = new int[n];

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

       {

           Console.Write("mas[" + i + "]=");

           mas[i] = Convert.ToInt32(Console.ReadLine());

       }

       arr = fun1(mas); // инициализация массива - результата

                                                      // не требуется

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

            Console.WriteLine("arr[" + i + "]="+arr[i]);

        Console.ReadLine();

   }

}

}

 

Контрольные вопросы

1. Для чего используют функции?

2. Для чего используют атрибуты out и ref?

3. Что означает атрибут static?

4. Для чего целесообразно использовать глобальные переменные?

 

 

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

Общие принципы

 

    Базовыми понятиями объектно-ориентированного программирования являются объект и класс. Объект – это какой-то реально существующий предмет со всеми его индивидуальными характеристиками. Класс – это множество объектов с одинаковыми характеристиками и одинаковым поведением. При определении значений характеристик класс превращается в объект. Характеристики класса задают данными, а поведение – методами. В C# методы представляют собой функции, среди методов выделяют конструктор и деструктор – функции особого назначения и с особыми правилами оформления.

Свойства объектно-ориентированного программирования:

- инкапсуляция (объединение в одной структуре данных – классе объявления данных и методов их обработки);

- наследование (класс может иметь одного предка, данные предка автоматически включаются в его состав, можно использовать методы предка);

- полиморфизм (можно иметь несколько реализаций одного метода с автоматическим выбором подходящего).

Рассмотрим в этой главе работу с классами в C#.

 










Последнее изменение этой страницы: 2018-04-12; просмотров: 313.

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