[a,b]. В языке C#, как и во многих других языках, индексы задаются целочисленным типом. В других языках, например, в языке Паскаль, индексы могут принадлежать счетному конечному множеству, на котором определены функции, задающие следующий и предыдущий элемент. Диапазон [a,b] называется a - b -
В языке C++ все |
В языке C# снято существенное ограничение языка C++ на статичность
В языке C++ "классических" Шаблоны, определенные в стандартных библиотеках, конечно, стоит использовать, но все-таки странной является рекомендация не пользоваться структурами, встроенными непосредственно в язык. Замечу, что в других языках |
В языке C#, соблюдая преемственность, сохранены одномерные
Рассмотрим, как объявляются одномерные
Напомню общую структуру объявления:
[<атрибуты>] [<модификаторы>] <тип> []<объявители>;
Забудем пока об атрибутах и модификаторах. Объявление одномерного
<тип>[] <объявители>;
Заметьте, в отличие от языка C++ квадратные скобки приписаны не к имени переменной, а к типу. Они являются неотъемлемой частью определения класса, так что запись T[] следует понимать как класс одномерный T.
Что же касается границ изменения индексов, то эта характеристика к классу не относится, она является характеристикой переменных - экземпляров, каждый из которых является одномерным
Как и в случае объявления простых переменных, каждый объявитель может быть именем или именем с инициализацией. В первом случае речь идет об отложенной инициализации. Нужно понимать, что при Null. Поэтому пока
int[] a, b, c;
Чаще всего при объявлении
double[] x= {5.5, 6.6, 7.7};
Следуя синтаксису, элементы константного
Во втором случае создание и инициализация
int[] d= new int[5];
Итак, если Null. Если инициализация выполняется конструктором, то в динамической памяти создается сам
Как обычно задаются элементы Arrays, поддерживающего эту лекцию:
public void TestDeclaration()
{
//объявляются три одномерных массива A,B,C
int[] A = new int[5], B= new int[5], C= new int[5];
Arrs.CreateOneDimAr(A);
Arrs.CreateOneDimAr(B);
for(int i = 0; i<5; i++)
C[i] = A[i] + B[i];
//объявление массива с явной инициализацией
int[] x ={5,5,6,6,7,7};
//объявление массивов с отложенной инициализацией
int[] u,v;
u = new int[3];
for(int i=0; i<3; i++) u[i] =i+1;
//v= {1,2,3}; //присваивание константного массива
//недопустимо
v = new int[4];
v=u; //допустимое присваивание
int [,] w = new int[3,5];
//v=w; //недопустимое присваивание: объекты разных классов
Arrs.PrintAr1("A", A); Arrs.PrintAr1("B", B);
Arrs.PrintAr1("C", C); Arrs.PrintAr1("X", x);
Arrs.PrintAr1("U", u); Arrs.PrintAr1("V", v);
}
На что следует обратить внимание, анализируя этот текст:
A, B и C, создаваемые конструктором. Значения элементов этих трех int. То, что они имеют одинаковое число элементов, произошло по воле программиста, а не диктовалось требованиями языка. Заметьте, что после такого объявления с инициализацией конструктором, все элементы имеют значение, в данном случае - ноль, и могут участвовать в вычислениях.x объявлен с явной инициализацией. Число и значения его элементов определяется константным u и v объявлены с отложенной инициализацией. В последующих операторах u инициализируется в объектном стиле - элементы получают его в цикле значения.v - это ссылка, которой можно присвоить ссылку, но нельзя присвоить константный v = u? Это корректное ссылочное присваивание: хотя u и v имеют разное число элементов, но они являются объектами одного класса. В результате присваивания память, отведенная v, освободится, ею займется теперь сборщик мусора. Обе ссылки u и v будут теперь указывать на один и тот же w и делается попытка выполнить оператор присваивания v=w. Это ссылочное присваивание некорректно, поскольку объекты w и v - разных классов и для них не выполняется требуемое для присваивания согласование по типу.Arrs, статические методы которого выполняют различные операции над public static void CreateOneDimAr(int[] A)
{
for(int i = 0; i<A.GetLength(0);i++)
A[i] = rnd.Next(1,100);
}//CreateOneDimAr
Здесь rnd - это статическое поле класса Arrs, объявленное следующим образом:
private static Random rnd = new Random();
Процедура печати name выглядит так:
public static void PrintAr1(string name,int[] A)
{
Console.WriteLine(name);
for(int i = 0; i<A.GetLength(0);i++)
Console.Write("\t" + name + "[{0}]={1}", i, A[i]);
Console.WriteLine();
}//PrintAr1
На рис. 11.1 показан консольный вывод результатов работы процедуры TestDeclarations.
(рис 11.1) Результаты объявления и создания массивовОсобое внимание обратите на вывод, связанный с u и v.
Во всех вышеприведенных примерах объявлялись
Чисто синтаксически нет существенной разницы в объявлении
Приведу пример, в котором описана работа с
public void TestDynAr()
{
//объявление динамического массива A1
Console.WriteLine("Введите число элементов массива A1");
int size = int.Parse(Console.ReadLine());
int[] A1 = new int[size];
Arrs.CreateOneDimAr(A1);
Arrs.PrintAr1("A1",A1);
}//TestDynAr
В особых комментариях эта процедура не нуждается. Здесь
Уже объяснялось, что разделение
В чем особенность объявления
<тип>[, ... ,] <объявители>;
Число запятых, увеличенное на единицу, и задает
public void TestMultiArr()
{
int[,]matrix = {{1,2},{3,4}};
Arrs.PrintAr2("matrix", matrix);
}//TestMultiArr
Давайте рассмотрим классическую задачу умножения прямоугольных матриц. Нам понадобится три
public void TestMultiMatr()
{
int n1, m1, n2, m2,n3, m3;
Arrs.GetSizes("MatrA",out n1,out m1);
Arrs.GetSizes("MatrB",out n2,out m2);
Arrs.GetSizes("MatrC",out n3,out m3);
int[,]MatrA = new int[n1,m1], MatrB = new int[n2,m2];
int[,]MatrC = new int[n3,m3];
Arrs.CreateTwoDimAr(MatrA);Arrs.CreateTwoDimAr(MatrB);
Arrs.MultMatr(MatrA, MatrB, MatrC);
Arrs.PrintAr2("MatrA",MatrA); Arrs.PrintAr2("MatrB",MatrB);
Arrs.PrintAr2("MatrC",MatrC);
}//TestMultiMatr
Три матрицы - MatrA, MatrB и MatrC - имеют произвольные размеры, выясняемые в диалоге с пользователем, и использование для их описания CreateTwoDimAr заполняет случайными числами элементы матрицы, переданной ему в качестве аргумента, метод PrintAr2 выводит матрицу на печать. Я не буду приводить их код, похожий на код их одномерных аналогов.
Метод MultMatr выполняет умножение прямоугольных матриц. Это классическая задача из набора задач, решаемых на первом курсе. Вот текст этого метода:
public void MultMatr(int[,]A, int[,]B, int[,]C)
{
if (A.GetLength(1) != B.GetLength(0))
Console.WriteLine("MultMatr: ошибка размерности!");
else
for(int i = 0; i < A.GetLength(0); i++)
for(int j = 0; j < B.GetLength(1); j++)
{
int s=0;
for(int k = 0; k < A.GetLength(1); k++)
s+= A[i,k]*B[k,j];
C[i,j] = s;
}
}//MultMatr
В особых комментариях эта процедура не нуждается. Замечу лишь, что прежде чем проводить вычисления, производится проверка корректности размерностей исходных матриц при их перемножении, - число столбцов первой матрицы должно быть равно числу строк второй матрицы.
Обратите внимание, как выглядят результаты консольного вывода на данном этапе работы (рис. 11.2).
(рис 11.2) Умножение матрицЕще одним видом
В каких ситуациях может возникать необходимость в таких структурах данных? Эти Fathers, представляющие отцов, могут задаваться одномерным Fathers[i] - это i -й отец. Вершины второго уровня представляются Children, так что Children[i] - это i -го отца, а Children[i][j] - это j -й ребенок i -го отца. Для представления внуков понадобится третий уровень, так что GrandChildren [i][j][k] будет представлять к -го внука j -го ребенка i -го отца.
Есть некоторые особенности в объявлении и инициализации таких int[][] задает int.
Сложнее с созданием самих new int[3][5], поскольку он не задает
//массив массивов - формальный пример
//объявление и инициализация
int[][] jagger = new int[3][]
{
new int[] {5,7,9,11},
new int[] {2,8},
new int[] {6,12,4}
};
jagger имеет всего два уровня. Можно считать, что у него три элемента, каждый из которых является new, чтобы создать внутренний
int[][] jagger1 = new int[3][]
{
new int[4],
new int[2],
new int[3]
};
В этом случае элементы new int[][]. Самое забавное, что вызов этого конструктора можно вообще опустить - он будет подразумеваться:
int[][] jagger2 =
{
new int[4],
new int[2],
new int[3]
};
А вот конструкторы нижнего уровня необходимы. Еще одно важное замечание -
Приведу теперь чуть более реальный пример, описывающий простое генеалогическое дерево, которое условно назову "отцы и дети":
//массив массивов -"Отцы и дети"
int Fcount =3;
string[] Fathers = new string[Fcount];
Fathers[0] ="Николай"; Fathers[1] = "Сергей";
Fathers[2] = "Петр";
string[][] Children = new string[Fcount][];
Children[0] = new string[] {"Ольга", "Федор"};
Children[1] = new string[]
{"Сергей","Валентина","Ира","Дмитрий"};
Children[2] = new string[]{"Мария","Ирина","Надежда"};
myar.PrintAr3(Fathers,Children);
Здесь отцов описывает обычный Fathers. Для описания детей этих отцов необходим уже Fathers. Здесь показан еще один способ создания таких void. А затем на нижнем уровне конструктор создает настоящие
Я не буду демонстрировать работу с генеалогическим деревом, ограничусь лишь печатью этого PrintAr3, которому в качестве аргументов передаются Fathers и Children. Вот текст данной процедуры:
public void PrintAr3(string [] Fathers, string[][] Children)
{
for(int i = 0; i < Fathers.Length; i++)
{
Console.WriteLine("Отец : {0}; Его дети:", Fathers[i]);
for(int j = 0; j < Children[i].Length; j++)
Console.Write( Children[i][j] + " ");
Console.WriteLine();
}
}//PrintAr3
Приведу некоторые комментарии к этой процедуре:
i организован по числу элементов Fathers. Заметьте, здесь используется свойство Length, в отличие от ранее применяемого метода GetLength.Children. Свойство Length для него возвращает число элементов верхнего уровня, совпадающее, как уже говорилось, с числом элементов Fathers.Length вызывается для каждого элемента Children[i], который является Приведу вывод, полученный в результате работы процедуры PrintAr3.
(рис 11.3) Дерево "Отцы и дети"В наших примерах
В лекции 9 подробно описывались особенности передачи аргументов в процедуру. Остается подчеркнуть только некоторые детали:
C в процедуре MultMatr, выходной аргумент совсем не обязательно снабжать ключевым словом ref или out (хотя и допустимо). Передача аргумента по значению в таких ситуациях так же хороша, как и передача по ссылке. В результате вычислений меняется сам GetSizes, где определялись границы out, сопровождающее аргументы, совершенно необходимо.[a,b]. В языке C#, как и во многих других языках, индексы задаются целочисленным типом. В других языках, например, в языке Паскаль, индексы могут принадлежать счетному конечному множеству, на котором определены функции, задающие следующий и предыдущий элемент. Диапазон [a,b] называется a - b -
В языке C++ все |
В языке C# снято существенное ограничение языка C++ на статичность
В языке C++ "классических" Шаблоны, определенные в стандартных библиотеках, конечно, стоит использовать, но все-таки странной является рекомендация не пользоваться структурами, встроенными непосредственно в язык. Замечу, что в других языках |
В языке C#, соблюдая преемственность, сохранены одномерные
Рассмотрим, как объявляются одномерные
Напомню общую структуру объявления:
[<атрибуты>] [<модификаторы>] <тип> []<объявители>;
Забудем пока об атрибутах и модификаторах. Объявление одномерного
<тип>[] <объявители>;
Заметьте, в отличие от языка C++ квадратные скобки приписаны не к имени переменной, а к типу. Они являются неотъемлемой частью определения класса, так что запись T[] следует понимать как класс одномерный T.
Что же касается границ изменения индексов, то эта характеристика к классу не относится, она является характеристикой переменных - экземпляров, каждый из которых является одномерным
Как и в случае объявления простых переменных, каждый объявитель может быть именем или именем с инициализацией. В первом случае речь идет об отложенной инициализации. Нужно понимать, что при Null. Поэтому пока
int[] a, b, c;
Чаще всего при объявлении
double[] x= {5.5, 6.6, 7.7};
Следуя синтаксису, элементы константного
Во втором случае создание и инициализация
int[] d= new int[5];
Итак, если Null. Если инициализация выполняется конструктором, то в динамической памяти создается сам
Как обычно задаются элементы Arrays, поддерживающего эту лекцию:
public void TestDeclaration()
{
//объявляются три одномерных массива A,B,C
int[] A = new int[5], B= new int[5], C= new int[5];
Arrs.CreateOneDimAr(A);
Arrs.CreateOneDimAr(B);
for(int i = 0; i<5; i++)
C[i] = A[i] + B[i];
//объявление массива с явной инициализацией
int[] x ={5,5,6,6,7,7};
//объявление массивов с отложенной инициализацией
int[] u,v;
u = new int[3];
for(int i=0; i<3; i++) u[i] =i+1;
//v= {1,2,3}; //присваивание константного массива
//недопустимо
v = new int[4];
v=u; //допустимое присваивание
int [,] w = new int[3,5];
//v=w; //недопустимое присваивание: объекты разных классов
Arrs.PrintAr1("A", A); Arrs.PrintAr1("B", B);
Arrs.PrintAr1("C", C); Arrs.PrintAr1("X", x);
Arrs.PrintAr1("U", u); Arrs.PrintAr1("V", v);
}
На что следует обратить внимание, анализируя этот текст:
A, B и C, создаваемые конструктором. Значения элементов этих трех int. То, что они имеют одинаковое число элементов, произошло по воле программиста, а не диктовалось требованиями языка. Заметьте, что после такого объявления с инициализацией конструктором, все элементы имеют значение, в данном случае - ноль, и могут участвовать в вычислениях.x объявлен с явной инициализацией. Число и значения его элементов определяется константным u и v объявлены с отложенной инициализацией. В последующих операторах u инициализируется в объектном стиле - элементы получают его в цикле значения.v - это ссылка, которой можно присвоить ссылку, но нельзя присвоить константный v = u? Это корректное ссылочное присваивание: хотя u и v имеют разное число элементов, но они являются объектами одного класса. В результате присваивания память, отведенная v, освободится, ею займется теперь сборщик мусора. Обе ссылки u и v будут теперь указывать на один и тот же w и делается попытка выполнить оператор присваивания v=w. Это ссылочное присваивание некорректно, поскольку объекты w и v - разных классов и для них не выполняется требуемое для присваивания согласование по типу.Arrs, статические методы которого выполняют различные операции над public static void CreateOneDimAr(int[] A)
{
for(int i = 0; i<A.GetLength(0);i++)
A[i] = rnd.Next(1,100);
}//CreateOneDimAr
Здесь rnd - это статическое поле класса Arrs, объявленное следующим образом:
private static Random rnd = new Random();
Процедура печати name выглядит так:
public static void PrintAr1(string name,int[] A)
{
Console.WriteLine(name);
for(int i = 0; i<A.GetLength(0);i++)
Console.Write("\t" + name + "[{0}]={1}", i, A[i]);
Console.WriteLine();
}//PrintAr1
На рис. 11.1 показан консольный вывод результатов работы процедуры TestDeclarations.
(рис 11.1) Результаты объявления и создания массивовОсобое внимание обратите на вывод, связанный с u и v.
Во всех вышеприведенных примерах объявлялись
Чисто синтаксически нет существенной разницы в объявлении
Приведу пример, в котором описана работа с
public void TestDynAr()
{
//объявление динамического массива A1
Console.WriteLine("Введите число элементов массива A1");
int size = int.Parse(Console.ReadLine());
int[] A1 = new int[size];
Arrs.CreateOneDimAr(A1);
Arrs.PrintAr1("A1",A1);
}//TestDynAr
В особых комментариях эта процедура не нуждается. Здесь
Уже объяснялось, что разделение
В чем особенность объявления
<тип>[, ... ,] <объявители>;
Число запятых, увеличенное на единицу, и задает
public void TestMultiArr()
{
int[,]matrix = {{1,2},{3,4}};
Arrs.PrintAr2("matrix", matrix);
}//TestMultiArr
Давайте рассмотрим классическую задачу умножения прямоугольных матриц. Нам понадобится три
public void TestMultiMatr()
{
int n1, m1, n2, m2,n3, m3;
Arrs.GetSizes("MatrA",out n1,out m1);
Arrs.GetSizes("MatrB",out n2,out m2);
Arrs.GetSizes("MatrC",out n3,out m3);
int[,]MatrA = new int[n1,m1], MatrB = new int[n2,m2];
int[,]MatrC = new int[n3,m3];
Arrs.CreateTwoDimAr(MatrA);Arrs.CreateTwoDimAr(MatrB);
Arrs.MultMatr(MatrA, MatrB, MatrC);
Arrs.PrintAr2("MatrA",MatrA); Arrs.PrintAr2("MatrB",MatrB);
Arrs.PrintAr2("MatrC",MatrC);
}//TestMultiMatr
Три матрицы - MatrA, MatrB и MatrC - имеют произвольные размеры, выясняемые в диалоге с пользователем, и использование для их описания CreateTwoDimAr заполняет случайными числами элементы матрицы, переданной ему в качестве аргумента, метод PrintAr2 выводит матрицу на печать. Я не буду приводить их код, похожий на код их одномерных аналогов.
Метод MultMatr выполняет умножение прямоугольных матриц. Это классическая задача из набора задач, решаемых на первом курсе. Вот текст этого метода:
public void MultMatr(int[,]A, int[,]B, int[,]C)
{
if (A.GetLength(1) != B.GetLength(0))
Console.WriteLine("MultMatr: ошибка размерности!");
else
for(int i = 0; i < A.GetLength(0); i++)
for(int j = 0; j < B.GetLength(1); j++)
{
int s=0;
for(int k = 0; k < A.GetLength(1); k++)
s+= A[i,k]*B[k,j];
C[i,j] = s;
}
}//MultMatr
В особых комментариях эта процедура не нуждается. Замечу лишь, что прежде чем проводить вычисления, производится проверка корректности размерностей исходных матриц при их перемножении, - число столбцов первой матрицы должно быть равно числу строк второй матрицы.
Обратите внимание, как выглядят результаты консольного вывода на данном этапе работы (рис. 11.2).
(рис 11.2) Умножение матрицЕще одним видом
В каких ситуациях может возникать необходимость в таких структурах данных? Эти Fathers, представляющие отцов, могут задаваться одномерным Fathers[i] - это i -й отец. Вершины второго уровня представляются Children, так что Children[i] - это i -го отца, а Children[i][j] - это j -й ребенок i -го отца. Для представления внуков понадобится третий уровень, так что GrandChildren [i][j][k] будет представлять к -го внука j -го ребенка i -го отца.
Есть некоторые особенности в объявлении и инициализации таких int[][] задает int.
Сложнее с созданием самих new int[3][5], поскольку он не задает
//массив массивов - формальный пример
//объявление и инициализация
int[][] jagger = new int[3][]
{
new int[] {5,7,9,11},
new int[] {2,8},
new int[] {6,12,4}
};
jagger имеет всего два уровня. Можно считать, что у него три элемента, каждый из которых является new, чтобы создать внутренний
int[][] jagger1 = new int[3][]
{
new int[4],
new int[2],
new int[3]
};
В этом случае элементы new int[][]. Самое забавное, что вызов этого конструктора можно вообще опустить - он будет подразумеваться:
int[][] jagger2 =
{
new int[4],
new int[2],
new int[3]
};
А вот конструкторы нижнего уровня необходимы. Еще одно важное замечание -
Приведу теперь чуть более реальный пример, описывающий простое генеалогическое дерево, которое условно назову "отцы и дети":
//массив массивов -"Отцы и дети"
int Fcount =3;
string[] Fathers = new string[Fcount];
Fathers[0] ="Николай"; Fathers[1] = "Сергей";
Fathers[2] = "Петр";
string[][] Children = new string[Fcount][];
Children[0] = new string[] {"Ольга", "Федор"};
Children[1] = new string[]
{"Сергей","Валентина","Ира","Дмитрий"};
Children[2] = new string[]{"Мария","Ирина","Надежда"};
myar.PrintAr3(Fathers,Children);
Здесь отцов описывает обычный Fathers. Для описания детей этих отцов необходим уже Fathers. Здесь показан еще один способ создания таких void. А затем на нижнем уровне конструктор создает настоящие
Я не буду демонстрировать работу с генеалогическим деревом, ограничусь лишь печатью этого PrintAr3, которому в качестве аргументов передаются Fathers и Children. Вот текст данной процедуры:
public void PrintAr3(string [] Fathers, string[][] Children)
{
for(int i = 0; i < Fathers.Length; i++)
{
Console.WriteLine("Отец : {0}; Его дети:", Fathers[i]);
for(int j = 0; j < Children[i].Length; j++)
Console.Write( Children[i][j] + " ");
Console.WriteLine();
}
}//PrintAr3
Приведу некоторые комментарии к этой процедуре:
i организован по числу элементов Fathers. Заметьте, здесь используется свойство Length, в отличие от ранее применяемого метода GetLength.Children. Свойство Length для него возвращает число элементов верхнего уровня, совпадающее, как уже говорилось, с числом элементов Fathers.Length вызывается для каждого элемента Children[i], который является Приведу вывод, полученный в результате работы процедуры PrintAr3.
(рис 11.3) Дерево "Отцы и дети"В наших примерах
В лекции 9 подробно описывались особенности передачи аргументов в процедуру. Остается подчеркнуть только некоторые детали:
C в процедуре MultMatr, выходной аргумент совсем не обязательно снабжать ключевым словом ref или out (хотя и допустимо). Передача аргумента по значению в таких ситуациях так же хороша, как и передача по ссылке. В результате вычислений меняется сам GetSizes, где определялись границы out, сопровождающее аргументы, совершенно необходимо.Для получения официальных документов о завершении программы дополнительного профессионального образования (удостоверения о повышении квалификации, дипломов о профессиональной переподготовке и MBA) необходимо предоставить:
Внимание! Вы можете не заказывать доставку бумажной версии официального документы, а скачать его в электронном виде и распечатать самостоятельно. Информация о выданном документе в течение 1 месяца загружается в Федеральную информационную систему «Федеральный реестр сведений о документах об образовании и (или) о квалификации, документах об обучении» - ФИС ФРДО.
Доступ на новый сайт осуществляется с использованием адреса электронной почты, который был указан вами при регистрации на "старом". Мы постарались перенести все ваши данные с прежнего ресурса, однако не исключена вероятность потери части информации.
При возникновении проблемы со входом, воспользуйтесь функцией сброса пароля
Если вы обнаружите несоответствия, пожалуйста, сообщите нам.