Главная Обратная связь

Дисциплины:

Архитектура (936)
Биология (6393)
География (744)
История (25)
Компьютеры (1497)
Кулинария (2184)
Культура (3938)
Литература (5778)
Математика (5918)
Медицина (9278)
Механика (2776)
Образование (13883)
Политика (26404)
Правоведение (321)
Психология (56518)
Религия (1833)
Социология (23400)
Спорт (2350)
Строительство (17942)
Технология (5741)
Транспорт (14634)
Физика (1043)
Философия (440)
Финансы (17336)
Химия (4931)
Экология (6055)
Экономика (9200)
Электроника (7621)






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



 

Как было уже сказано выше, в 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#.

 


Эта страница нарушает авторские права

allrefrs.ru - 2019 год. Все права принадлежат их авторам!