Программирование на языке С#: разработка консольных приложений

Массивы

Разбить на страницы
Показывать лекцию целиком

Массив - набор элементов одного и того же типа, объединенных общим именем. Массивы в С# можно использовать по аналогии с тем, как они используются в других языках программирования. Однако С#-массивы имеют существенные отличия: они относятся к ссылочным типам данных, более того - реализованы как объекты. Фактически имя массива является ссылкой на область кучи (динамической памяти), в которой последовательно размещается набор элементов определенного типа. Выделение памяти под элементы происходит на этапе инициализации массива. А за освобождением памяти следит система сборки мусора - неиспользуемые массивы автоматически утилизируются данной системой.

Рассмотрим различные типы массивов.

Одномерные массивы

Одномерный массив - это фиксированное количество элементов одного и того же типа, объединенных общим именем, где каждый элемент имеет свой номер. Нумерация элементов массива в С# начинается с нуля, то есть, если массив состоит из 10 элементов, то его элементы будут иметь следующие номера: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9.

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

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

Форма записи Пояснения
базовый_тип [] имя__массива;
Например:
int [] a;
Описана ссылка на одномерный массив, которая в дальнейшем может быть использована:
  • для адресации на уже существующий массив;
  • передачи массива в метод в качестве параметра
  • отсроченного выделения памяти под элементы массива.
  • базовый_тип [] имя__массива = new базовый_тип [размер];
    Например:
    int []a=new int [10];
    Объявлен одномерный массив заданного типа и выделена память под одномерный массив указанной размерности. Адрес данной области памяти записан в ссылочную переменную. Элементы массива равны нулю.Замечание. Надо отметить, что в C# элементам массива присваиваются начальные значения по умолчанию в зависимости от базового типа. Для арифметических типов - нули, для ссылочных типов - null, для символов - пробел.
    базовый_тип [] имя__массива={список инициализации};
    Например:
    int []a={0, 1, 2, 3};
    Выделена память под одномерный массив, размерность которого соответствует количеству элементов в списке инициализации. Адрес этой области памяти записан в ссылочную переменную. Значение элементов массива соответствует списку инициализации.

    Обращения к элементам массива происходит с помощью индекса, для этого нужно указать имя массива и в квадратных скобках его номер. Например, a[0], b[10], c[i].

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

    Пример 1.

    static void Main()
    {
      int[] myArray = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
      int i;
      for (i = 0; i < 10; ++i)
      Console.WriteLine(myArray[i]);
    }
    Задание. Измените программу так, чтобы числа выводились в строчку.

    Пример 2.

    static void Main()
    {
      int[] myArray = new int[10];
      int i;
      for (i = 0; i < 10; i++)
      myArray[i] = i * i;
      for (i = 0; i < 10; i++)
      Console.WriteLine(myArray[i]);
    }
    Задание. Измените программу так, чтобы обрабатывался массив из n чисел.

    Хотя при инициализации массива нет необходимости использовать операцию new, все же массив можно инициализировать следующим образом:

    int [ ] myArray = new int [ ] { 99, 10, 100, 18, 78, 23, 163, 9, 87, 49 };

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

    static void Main()
    {
      int[] myArray = { 0, 1, 2, 3, 4, 5};
      int i;
      for (i = 0; i < 6; i++)
      Console.Write(" "+myArray[i]);
      Console.WriteLine("\nНовый массив: ");
      myArray = new int[] { 99, 10, 100, 18, 78, 23, 163, 9, 87, 49 }; // 1
      for (i = 0; i < 10; i++)
      Console.Write(" " + myArray[i]);
    }

    Следует отметить, что первоначально переменная myArray ссылалась на 6-ти элементный массив. В строке 1 переменной myArray была присвоена ссылка на новый 10-элементный массив, в результате чего исходный массив оказался неиспользуемым, т.к. на него теперь не ссылается ни один объект. Поэтому он автоматически будет удален сборщиком мусора.

    Массивы и исключения

    Выход за границы массива в C# расценивается как ошибка, в ответ на которую генерируется исключение - IndexOutOfRangeException.

    Рассмотрим следующий пример:

    static void Main()
    {
      int[] myArray = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
      int i;
      try
      {
        for (i = 0; i <= 10; i++) Console.WriteLine(myArray[i]);
      }
      catch (IndexOutOfRangeException)
      {
        Console.WriteLine("Exception: Выход за границу диапазона");
      }
    }
    Задание. Добавьте в программу обработчики исключений FormatException и OutOfMemoryException. Вспомните, что они контролируют.

    Массив как параметр

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

    Рассмотрим пример передачи массива как параметра:

    class Program
    {
      static void Print(int n, int[] a) //n - размерность массива, а - ссылка на массив
      {
        for (int i = 0; i < n; i++) Console.Write("{0} ", a[i]);
        Console.WriteLine();
      }
    
      static void Change(int n, int[] a)
      {
        for (int i = 0; i < n; i++)
        if (a[i] > 0) a[i] = 0; // изменяются элементы массива
      }
    
      static void Main()
      {
        int[] myArray = { 0, -1, -2, 3, 4, 5, -6, -7, 8, -9 };
        Print(10, myArray);
        Change(10, myArray);
        Print(10, myArray);
      }
    }
    Задание. Измените программу так, чтобы метод Change удваивал значения положительных элементов массива.

    Массив как объект

    Мы уже говорили о том, что массивы в С# реализованы как объекты. Если говорить более точно, то они реализованы на основе базового класса Array, определенного в пространстве имен System. Данный класс содержит различные свойства и методы. Например, свойство Length позволяет определять количество элементов в массиве. Преобразуем предыдущий пример:

    class Program
    {
      static void Print(int[] a) // передаем только ссылку на массив
      {
        for (int i = 0; i < a.Length; i++) Console.Write("{0} ", a[i]);
        Console.WriteLine();
      }
    
      static void Change(int[] a)
      {
        for (int i = 0; i < a.Length; i++)
        if (a[i] > 0) a[i] = 0;
      }
    
      static void Main()
      {
        int[] myArray = { 0, -1, -2, 3, 4, 5, -6, -7, 8, -9 };
        Print(myArray);
        Change(myArray);
        Print(myArray);
      }
    }

    Другие свойства и методы класса Array приведены в следующей таблице:

    Элемент Вид Описание
    Length свойство Количество элементов массива (по всем размерностям)
    BinarySearch статический метод Двоичный поиск в отсортированном массиве
    Clear статический метод Присваивание элементам массива значений по умолчанию
    Copy статический метод Копирование заданного диапазона элементов одного массива в другой
    CopyTo экземплярный метод Копирование всех элементов текущего одномерного массива в другой массив
    GetValue экземплярный метод Получение значения элемента массива
    IndexOf статический метод Поиск первого вхождения элемента в одномерный массив
    LastIndexOf статический метод Поиск последнего вхождения элемента в одномерный массив
    Reverse статический метод Изменение порядка следования элементов на обратный
    SetValue экземплярный метод Установка значения элемента массива
    Sort статический метод Упорядочивание элементов одномерного массива

    Вызов статических методов происходит через обращение к имени класса, например, Array.Sort(myArray). В данном случае мы обращаемся к статическому методу Sort класса Array и передаем данному методу в качестве параметра объект myArray - экземпляр класса Array.

    Обращение к свойству или вызов экземплярного метода производится через обращение к экземпляру класса, например, myArray.Length или myArray.GetValue(i).

    Пример:

    class Program
    {
      static void Main()
      {
        try
        {
          int[] MyArray;
          Console.Write("Введите размерность массива: ");
          int n = int.Parse(Console.ReadLine());
          MyArray = new int[n];
          for (int i = 0; i < MyArray.Length; ++i)
          {
            Console.Write("a[{0}]=",i);
            MyArray[i] = int.Parse(Console.ReadLine());
          }
          PrintArray("исходный массив:", MyArray);
          Array.Sort(MyArray);
          PrintArray("массив отсортирован по возрастанию", MyArray);
          Array.Reverse(MyArray);
          PrintArray("массив отсортирован по убыванию", MyArray);
        }
        catch (FormatException)
        {
          Console.WriteLine("неверный формат ввода данных");
        }
        catch (OverflowException)
        {
          Console.WriteLine("переполнение");
        }
        catch (OutOfMemoryException)
        {
          Console.WriteLine("недостаточно памяти для создания нового объекта");
        }
      }
    
      static void PrintArray(string a, int[] mas)
      {
        Console.WriteLine(a);
        for (int i = 0; i < mas.Length; i++) Console.Write("{0} ", mas[i]);
        Console.WriteLine();
      }
    }
    }
    Задание. Добавьте в программу метод InputArray, предназначенный для ввода с клавиатуры элементов массива. Продемонстрируйте работу данного метода.

    Многомерные массивы

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

    Объявить двумерный массив можно одним из предложенных способов:

    тип [,] имя__массива;
    тип [,] имя__массива = new тип [размер1, размер2];
    тип [,] имя__массива={{элементы 1-ой строки}, … , {элементы n-ой строки}};
    тип [,] имя__массива= new тип [,]{{элементы 1-ой строки}, … ,{элементы n-ой строки}};
    строки}};

    Например:

    int [,] a; 
    int [,] a= new int [3, 4];
    int [,] a={{0, 1, 2}, {3, 4, 5}};
    int [,] a= new int [,]{{0, 1, 2}, {3, 4, 5}};
    Замечания.
  • Как и в случае с одномерными массивами, последние два описания являются избыточными.
  • При работе с многомерными массивами можно использовать приемы, которые мы рассмотрели для одномерных массивов.
  • При обращении к свойству Length для двумерного массива мы получим общее количество элементов в массиве. Чтобы получить количество строк нужно обратиться к методу GetLength с параметром 0. Чтобы получить количество столбцов - к методу GetLength с параметром 1.
  • Пример:

    class Program
      {
        static void PrintArray(string a, int[,] mas)
        {
          Console.WriteLine(a);
          for (int i = 0; i < mas.GetLength(0); i++)
          {
            for (int j = 0; j < mas.GetLength(1); j++)
              Console.Write("{0} ", mas[i, j]);
            Console.WriteLine();
          }
        }
    
        static void Change(int[,] mas)
        {
          for (int i = 0; i < mas.GetLength(0); i++)
            for (int j = 0; j < mas.GetLength(1); j++)
              if (mas[i, j] % 2 == 0) mas[i, j] = 0;              
        }
    
        static void Main()
        {
          try
          {
            int[,] MyArray ={ { 1, 2, 3 }, { 4, 5, 6 }, { 7, 8, 9 } };
            PrintArray("исходный массив:", MyArray);
            Change(MyArray);
            PrintArray("итоговый массив", MyArray);
          }
          catch (FormatException)
          {
                Console.WriteLine("неверный формат ввода данных");
          }
          catch (OverflowException)
          {
                Console.WriteLine("переполнение");
          }
          catch (OutOfMemoryException)
          {
                Console.WriteLine("недостаточно памяти для создания нового объекта");
          }
        }
      }
    Задания.
  • Добавьте в программу метод InputArray, предназначенный для ввода с клавиатуры элементов массива. Продемонстрируйте работу данного метода.
  • Измените метод Change так, чтобы он вычислял сумму четных элементов двумерного массива.
  • Ступенчатые массивы

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

    Массив a a[0] a[0][0] a[0][1]
    a[1]
    a[1][0] a[1][1]
    a[n]
    a[n][0] a[n][1]

    Объявление ступенчатого массива:

    тип [][] имя_массива;

    Например:

    int [][]a;

    Фактически мы объявили одномерный массив ссылок на целочисленные одномерные массивы. При таком описании потребуется не только выделять память под одномерный массив ссылок, но и под каждый из целочисленных одномерных массивов. Такое распределение памяти позволяет определять произвольную длину каждой строки массива (отсюда и произошло название массива - ступенчатый). Например:

    int [][] a= new int [3][];  // Создаем три строки
    a[0]=new int [2];  // 0-ая строка ссылается на 2-х элементый одномерный массив 
    a[1]=new int [3];  // 1-ая строка ссылается на 3-х элементый одномерный массив
    a[2]=new int [10];  // 2-ая строка ссылается на 10-ти элементый одномерный массив

    Другой способ выделения памяти:

    int [][] a= {new int [2], new int [3], new int [10]};

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

    Пример:

    class Program
    {
      static void Main()
      {
        try
        {
          int[][] MyArray;
          Console.Write("Ввведите количество строк: ");
          int n = int.Parse(Console.ReadLine());
          MyArray = new int[n][];
          for (int i = 0; i < MyArray.Length; i++)
          {
            Console.Write("введите количество элементов в {0} строке: ", i);
            int j = int.Parse(Console.ReadLine());
            MyArray[i] = new int[j];
            for (j = 0; j < MyArray[i].Length; j++)
            {
              Console.Write("a[{0}][{1}]= ", i, j);
              MyArray[i][j] = int.Parse(Console.ReadLine());
            }
          }
          PrintArray("исходный массив:", MyArray);
          for (int i = 0; i < MyArray.Length; i++) Array.Sort(MyArray[i]);
          PrintArray("измененный массив", MyArray);
        }
        catch (FormatException)
        {
          Console.WriteLine("неверный формат ввода данных");
        }
        catch (OverflowException)
        {
          Console.WriteLine("переполнение");
        }
        catch (OutOfMemoryException)
        {
          Console.WriteLine("недостаточно памяти для создания нового объекта");
        }
      }
    
      static void PrintArray(string a, int[][] mas)
      {
        Console.WriteLine(a);
        for (int i = 0; i < mas.Length; i++)
        {
          for (int j = 0; j < mas[i].Length; j++) Console.Write("{0} ", mas[i][j]);
          Console.WriteLine();
        }
      }
    }
    Задание. Добавьте в программу метод MakeArray, предназначенный для создания ступенчатого массива, в котором количество элементов в каждой строке больше номера строки в два раза. А сам элемент равен сумме номеров строки и столбца, в котором он находится. Продемонстрируйте работу данного метода.

    Оператор foreach и его использование при работе с массивами

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

    foreach (<тип> <имя> in <группа>) <тело цикла>

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

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

    Рассмотрим несколько примеров использования оператора foreach:

  • для работы с одномерными массивами:
    static void PrintArray(string a, int [] mas)
    {
      Console.WriteLine(a);
      foreach (int x in mas)Console.Write("{0} ", x);
      Console.WriteLine();
    }
  • для работы с двумерными массивами:
    static int Sum (int [,] mas)
    {
      int s=0;
      foreach (int x in mas) s += x;
      return s;
    }
  • для работы со ступенчатыми массивами:
    static void PrintArray3(string a, int[][] mas)
    {
      Console.WriteLine(a);
      for (int i = 0; i < mas.Length; i++)
      {
        foreach (int x in mas[i]) Console.Write("{0} ", x);
        Console.WriteLine();
      }
    }
  • Практикум

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

    Пример 1: для одномерного массива

    using System;
    namespace ConsoleApplication2
    {
      class Class
      {
        static int [] Input ()
        {
          Console.WriteLine("введите размерность массива");
          int n=int.Parse(Console.ReadLine());
          int []a=new int[n];
          for (int i = 0; i < n; ++i) 
          {
            Console.Write("a[{0}]= ", i);
            a[i]=int.Parse(Console.ReadLine());
          }
          return a;
        }
    
        static void Print(int[] a) 
        {
          for (int i = 0; i < a.Length; ++i) Console.Write("{0} ", a[i]);
          Console.WriteLine();
        }
    
        static void Change(int[] a)
        {
          for (int i = 0; i < a.Length; ++i)
            if (a[i] > 0) a[i] = -a[i];
        }
    
        static void Main()
        {
          int[] myArray=Input();
    Console.WriteLine("Исходный массив:");
          Print(myArray);
          Change(myArray);
    Console.WriteLine("Измененный массив:");
          Print(myArray);
        }
      }
    }

    Пример 2: для двумерного массива

    using System;
    namespace ConsoleApplication
    {
      class Class
      {
        static int [,] Input (out int n, out int m)
        {
          Console.WriteLine("введите размерность массива");
          Console.Write("n = ");
          n=int.Parse(Console.ReadLine());
          Console.Write("m = ");
          m=int.Parse(Console.ReadLine());
          int [,]a=new int[n, m];
          for (int i = 0; i < n; ++i) 
            for (int j = 0; j < m; ++j)
            {
              Console.Write("a[{0},{1}]= ", i, j);
              a[i, j]=int.Parse(Console.ReadLine());
            }
          return a;
        }
    
        static void Print(int[,] a) 
        {
          for (int i = 0; i < a.GetLength(0); ++i,Console.WriteLine() )
            for (int j = 0; j < a.GetLength(1); ++j)
              Console.Write("{0,5} ", a[i, j]);
        }
    
        static void Change(int[,] a)
        {
          for (int i = 0; i < a.GetLength(0); ++i)
            for (int j = 0; j < a.GetLength(1); ++j)
              if (a[i, j] > 0) a[i, j] = -a[i, j];
        }
    
        static void Main()
        {
          int n,m;
          int[,] myArray=Input(out n, out m);
          Console.WriteLine("Исходный массив:");
          Print(myArray);
          Change(myArray);
          Console.WriteLine("Измененный массив:");
          Print(myArray);
        }
      }
    }
  • Заменить все элементы, меньшие заданного числа, этим числом.
  • Заменить все элементы, попадающие в интервал $$[a, b]$$, нулем.
  • Заменить все отрицательные элементы, не кратные $$3$$, противоположными им числами.
  • Все элементы, меньшие заданного числа, увеличить в два раза.
  • Подсчитать среднее арифметическое элементов.
  • Подсчитать среднее арифметическое отрицательных элементов.
  • Подсчитать количество нечетных элементов.
  • Подсчитать сумму элементов, попадающих в заданный интервал.
  • Подсчитать сумму элементов, кратных 9.
  • Подсчитать количество элементов, не попадающих в заданный интервал.
  • Подсчитать сумму квадратов четных элементов.
  • Вывести на экран номера всех элементов больших заданного числа.
  • Вывести на экран номера всех нечетных элементов.
  • Вывести на экран номера всех элементов, которые не делятся на 7.
  • Вывести на экран номера всех элементов, не попадающих в заданный интервал.
  • Определить, является ли произведение элементов трехзначным числом.
  • Определить, является ли сумма элементов двухзначным числом.
  • Вывести на экран элементы с четными индексами (для двумерного массива - сумма индексов должна быть четной).
  • Вывести на экран положительные элементы с нечетными индексами (для двумерного массива - первый индекс должен быть нечетным).
  • Дана последовательность из n действительных чисел.Замечание. Задачи из данного пункта решить, используя одномерный массив.
  • Подсчитать количество максимальных элементов.

    Пример.

    using System;
    namespace ConsoleApplication
    {
      class Class
      {
        static int [] Input ()
        {
          Console.WriteLine("введите размерность массива");
          int n=int.Parse(Console.ReadLine());
          int []a=new int[n];
          for (int i = 0; i < n; ++i) 
          {
            Console.Write("a[{0}]= ", i);
            a[i]=int.Parse(Console.ReadLine());
          }
          return a;
        }
    
        static int Max(int[] a)
        {
          int max=a[0];
          for (int i = 1; i < a.Length; ++i)
            if (a[i] > max) max=a[i];
          return max;
        }
    
        static void Main()
        {
          int[] myArray=Input();
          int max=Max(myArray);
          int kol=0;
          for (int i=0; i<myArray.Length;++i)
            if (myArray[i]==max)++kol;
          Console.WriteLine("Количество максимальных элементов = "+kol);
        }
      }
    }
  • Вывести на экран номера всех минимальных элементов.
  • Заменить все максимальные элементы нулями.
  • Заменить все минимальные элементы на противоположные.
  • Поменять местами максимальный элемент и первый.
  • Вывести на экран номера всех элементов, не совпадающих с максимальным.
  • Найти номер первого минимального элемента.
  • Найти номер последнего максимального элемента.
  • Подсчитать сумму элементов, расположенных между максимальным и минимальным элементами (минимальный и максимальный элементы в массиве единственные). Если максимальный элемент встречается позже минимального, то выдать сообщение об этом.
  • Найти номер первого максимального элемента.
  • Найти номер последнего минимального элемента.
  • Подсчитать сумму элементов, расположенных между первым максимальным и последним минимальными элементами. Если максимальный элемент встречается позже минимального, то выдать сообщение об этом.
  • Поменять местами первый минимальный и последний максимальный элементы.
  • Найти максимум из отрицательных элементов.
  • Найти минимум из положительных элементов.
  • Найти максимум из модулей элементов.
  • Найти количество пар соседних элементов, разность между которыми равна заданному числу.
  • Подсчитать количество элементов, значения которых больше значения предыдущего элемента.
  • Найти количество пар соседних элементов, в которых предыдущий элемент кратен последующему.
  • Найти количество пар соседних элементов, в которых предыдущий элемент меньше последующего.
  • Дан массив размером nxn, элементы которого целые числа.Замечание. При решении задач из данного пункта использовать двумерный массив.
  • Подсчитать среднее арифметическое нечетных элементов, расположенных выше главной диагонали.

    Пример.

    using System;
    namespace ConsoleApplication
    {
      class Class
      {
        static int [,] Input (out int n)
        {
          Console.WriteLine("введите размерность массива");
          Console.Write("n = ");
          n=int.Parse(Console.ReadLine());
          int [,]a=new int[n, n];
          for (int i = 0; i < n; ++i) 
            for (int j = 0; j < n; ++j)
            {
              Console.Write("a[{0},{1}]= ", i, j);
              a[i, j]=int.Parse(Console.ReadLine());
            }
          return a;
        }
    
        static void Print(int[,] a) 
        {
          for (int i = 0; i < a.GetLength(0); ++i,Console.WriteLine() )
            for (int j = 0; j < a.GetLength(1); ++j)
              Console.Write("{0,5} ", a[i, j]);
        }
    
        static double Rezalt(int[,] a)
        {
          int k=0;
          double s=0;
          for (int i = 0; i < a.GetLength(0); ++i)
            for (int j = i+1; j < a.GetLength(1); ++j)
              if (a[i, j] %2!= 0) {++k; s+=a[i, j];}
          if (k!=0) return s/k;
          else return 0;
        }
    
        static void Main()
        {
          int n;
          int[,] myArray=Input(out n);
          Console.WriteLine("Исходный массив:");
          Print(myArray);
          double rez=Rezalt(myArray);
          Console.WriteLine("Среднее арифметическое ={0:f2}", rez);
        }
      }
    }
  • Подсчитать среднее арифметическое четных элементов, расположенных ниже главной диагонали.
  • Подсчитать сумму элементов, расположенных на побочной диагонали.
  • Подсчитать среднее арифметическое ненулевых элементов, расположенных над побочной диагональю.
  • Подсчитать среднее арифметическое элементов, расположенных под побочной диагональю.
  • Поменять местами столбцы по правилу: первый с последним, второй с предпоследним и т.д.
  • Поменять местами две средних строки, если количество строк четное, и первую со средней строкой, если количество строк нечетное.
  • Поменять местами два средних столбца, если количество столбцов четное, и первый со средним столбцом, если количество столбцов нечетное.
  • Если количество строк в массиве четное, то поменять строки местами по правилу: первую строку со второй, третью - с четвертой и т.д. Если количество строк в массиве нечетное, то оставить массив без изменений.
  • Если количество столбцов в массиве четное, то поменять столбцы местами по правилу: первый столбец со вторым, третий - с четвертым и т.д. Если количество столбцов в массиве нечетное, то оставить массив без изменений.
  • Вычислить $$А^{n}$$, где $$n$$ - натуральное число.
  • Подсчитать норму матрицы по формуле$$||A||=\sum_{i}{\max_j{a_{i,j}}}.$$
  • Подсчитать норму матрицы по формуле$$||A||=\sum_{j}^{}{\max_i{a_{i,j}}}.$$
  • Вывести элементы матрицы в следующем порядке:(рис 8.3) 08_03
  • Выяснить, является ли матрица симметричной относительно главной диагонали.
  • Заполнить матрицу числами от 1 до n (где $$n=m \times k$$, а $$m $$ - количесто строк, а $$k $$ - количество столбцов прямоугольной матрицы) следующим образом:

    (рис 8.4) 08_04

  • Определить, есть ли в данном массиве строка, состоящая только из положительных элементов.
  • Определить, есть ли в данном массиве столбец, состоящий только из отрицательных элементов.
  • В каждой строке найти максимум и заменить его на противоположный элемент.
  • В каждом столбце найти минимум и заменить его нулем.
  • Дан массив размером nxn, элементы которого целые числа.Замечание. Для хранения массив n?n использовать ступенчатый массив.
  • Найти максимальный элемент в каждой строке и записать данные в новый массив.

    Пример

    using System;
    namespace ConsoleApplication
    {
      class Class
      {
        static int [][] Input ()
        {
          Console.WriteLine("введите размерность массива");
          Console.Write("n = ");
          int n=int.Parse(Console.ReadLine());
          int [][]a=new int[n][];
          for (int i = 0; i < n; ++i)
          {
            a[i]=new int [n];
            for (int j = 0; j < n; ++j)
            {
              Console.Write("a[{0},{1}]= ", i, j);
              a[i][j]=int.Parse(Console.ReadLine());
            }
          }
          return a;
        }
    
        static void Print1(int[] a) 
        {
          for (int i = 0; i < a.Length; ++i)
            Console.Write("{0,5} ", a[i]);
        }
    
        static void Print2(int[][] a) 
        {
          for (int i = 0; i < a.Length; ++i,Console.WriteLine() )
            for (int j = 0; j < a[i].Length; ++j)
              Console.Write("{0,5} ", a[i][j]);
        }
    
        static int Max(int[] a)
        {
          int max=a[0];
          for (int i = 1; i < a.Length; ++i)
            
            if (a[i] >max) {max=a[i];}
          return max;
        }
    
        static void Main()
        {
          int[][] myArray=Input();
          Console.WriteLine("Исходный массив:");
          Print2(myArray);
          int[]rez=new int [myArray.Length];
          for (int i=0;i<myArray.Length; ++i)
            rez[i]=Max(myArray[i]);
          Console.WriteLine("Новый массив:");
          Print1(rez);
        }
      }
    }
  • Найти минимальный элемент в каждом столбце и записать данные в новый массив.
  • Четные столбцы таблицы заменить на вектор $$Х$$.
  • Нечетные строки таблицы заменить на вектор $$Х$$.
  • Вычислить $$А*Х$$, где $$А$$ - двумерная матрица, $$X$$ - вектор.
  • Для каждой строки подсчитать количество положительных элементов и записать данные в новый массив.
  • Для каждого столбца подсчитать сумму отрицательных элементов и записать данные в новый массив.
  • Для каждого столбца подсчитать сумму четных положительных элементов и записать данные в новый массив.
  • Для каждой строки подсчитать количество элементов, больших заданного числа, и записать данные в новый массив.
  • Для каждого столбца найти первый положительный элемент и записать данные в новый массив.
  • Для каждой строки найти последний четный элемент и записать данные в новый массив.
  • Для каждого столбца найти номер последнего нечетного элемента и записать данные в новый массив.
  • Для каждой строки найти номер первого отрицательного элемента и записать данные в новый массив.
  • Для каждой строки найти сумму элементов с номерами от $$k1$$ до $$k2 $$ и записать данные в новый массив.
  • Для каждого столбца найти произведение элементов с номерами от $$k1 $$ до $$k2 $$ и записать данные в новый массив.
  • Для каждой строки подсчитать сумму элементов, не попадающих в заданный интервал, и записать данные в новый массив.
  • Подсчитать сумму элементов каждой строки и записать данные в новый массив. Найти максимальный элемент нового массива.
  • Подсчитать произведение элементов каждого столбца и записать данные в новый массив. Найти минимальный элемент нового массива.
  • Для каждой строки найти номер первой пары неравных элементов. Данные записать в новый массив.
  • Для каждого столбца найти номер первой пары одинаковых элементов. Данные записать в новый массив.
  • Самостоятельная работа

    Теоретический материал

    Вставка и удаление элементов в массивах

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

    Замечание. В пространстве имен System.Collection реализована коллекция ArrayList - массив, динамически изменяющий свой размер. Мы будем рассматривать его позже.

    Пример. Рассмотрим фрагмент программы:

    int []a=new int [10];
    int n=5;
    for (int i=0; i<5;i++) a[i]:=i*i;

    В этом случае массив можно представить следующим образом:

    n=5 0 1 2 3 4 5 6 7 8 9
    а 0 1 4 9 16 0 0 0 0 0

    Так как во время описания был определен массив из 10 элементов, а заполнено только первые 5, то оставшиеся элементы будут заполнены нулями.

    Что значит удалить из одномерного массива элемент с номером 3? Удаление должно привести к физическому "уничтожению" элемента с номером 3 из массива, при этом общее количество элементов должно быть уменьшено. В этом понимании удаления элемента итоговый массив должен выглядеть следующем образом

    0 1 2 4 5 6 7 8 9 недопустимое состояние
    а 0 1 4 16 0 0 0 0 0

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

    Однако "удаление" можно смоделировать сдвигом элементов влево и уменьшением значения переменной, которая отвечает за текущее количество элементов в массиве, на единицу:

    n=4 0 1 2 3 4 5 6 7 8 9
    а 0 1 4 16 0 0 0 0 0 0

    В общем случае, если мы хотим удалить элемент массива с номером k (всего в массиве n элементов, а последний элемент имеет индекс n-1 ), то нам необходимо произвести сдвиг элементов, начиная с k+1 -го на одну позицию влево. Т.е. на k -ое место поставить k+1 -й элемент, на место k+1 - k+2 -й элемент, …, на место n-2 - n-1 -й элемент. После чего значение n уменьшить на 1. В этом случае размерность массива не изменится, изменится лишь текущее количество элементов, и у нас создастся ощущение, что элемент с номером k удален. Рассмотрим данный алгоритм на примере:

    using System;
    namespace ConsoleApplication
    {
      class Class
      {
        static int [] Input ()
        {
          Console.WriteLine("введите размерность массива");
          int n=int.Parse(Console.ReadLine());
          int []a=new int[n];
          for (int i = 0; i < n; ++i) 
          {
            Console.Write("a[{0}]= ", i);
            a[i]=int.Parse(Console.ReadLine());
          }
          return a;
        }
    
        static void Print(int[] a, int n) 
        {
          for (int i = 0; i < n; ++i) Console.Write("{0} ", a[i]);
          Console.WriteLine();
        }
    
        static void DeleteArray(int[] a, ref int n, int m)
        {
          for (int i = m; i < n-1; ++i)
            a[i] = a[i+1];
          --n;
        }
    
        static void Main()
        {
          int[] myArray=Input();
          int n=myArray.Length;
          Console.WriteLine("Исходный массив:");
          Print(myArray, n);
          Console.WriteLine("Введите номер элемента для удаления:");
          int m=int.Parse(Console.ReadLine());
    DeleteArray(myArray, ref n,m);
          Console.WriteLine("Измененный массив:");
          Print(myArray, n);
        }
      }
    }
    Задание. Подумайте, какие исключительные ситуации могут возникнуть в данной программе и добавьте в нее соответствующие обработки исключительных ситуаций

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

    using System;
    namespace ConsoleApplication
    {
      class Class
      {
        static int [,] Input (out int n, out int m)
        {
          Console.WriteLine("введите размерность массива");
          Console.Write("n = ");
          n=int.Parse(Console.ReadLine());
          Console.Write("m = ");
          m=int.Parse(Console.ReadLine());
          int [,]a=new int[n, m];
          for (int i = 0; i < n; ++i) 
            for (int j = 0; j < m; ++j)
            {
              Console.Write("a[{0},{1}]= ", i, j);
              a[i, j]=int.Parse(Console.ReadLine());
            }
          return a;
        }
    
        static void Print(int[,] a, int n, int m) 
        {
          for (int i = 0; i < n; ++i,Console.WriteLine() )
            for (int j = 0; j < m; ++j)
              Console.Write("{0,5} ", a[i, j]);
        }
    
        static void DeleteArray(int[,] a, ref int n, int m, int k)
        {
          for (int i = k; i < n-1; ++i)
            for (int j = 0; j < m; ++j)
              a[i, j] = a[i+1, j];
          --n;
        }
    
        static void Main()
        {
          int n,m;
          int[,] myArray=Input(out n, out m);
          Console.WriteLine("Исходный массив:");
          Print(myArray, n, m);
          Console.WriteLine("Введите номер строки для удаления:");
          int k=int.Parse(Console.ReadLine());
          DeleteArray(myArray, ref n, m, k);
          Console.WriteLine("Измененный массив:");
          Print(myArray, n, m);
        }
      }
    }
    Задания.
  • Подумайте, какие исключительные ситуации могут возникнуть в данной программе и добавьте в нее соответствующие обработки исключительных ситуаций.
  • Измените программу так, чтобы она удаляла k -тый столбец в двумерном массиве.
  • Рассмотрим модификацию предыдущей программы, для случая, когда используется ступенчатый массив.

    using System;
    namespace ConsoleApplication
    {
      class Class
      {
        
        static int [][] Input (out int n, out int m)
        {
          Console.WriteLine("введите размерность массива");
          Console.Write("n = ");
          n=int.Parse(Console.ReadLine());
          Console.Write("m = ");
          m=int.Parse(Console.ReadLine());
          int [] []a=new int[n][];
          for (int i = 0; i < n; ++i)
          {
            a[i]=new int[m];
            for (int j = 0; j < m; ++j)
            {
              Console.Write("a[{0},{1}]= ", i, j);
              a[i][j]=int.Parse(Console.ReadLine());
            }
          }
          return a;
        }
    
        static void Print(int[][] a, int n, int m) 
        {
          for (int i = 0; i < n; ++i,Console.WriteLine() )
            for (int j = 0; j < m; ++j)
              Console.Write("{0,5} ", a[i] [j]);
        }
    
        static void DeleteArray(int[][] a, ref int n, int k)
        {
          for (int i = k; i < n-1; ++i)//производим сдвиг ссылок
            a[i] = a[i+1];
          --n;
        }
    
        static void Main()
        {
          int n,m;
          int[][] myArray=Input(out n, out m);
          Console.WriteLine("Исходный массив:");
          Print(myArray, n, m);
          Console.WriteLine("Введите номер строки для удаления:");
          int k=int.Parse(Console.ReadLine());
          DeleteArray(myArray, ref n, k);
          Console.WriteLine("Измененный массив:");
          Print(myArray, n, m);
        }
      }
    }

    Вернемся к массиву, определенному в самом первом примере. И подумаем теперь, что значит добавить элемент в одномерный массив в позицию с номером k? В этом случае все элементы, начиная с k -ого, должны быть сдвинуты вправо на одну позицию. Однако сдвиг нужно начинать с конца, т.е. на первом шаге на n -е место поставить n-1 -ый элемент, потом на n-1 -ое место поставить n-2 -й элемент, …, наконец, на k+ 1 место вставить k-й элемент. Таким образом, копия k -го элемента будет на k+1 -м месте и на k -е место можно поставить новый элемент. Затем необходимо увеличить текущее количество элементов на 1.

    Рассмотрим массив из примера 1 и в качестве k зададим значение равное 3. В этом случае массив будет выглядеть следующим образом:

    k=3 0 1 2 3 4 5 6 7 8 9
    а 0 1 4 9 9 16 0 0 0 0

    Теперь в позицию с номером 3 можно поместить новое значение. А текущее количество элементов в массиве становится равным 6. Подумайте, почему сдвиг нужно выполнять с конца массива, а не с начала, как мы это делали в случае удаления элемента из массива.

    Рассмотрим программную реализацию данного алгоритма:

    using System;
    namespace ConsoleApplication
    {
      class Class
      {
        static int [] Input (out int n)
        {
          Console.WriteLine("введите размерность массива");
          n=int.Parse(Console.ReadLine());
          int []a=new int[2*n]; //выделяем памяти больше чем требуется
          for (int i = 0; i < n; ++i) 
          {
            Console.Write("a[{0}]= ", i);
            a[i]=int.Parse(Console.ReadLine());
          }
          return a;
        }
    
        static void Print(int[] a, int n) 
        {
          for (int i = 0; i < n; ++i) Console.Write("{0} ", a[i]);
          Console.WriteLine();
        }
    
        static void AddArray(int[] a, ref int n, int m)
        {
          for (int i = n; i >= m; --i)
            a[i] = a[i-1];
          ++n;
          Console.WriteLine("Введите значение нового элемента");
          a[m]=int.Parse(Console.ReadLine());
        }
    
        static void Main()
        {
          int n;
          int[] myArray=Input(out n);
          Console.WriteLine("Исходный массив:");
          Print(myArray, n);
          Console.WriteLine("Введите номер элемента для вставки:");
          int m=int.Parse(Console.ReadLine());
          AddArray(myArray, ref n,m);
          Console.WriteLine("Измененный массив:");
          Print(myArray, n);
        }
      }
    }

    Теперь рассмотрим добавление строки в двумерный массив. Для этого все строки после строки с номером k передвигаем на 1 строку вниз. Затем увеличиваем количество строк на 1. После этого копия строки с номером k будет находиться в столбце с номером k+1. И, следовательно, k -тый столбец можно заполнить новыми значениями. Рассмотрим программную реализацию алгоритма:

    using System;
    namespace ConsoleApplication
    {
      class Class
      {
        
        static int [,] Input (out int n, out int m)
        {
          Console.WriteLine("введите размерность массива");
          Console.Write("n = ");
          n=int.Parse(Console.ReadLine());
          Console.Write("m = ");
          m=int.Parse(Console.ReadLine());
    //выделяем памяти больше чем необходимо
          int [,]a=new int[2*n, m]; 
          for (int i = 0; i < n; ++i) 
            for (int j = 0; j < m; ++j)
            {
              Console.Write("a[{0},{1}]= ", i, j);
              a[i, j]=int.Parse(Console.ReadLine());
            }
          return a;
        }
    
    
        static void Print(int[,] a, int n, int m) 
        {
          for (int i = 0; i < n; ++i,Console.WriteLine() )
            for (int j = 0; j < m; ++j)
              Console.Write("{0,5} ", a[i, j]);
        }
    
        static void AddArray(int[,] a, ref int n, int m, int k)
        {
          for (int i = n; i >=k; --i)
            for (int j = 0; j < m; ++j)
              a[i+1, j] = a[i, j];
          ++n;
          Console.WriteLine("Введите элементы новой строки");
          for (int j=0; j<m;++j)
          {
            Console.Write("a[{0},{1}]=", k, j);
            a[k, j]=int.Parse(Console.ReadLine());
          }
        }
    
        static void Main()
        {
          int n,m;
          int[,] myArray=Input(out n, out m);
          Console.WriteLine("Исходный массив:");
          Print(myArray, n, m);
          Console.WriteLine("Введите номер строки для добавления:");
          int k=int.Parse(Console.ReadLine());
          AddArray(myArray, ref n, m, k);
          Console.WriteLine("Измененный массив:");
          Print(myArray, n, m);
        }
      }
    }
    Задания.
  • Подумайте, какие исключительные ситуации могут возникнуть в данной программе и добавьте в нее соответствующие обработки исключительных ситуаций.
  • Измените программу так, чтобы она добавляла k -тый столбец в двумерном массиве.
  • Рассмотрим модификацию предыдущей программы для случая, когда используется ступенчатый массив.

    using System;
    namespace ConsoleApplication
    {
      class Class
      {
        
        static int [][] Input (out int n, out int m)
        {
          Console.WriteLine("введите размерность массива");
          Console.Write("n = ");
          n=int.Parse(Console.ReadLine());
          Console.Write("m = ");
          m=int.Parse(Console.ReadLine());
    //выделяем памяти больше чем неообходимо
          int [][]a=new int[2*n][]; 
          for (int i = 0; i < n; ++i)
          {
            a[i]=new int [m];
            for (int j = 0; j < m; ++j)
            {
              Console.Write("a[{0}][{1}]= ", i, j);
              a[i][j]=int.Parse(Console.ReadLine());
            }
          }
          return a;
        }
    
        static void Print(int[][] a, int n, int m) 
        {
          for (int i = 0; i < n; ++i,Console.WriteLine() )
            for (int j = 0; j < m; ++j)
              Console.Write("{0,5} ", a[i][j]);
        }
    
        static void AddArray(int[][] a, ref int n, int m, int k)
        {
          for (int i = n; i >=k; --i)//выполняем сдвиг ссылок
            a[i+1] = a[i];
          ++n;
          a[k]=new int[m]; //создаем новую строку
          Console.WriteLine("Введите элементы новой строки");
          for (int j=0; j<m;++j)
          {
            Console.Write("a[{0}][{1}]=", k, j);
            a[k][j]=int.Parse(Console.ReadLine());
          }
        }
    
        static void Main()
        {
          int n,m;
          int[][] myArray=Input(out n, out m);
          Console.WriteLine("Исходный массив:");
          Print(myArray, n, m);
          Console.WriteLine("Введите номер строки для добавления:");
          int k=int.Parse(Console.ReadLine());
          AddArray(myArray, ref n, m, k);
          Console.WriteLine("Измененный массив:");
          Print(myArray, n, m);
        }
      }
    }

    Практические задания

  • В одномерном массиве, элементы которого - целые числа, произвести следующие действия:
  • Удалить из массива все четные числа.
  • Вставить новый элемент после всех элементов, которые заканчиваются на данную цифру.
  • Удалить из массива повторяющиеся элементы, оставив только их первые вхождения.
  • Вставить новый элемент между всеми парами элементов, имеющими разные знаки.
  • Уплотнить массив, удалив из него все нулевые значения.
  • В двумерном массиве, элементы которого - целые числа, произвести следующие действия:
  • Вставить новую строку после строки, в которой находится первый встреченный минимальный элемент.
  • Вставить новый столбец перед всеми столбцами, в которых встречается заданное число.
  • Удалить все строки, в которых нет ни одного четного элемента.
  • Удалить все столбцы, в которых все элементы положительны.
  • Удалить из массива k-тую строку и j-тый столбец, если их значения совпадают.
  • Уплотнить массив, удалив из него все нулевые строки и столбцы.
  • Страницы:

    Массив - набор элементов одного и того же типа, объединенных общим именем. Массивы в С# можно использовать по аналогии с тем, как они используются в других языках программирования. Однако С#-массивы имеют существенные отличия: они относятся к ссылочным типам данных, более того - реализованы как объекты. Фактически имя массива является ссылкой на область кучи (динамической памяти), в которой последовательно размещается набор элементов определенного типа. Выделение памяти под элементы происходит на этапе инициализации массива. А за освобождением памяти следит система сборки мусора - неиспользуемые массивы автоматически утилизируются данной системой.

    Рассмотрим различные типы массивов.

    Одномерные массивы

    Одномерный массив - это фиксированное количество элементов одного и того же типа, объединенных общим именем, где каждый элемент имеет свой номер. Нумерация элементов массива в С# начинается с нуля, то есть, если массив состоит из 10 элементов, то его элементы будут иметь следующие номера: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9.

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

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

    Форма записи Пояснения
    базовый_тип [] имя__массива;
    Например:
    int [] a;
    Описана ссылка на одномерный массив, которая в дальнейшем может быть использована:
  • для адресации на уже существующий массив;
  • передачи массива в метод в качестве параметра
  • отсроченного выделения памяти под элементы массива.
  • базовый_тип [] имя__массива = new базовый_тип [размер];
    Например:
    int []a=new int [10];
    Объявлен одномерный массив заданного типа и выделена память под одномерный массив указанной размерности. Адрес данной области памяти записан в ссылочную переменную. Элементы массива равны нулю.Замечание. Надо отметить, что в C# элементам массива присваиваются начальные значения по умолчанию в зависимости от базового типа. Для арифметических типов - нули, для ссылочных типов - null, для символов - пробел.
    базовый_тип [] имя__массива={список инициализации};
    Например:
    int []a={0, 1, 2, 3};
    Выделена память под одномерный массив, размерность которого соответствует количеству элементов в списке инициализации. Адрес этой области памяти записан в ссылочную переменную. Значение элементов массива соответствует списку инициализации.

    Обращения к элементам массива происходит с помощью индекса, для этого нужно указать имя массива и в квадратных скобках его номер. Например, a[0], b[10], c[i].

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

    Пример 1.

    static void Main()
    {
      int[] myArray = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
      int i;
      for (i = 0; i < 10; ++i)
      Console.WriteLine(myArray[i]);
    }
    Задание. Измените программу так, чтобы числа выводились в строчку.

    Пример 2.

    static void Main()
    {
      int[] myArray = new int[10];
      int i;
      for (i = 0; i < 10; i++)
      myArray[i] = i * i;
      for (i = 0; i < 10; i++)
      Console.WriteLine(myArray[i]);
    }
    Задание. Измените программу так, чтобы обрабатывался массив из n чисел.

    Хотя при инициализации массива нет необходимости использовать операцию new, все же массив можно инициализировать следующим образом:

    int [ ] myArray = new int [ ] { 99, 10, 100, 18, 78, 23, 163, 9, 87, 49 };

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

    static void Main()
    {
      int[] myArray = { 0, 1, 2, 3, 4, 5};
      int i;
      for (i = 0; i < 6; i++)
      Console.Write(" "+myArray[i]);
      Console.WriteLine("\nНовый массив: ");
      myArray = new int[] { 99, 10, 100, 18, 78, 23, 163, 9, 87, 49 }; // 1
      for (i = 0; i < 10; i++)
      Console.Write(" " + myArray[i]);
    }

    Следует отметить, что первоначально переменная myArray ссылалась на 6-ти элементный массив. В строке 1 переменной myArray была присвоена ссылка на новый 10-элементный массив, в результате чего исходный массив оказался неиспользуемым, т.к. на него теперь не ссылается ни один объект. Поэтому он автоматически будет удален сборщиком мусора.

    Массивы и исключения

    Выход за границы массива в C# расценивается как ошибка, в ответ на которую генерируется исключение - IndexOutOfRangeException.

    Рассмотрим следующий пример:

    static void Main()
    {
      int[] myArray = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
      int i;
      try
      {
        for (i = 0; i <= 10; i++) Console.WriteLine(myArray[i]);
      }
      catch (IndexOutOfRangeException)
      {
        Console.WriteLine("Exception: Выход за границу диапазона");
      }
    }
    Задание. Добавьте в программу обработчики исключений FormatException и OutOfMemoryException. Вспомните, что они контролируют.

    Массив как параметр

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

    Рассмотрим пример передачи массива как параметра:

    class Program
    {
      static void Print(int n, int[] a) //n - размерность массива, а - ссылка на массив
      {
        for (int i = 0; i < n; i++) Console.Write("{0} ", a[i]);
        Console.WriteLine();
      }
    
      static void Change(int n, int[] a)
      {
        for (int i = 0; i < n; i++)
        if (a[i] > 0) a[i] = 0; // изменяются элементы массива
      }
    
      static void Main()
      {
        int[] myArray = { 0, -1, -2, 3, 4, 5, -6, -7, 8, -9 };
        Print(10, myArray);
        Change(10, myArray);
        Print(10, myArray);
      }
    }
    Задание. Измените программу так, чтобы метод Change удваивал значения положительных элементов массива.

    Массив как объект

    Мы уже говорили о том, что массивы в С# реализованы как объекты. Если говорить более точно, то они реализованы на основе базового класса Array, определенного в пространстве имен System. Данный класс содержит различные свойства и методы. Например, свойство Length позволяет определять количество элементов в массиве. Преобразуем предыдущий пример:

    class Program
    {
      static void Print(int[] a) // передаем только ссылку на массив
      {
        for (int i = 0; i < a.Length; i++) Console.Write("{0} ", a[i]);
        Console.WriteLine();
      }
    
      static void Change(int[] a)
      {
        for (int i = 0; i < a.Length; i++)
        if (a[i] > 0) a[i] = 0;
      }
    
      static void Main()
      {
        int[] myArray = { 0, -1, -2, 3, 4, 5, -6, -7, 8, -9 };
        Print(myArray);
        Change(myArray);
        Print(myArray);
      }
    }

    Другие свойства и методы класса Array приведены в следующей таблице:

    Элемент Вид Описание
    Length свойство Количество элементов массива (по всем размерностям)
    BinarySearch статический метод Двоичный поиск в отсортированном массиве
    Clear статический метод Присваивание элементам массива значений по умолчанию
    Copy статический метод Копирование заданного диапазона элементов одного массива в другой
    CopyTo экземплярный метод Копирование всех элементов текущего одномерного массива в другой массив
    GetValue экземплярный метод Получение значения элемента массива
    IndexOf статический метод Поиск первого вхождения элемента в одномерный массив
    LastIndexOf статический метод Поиск последнего вхождения элемента в одномерный массив
    Reverse статический метод Изменение порядка следования элементов на обратный
    SetValue экземплярный метод Установка значения элемента массива
    Sort статический метод Упорядочивание элементов одномерного массива

    Вызов статических методов происходит через обращение к имени класса, например, Array.Sort(myArray). В данном случае мы обращаемся к статическому методу Sort класса Array и передаем данному методу в качестве параметра объект myArray - экземпляр класса Array.

    Обращение к свойству или вызов экземплярного метода производится через обращение к экземпляру класса, например, myArray.Length или myArray.GetValue(i).

    Пример:

    class Program
    {
      static void Main()
      {
        try
        {
          int[] MyArray;
          Console.Write("Введите размерность массива: ");
          int n = int.Parse(Console.ReadLine());
          MyArray = new int[n];
          for (int i = 0; i < MyArray.Length; ++i)
          {
            Console.Write("a[{0}]=",i);
            MyArray[i] = int.Parse(Console.ReadLine());
          }
          PrintArray("исходный массив:", MyArray);
          Array.Sort(MyArray);
          PrintArray("массив отсортирован по возрастанию", MyArray);
          Array.Reverse(MyArray);
          PrintArray("массив отсортирован по убыванию", MyArray);
        }
        catch (FormatException)
        {
          Console.WriteLine("неверный формат ввода данных");
        }
        catch (OverflowException)
        {
          Console.WriteLine("переполнение");
        }
        catch (OutOfMemoryException)
        {
          Console.WriteLine("недостаточно памяти для создания нового объекта");
        }
      }
    
      static void PrintArray(string a, int[] mas)
      {
        Console.WriteLine(a);
        for (int i = 0; i < mas.Length; i++) Console.Write("{0} ", mas[i]);
        Console.WriteLine();
      }
    }
    }
    Задание. Добавьте в программу метод InputArray, предназначенный для ввода с клавиатуры элементов массива. Продемонстрируйте работу данного метода.

    Многомерные массивы

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

    Объявить двумерный массив можно одним из предложенных способов:

    тип [,] имя__массива;
    тип [,] имя__массива = new тип [размер1, размер2];
    тип [,] имя__массива={{элементы 1-ой строки}, … , {элементы n-ой строки}};
    тип [,] имя__массива= new тип [,]{{элементы 1-ой строки}, … ,{элементы n-ой строки}};
    строки}};

    Например:

    int [,] a; 
    int [,] a= new int [3, 4];
    int [,] a={{0, 1, 2}, {3, 4, 5}};
    int [,] a= new int [,]{{0, 1, 2}, {3, 4, 5}};
    Замечания.
  • Как и в случае с одномерными массивами, последние два описания являются избыточными.
  • При работе с многомерными массивами можно использовать приемы, которые мы рассмотрели для одномерных массивов.
  • При обращении к свойству Length для двумерного массива мы получим общее количество элементов в массиве. Чтобы получить количество строк нужно обратиться к методу GetLength с параметром 0. Чтобы получить количество столбцов - к методу GetLength с параметром 1.
  • Пример:

    class Program
      {
        static void PrintArray(string a, int[,] mas)
        {
          Console.WriteLine(a);
          for (int i = 0; i < mas.GetLength(0); i++)
          {
            for (int j = 0; j < mas.GetLength(1); j++)
              Console.Write("{0} ", mas[i, j]);
            Console.WriteLine();
          }
        }
    
        static void Change(int[,] mas)
        {
          for (int i = 0; i < mas.GetLength(0); i++)
            for (int j = 0; j < mas.GetLength(1); j++)
              if (mas[i, j] % 2 == 0) mas[i, j] = 0;              
        }
    
        static void Main()
        {
          try
          {
            int[,] MyArray ={ { 1, 2, 3 }, { 4, 5, 6 }, { 7, 8, 9 } };
            PrintArray("исходный массив:", MyArray);
            Change(MyArray);
            PrintArray("итоговый массив", MyArray);
          }
          catch (FormatException)
          {
                Console.WriteLine("неверный формат ввода данных");
          }
          catch (OverflowException)
          {
                Console.WriteLine("переполнение");
          }
          catch (OutOfMemoryException)
          {
                Console.WriteLine("недостаточно памяти для создания нового объекта");
          }
        }
      }
    Задания.
  • Добавьте в программу метод InputArray, предназначенный для ввода с клавиатуры элементов массива. Продемонстрируйте работу данного метода.
  • Измените метод Change так, чтобы он вычислял сумму четных элементов двумерного массива.
  • Ступенчатые массивы

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

    Массив a a[0] a[0][0] a[0][1]
    a[1]
    a[1][0] a[1][1]
    a[n]
    a[n][0] a[n][1]

    Объявление ступенчатого массива:

    тип [][] имя_массива;

    Например:

    int [][]a;

    Фактически мы объявили одномерный массив ссылок на целочисленные одномерные массивы. При таком описании потребуется не только выделять память под одномерный массив ссылок, но и под каждый из целочисленных одномерных массивов. Такое распределение памяти позволяет определять произвольную длину каждой строки массива (отсюда и произошло название массива - ступенчатый). Например:

    int [][] a= new int [3][];  // Создаем три строки
    a[0]=new int [2];  // 0-ая строка ссылается на 2-х элементый одномерный массив 
    a[1]=new int [3];  // 1-ая строка ссылается на 3-х элементый одномерный массив
    a[2]=new int [10];  // 2-ая строка ссылается на 10-ти элементый одномерный массив

    Другой способ выделения памяти:

    int [][] a= {new int [2], new int [3], new int [10]};

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

    Пример:

    class Program
    {
      static void Main()
      {
        try
        {
          int[][] MyArray;
          Console.Write("Ввведите количество строк: ");
          int n = int.Parse(Console.ReadLine());
          MyArray = new int[n][];
          for (int i = 0; i < MyArray.Length; i++)
          {
            Console.Write("введите количество элементов в {0} строке: ", i);
            int j = int.Parse(Console.ReadLine());
            MyArray[i] = new int[j];
            for (j = 0; j < MyArray[i].Length; j++)
            {
              Console.Write("a[{0}][{1}]= ", i, j);
              MyArray[i][j] = int.Parse(Console.ReadLine());
            }
          }
          PrintArray("исходный массив:", MyArray);
          for (int i = 0; i < MyArray.Length; i++) Array.Sort(MyArray[i]);
          PrintArray("измененный массив", MyArray);
        }
        catch (FormatException)
        {
          Console.WriteLine("неверный формат ввода данных");
        }
        catch (OverflowException)
        {
          Console.WriteLine("переполнение");
        }
        catch (OutOfMemoryException)
        {
          Console.WriteLine("недостаточно памяти для создания нового объекта");
        }
      }
    
      static void PrintArray(string a, int[][] mas)
      {
        Console.WriteLine(a);
        for (int i = 0; i < mas.Length; i++)
        {
          for (int j = 0; j < mas[i].Length; j++) Console.Write("{0} ", mas[i][j]);
          Console.WriteLine();
        }
      }
    }
    Задание. Добавьте в программу метод MakeArray, предназначенный для создания ступенчатого массива, в котором количество элементов в каждой строке больше номера строки в два раза. А сам элемент равен сумме номеров строки и столбца, в котором он находится. Продемонстрируйте работу данного метода.

    Оператор foreach и его использование при работе с массивами

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

    foreach (<тип> <имя> in <группа>) <тело цикла>

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

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

    Рассмотрим несколько примеров использования оператора foreach:

  • для работы с одномерными массивами:
    static void PrintArray(string a, int [] mas)
    {
      Console.WriteLine(a);
      foreach (int x in mas)Console.Write("{0} ", x);
      Console.WriteLine();
    }
  • для работы с двумерными массивами:
    static int Sum (int [,] mas)
    {
      int s=0;
      foreach (int x in mas) s += x;
      return s;
    }
  • для работы со ступенчатыми массивами:
    static void PrintArray3(string a, int[][] mas)
    {
      Console.WriteLine(a);
      for (int i = 0; i < mas.Length; i++)
      {
        foreach (int x in mas[i]) Console.Write("{0} ", x);
        Console.WriteLine();
      }
    }
  • Практикум

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

    Пример 1: для одномерного массива

    using System;
    namespace ConsoleApplication2
    {
      class Class
      {
        static int [] Input ()
        {
          Console.WriteLine("введите размерность массива");
          int n=int.Parse(Console.ReadLine());
          int []a=new int[n];
          for (int i = 0; i < n; ++i) 
          {
            Console.Write("a[{0}]= ", i);
            a[i]=int.Parse(Console.ReadLine());
          }
          return a;
        }
    
        static void Print(int[] a) 
        {
          for (int i = 0; i < a.Length; ++i) Console.Write("{0} ", a[i]);
          Console.WriteLine();
        }
    
        static void Change(int[] a)
        {
          for (int i = 0; i < a.Length; ++i)
            if (a[i] > 0) a[i] = -a[i];
        }
    
        static void Main()
        {
          int[] myArray=Input();
    Console.WriteLine("Исходный массив:");
          Print(myArray);
          Change(myArray);
    Console.WriteLine("Измененный массив:");
          Print(myArray);
        }
      }
    }

    Пример 2: для двумерного массива

    using System;
    namespace ConsoleApplication
    {
      class Class
      {
        static int [,] Input (out int n, out int m)
        {
          Console.WriteLine("введите размерность массива");
          Console.Write("n = ");
          n=int.Parse(Console.ReadLine());
          Console.Write("m = ");
          m=int.Parse(Console.ReadLine());
          int [,]a=new int[n, m];
          for (int i = 0; i < n; ++i) 
            for (int j = 0; j < m; ++j)
            {
              Console.Write("a[{0},{1}]= ", i, j);
              a[i, j]=int.Parse(Console.ReadLine());
            }
          return a;
        }
    
        static void Print(int[,] a) 
        {
          for (int i = 0; i < a.GetLength(0); ++i,Console.WriteLine() )
            for (int j = 0; j < a.GetLength(1); ++j)
              Console.Write("{0,5} ", a[i, j]);
        }
    
        static void Change(int[,] a)
        {
          for (int i = 0; i < a.GetLength(0); ++i)
            for (int j = 0; j < a.GetLength(1); ++j)
              if (a[i, j] > 0) a[i, j] = -a[i, j];
        }
    
        static void Main()
        {
          int n,m;
          int[,] myArray=Input(out n, out m);
          Console.WriteLine("Исходный массив:");
          Print(myArray);
          Change(myArray);
          Console.WriteLine("Измененный массив:");
          Print(myArray);
        }
      }
    }
  • Заменить все элементы, меньшие заданного числа, этим числом.
  • Заменить все элементы, попадающие в интервал $$[a, b]$$, нулем.
  • Заменить все отрицательные элементы, не кратные $$3$$, противоположными им числами.
  • Все элементы, меньшие заданного числа, увеличить в два раза.
  • Подсчитать среднее арифметическое элементов.
  • Подсчитать среднее арифметическое отрицательных элементов.
  • Подсчитать количество нечетных элементов.
  • Подсчитать сумму элементов, попадающих в заданный интервал.
  • Подсчитать сумму элементов, кратных 9.
  • Подсчитать количество элементов, не попадающих в заданный интервал.
  • Подсчитать сумму квадратов четных элементов.
  • Вывести на экран номера всех элементов больших заданного числа.
  • Вывести на экран номера всех нечетных элементов.
  • Вывести на экран номера всех элементов, которые не делятся на 7.
  • Вывести на экран номера всех элементов, не попадающих в заданный интервал.
  • Определить, является ли произведение элементов трехзначным числом.
  • Определить, является ли сумма элементов двухзначным числом.
  • Вывести на экран элементы с четными индексами (для двумерного массива - сумма индексов должна быть четной).
  • Вывести на экран положительные элементы с нечетными индексами (для двумерного массива - первый индекс должен быть нечетным).
  • Дана последовательность из n действительных чисел.Замечание. Задачи из данного пункта решить, используя одномерный массив.
  • Подсчитать количество максимальных элементов.

    Пример.

    using System;
    namespace ConsoleApplication
    {
      class Class
      {
        static int [] Input ()
        {
          Console.WriteLine("введите размерность массива");
          int n=int.Parse(Console.ReadLine());
          int []a=new int[n];
          for (int i = 0; i < n; ++i) 
          {
            Console.Write("a[{0}]= ", i);
            a[i]=int.Parse(Console.ReadLine());
          }
          return a;
        }
    
        static int Max(int[] a)
        {
          int max=a[0];
          for (int i = 1; i < a.Length; ++i)
            if (a[i] > max) max=a[i];
          return max;
        }
    
        static void Main()
        {
          int[] myArray=Input();
          int max=Max(myArray);
          int kol=0;
          for (int i=0; i<myArray.Length;++i)
            if (myArray[i]==max)++kol;
          Console.WriteLine("Количество максимальных элементов = "+kol);
        }
      }
    }
  • Вывести на экран номера всех минимальных элементов.
  • Заменить все максимальные элементы нулями.
  • Заменить все минимальные элементы на противоположные.
  • Поменять местами максимальный элемент и первый.
  • Вывести на экран номера всех элементов, не совпадающих с максимальным.
  • Найти номер первого минимального элемента.
  • Найти номер последнего максимального элемента.
  • Подсчитать сумму элементов, расположенных между максимальным и минимальным элементами (минимальный и максимальный элементы в массиве единственные). Если максимальный элемент встречается позже минимального, то выдать сообщение об этом.
  • Найти номер первого максимального элемента.
  • Найти номер последнего минимального элемента.
  • Подсчитать сумму элементов, расположенных между первым максимальным и последним минимальными элементами. Если максимальный элемент встречается позже минимального, то выдать сообщение об этом.
  • Поменять местами первый минимальный и последний максимальный элементы.
  • Найти максимум из отрицательных элементов.
  • Найти минимум из положительных элементов.
  • Найти максимум из модулей элементов.
  • Найти количество пар соседних элементов, разность между которыми равна заданному числу.
  • Подсчитать количество элементов, значения которых больше значения предыдущего элемента.
  • Найти количество пар соседних элементов, в которых предыдущий элемент кратен последующему.
  • Найти количество пар соседних элементов, в которых предыдущий элемент меньше последующего.
  • Дан массив размером nxn, элементы которого целые числа.Замечание. При решении задач из данного пункта использовать двумерный массив.
  • Подсчитать среднее арифметическое нечетных элементов, расположенных выше главной диагонали.

    Пример.

    using System;
    namespace ConsoleApplication
    {
      class Class
      {
        static int [,] Input (out int n)
        {
          Console.WriteLine("введите размерность массива");
          Console.Write("n = ");
          n=int.Parse(Console.ReadLine());
          int [,]a=new int[n, n];
          for (int i = 0; i < n; ++i) 
            for (int j = 0; j < n; ++j)
            {
              Console.Write("a[{0},{1}]= ", i, j);
              a[i, j]=int.Parse(Console.ReadLine());
            }
          return a;
        }
    
        static void Print(int[,] a) 
        {
          for (int i = 0; i < a.GetLength(0); ++i,Console.WriteLine() )
            for (int j = 0; j < a.GetLength(1); ++j)
              Console.Write("{0,5} ", a[i, j]);
        }
    
        static double Rezalt(int[,] a)
        {
          int k=0;
          double s=0;
          for (int i = 0; i < a.GetLength(0); ++i)
            for (int j = i+1; j < a.GetLength(1); ++j)
              if (a[i, j] %2!= 0) {++k; s+=a[i, j];}
          if (k!=0) return s/k;
          else return 0;
        }
    
        static void Main()
        {
          int n;
          int[,] myArray=Input(out n);
          Console.WriteLine("Исходный массив:");
          Print(myArray);
          double rez=Rezalt(myArray);
          Console.WriteLine("Среднее арифметическое ={0:f2}", rez);
        }
      }
    }
  • Подсчитать среднее арифметическое четных элементов, расположенных ниже главной диагонали.
  • Подсчитать сумму элементов, расположенных на побочной диагонали.
  • Подсчитать среднее арифметическое ненулевых элементов, расположенных над побочной диагональю.
  • Подсчитать среднее арифметическое элементов, расположенных под побочной диагональю.
  • Поменять местами столбцы по правилу: первый с последним, второй с предпоследним и т.д.
  • Поменять местами две средних строки, если количество строк четное, и первую со средней строкой, если количество строк нечетное.
  • Поменять местами два средних столбца, если количество столбцов четное, и первый со средним столбцом, если количество столбцов нечетное.
  • Если количество строк в массиве четное, то поменять строки местами по правилу: первую строку со второй, третью - с четвертой и т.д. Если количество строк в массиве нечетное, то оставить массив без изменений.
  • Если количество столбцов в массиве четное, то поменять столбцы местами по правилу: первый столбец со вторым, третий - с четвертым и т.д. Если количество столбцов в массиве нечетное, то оставить массив без изменений.
  • Вычислить $$А^{n}$$, где $$n$$ - натуральное число.
  • Подсчитать норму матрицы по формуле$$||A||=\sum_{i}{\max_j{a_{i,j}}}.$$
  • Подсчитать норму матрицы по формуле$$||A||=\sum_{j}^{}{\max_i{a_{i,j}}}.$$
  • Вывести элементы матрицы в следующем порядке:(рис 8.3) 08_03
  • Выяснить, является ли матрица симметричной относительно главной диагонали.
  • Заполнить матрицу числами от 1 до n (где $$n=m \times k$$, а $$m $$ - количесто строк, а $$k $$ - количество столбцов прямоугольной матрицы) следующим образом:

    (рис 8.4) 08_04

  • Определить, есть ли в данном массиве строка, состоящая только из положительных элементов.
  • Определить, есть ли в данном массиве столбец, состоящий только из отрицательных элементов.
  • В каждой строке найти максимум и заменить его на противоположный элемент.
  • В каждом столбце найти минимум и заменить его нулем.
  • Дан массив размером nxn, элементы которого целые числа.Замечание. Для хранения массив n?n использовать ступенчатый массив.
  • Найти максимальный элемент в каждой строке и записать данные в новый массив.

    Пример

    using System;
    namespace ConsoleApplication
    {
      class Class
      {
        static int [][] Input ()
        {
          Console.WriteLine("введите размерность массива");
          Console.Write("n = ");
          int n=int.Parse(Console.ReadLine());
          int [][]a=new int[n][];
          for (int i = 0; i < n; ++i)
          {
            a[i]=new int [n];
            for (int j = 0; j < n; ++j)
            {
              Console.Write("a[{0},{1}]= ", i, j);
              a[i][j]=int.Parse(Console.ReadLine());
            }
          }
          return a;
        }
    
        static void Print1(int[] a) 
        {
          for (int i = 0; i < a.Length; ++i)
            Console.Write("{0,5} ", a[i]);
        }
    
        static void Print2(int[][] a) 
        {
          for (int i = 0; i < a.Length; ++i,Console.WriteLine() )
            for (int j = 0; j < a[i].Length; ++j)
              Console.Write("{0,5} ", a[i][j]);
        }
    
        static int Max(int[] a)
        {
          int max=a[0];
          for (int i = 1; i < a.Length; ++i)
            
            if (a[i] >max) {max=a[i];}
          return max;
        }
    
        static void Main()
        {
          int[][] myArray=Input();
          Console.WriteLine("Исходный массив:");
          Print2(myArray);
          int[]rez=new int [myArray.Length];
          for (int i=0;i<myArray.Length; ++i)
            rez[i]=Max(myArray[i]);
          Console.WriteLine("Новый массив:");
          Print1(rez);
        }
      }
    }
  • Найти минимальный элемент в каждом столбце и записать данные в новый массив.
  • Четные столбцы таблицы заменить на вектор $$Х$$.
  • Нечетные строки таблицы заменить на вектор $$Х$$.
  • Вычислить $$А*Х$$, где $$А$$ - двумерная матрица, $$X$$ - вектор.
  • Для каждой строки подсчитать количество положительных элементов и записать данные в новый массив.
  • Для каждого столбца подсчитать сумму отрицательных элементов и записать данные в новый массив.
  • Для каждого столбца подсчитать сумму четных положительных элементов и записать данные в новый массив.
  • Для каждой строки подсчитать количество элементов, больших заданного числа, и записать данные в новый массив.
  • Для каждого столбца найти первый положительный элемент и записать данные в новый массив.
  • Для каждой строки найти последний четный элемент и записать данные в новый массив.
  • Для каждого столбца найти номер последнего нечетного элемента и записать данные в новый массив.
  • Для каждой строки найти номер первого отрицательного элемента и записать данные в новый массив.
  • Для каждой строки найти сумму элементов с номерами от $$k1$$ до $$k2 $$ и записать данные в новый массив.
  • Для каждого столбца найти произведение элементов с номерами от $$k1 $$ до $$k2 $$ и записать данные в новый массив.
  • Для каждой строки подсчитать сумму элементов, не попадающих в заданный интервал, и записать данные в новый массив.
  • Подсчитать сумму элементов каждой строки и записать данные в новый массив. Найти максимальный элемент нового массива.
  • Подсчитать произведение элементов каждого столбца и записать данные в новый массив. Найти минимальный элемент нового массива.
  • Для каждой строки найти номер первой пары неравных элементов. Данные записать в новый массив.
  • Для каждого столбца найти номер первой пары одинаковых элементов. Данные записать в новый массив.
  • Самостоятельная работа

    Теоретический материал

    Вставка и удаление элементов в массивах

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

    Замечание. В пространстве имен System.Collection реализована коллекция ArrayList - массив, динамически изменяющий свой размер. Мы будем рассматривать его позже.

    Пример. Рассмотрим фрагмент программы:

    int []a=new int [10];
    int n=5;
    for (int i=0; i<5;i++) a[i]:=i*i;

    В этом случае массив можно представить следующим образом:

    n=5 0 1 2 3 4 5 6 7 8 9
    а 0 1 4 9 16 0 0 0 0 0

    Так как во время описания был определен массив из 10 элементов, а заполнено только первые 5, то оставшиеся элементы будут заполнены нулями.

    Что значит удалить из одномерного массива элемент с номером 3? Удаление должно привести к физическому "уничтожению" элемента с номером 3 из массива, при этом общее количество элементов должно быть уменьшено. В этом понимании удаления элемента итоговый массив должен выглядеть следующем образом

    0 1 2 4 5 6 7 8 9 недопустимое состояние
    а 0 1 4 16 0 0 0 0 0

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

    Однако "удаление" можно смоделировать сдвигом элементов влево и уменьшением значения переменной, которая отвечает за текущее количество элементов в массиве, на единицу:

    n=4 0 1 2 3 4 5 6 7 8 9
    а 0 1 4 16 0 0 0 0 0 0

    В общем случае, если мы хотим удалить элемент массива с номером k (всего в массиве n элементов, а последний элемент имеет индекс n-1 ), то нам необходимо произвести сдвиг элементов, начиная с k+1 -го на одну позицию влево. Т.е. на k -ое место поставить k+1 -й элемент, на место k+1 - k+2 -й элемент, …, на место n-2 - n-1 -й элемент. После чего значение n уменьшить на 1. В этом случае размерность массива не изменится, изменится лишь текущее количество элементов, и у нас создастся ощущение, что элемент с номером k удален. Рассмотрим данный алгоритм на примере:

    using System;
    namespace ConsoleApplication
    {
      class Class
      {
        static int [] Input ()
        {
          Console.WriteLine("введите размерность массива");
          int n=int.Parse(Console.ReadLine());
          int []a=new int[n];
          for (int i = 0; i < n; ++i) 
          {
            Console.Write("a[{0}]= ", i);
            a[i]=int.Parse(Console.ReadLine());
          }
          return a;
        }
    
        static void Print(int[] a, int n) 
        {
          for (int i = 0; i < n; ++i) Console.Write("{0} ", a[i]);
          Console.WriteLine();
        }
    
        static void DeleteArray(int[] a, ref int n, int m)
        {
          for (int i = m; i < n-1; ++i)
            a[i] = a[i+1];
          --n;
        }
    
        static void Main()
        {
          int[] myArray=Input();
          int n=myArray.Length;
          Console.WriteLine("Исходный массив:");
          Print(myArray, n);
          Console.WriteLine("Введите номер элемента для удаления:");
          int m=int.Parse(Console.ReadLine());
    DeleteArray(myArray, ref n,m);
          Console.WriteLine("Измененный массив:");
          Print(myArray, n);
        }
      }
    }
    Задание. Подумайте, какие исключительные ситуации могут возникнуть в данной программе и добавьте в нее соответствующие обработки исключительных ситуаций

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

    using System;
    namespace ConsoleApplication
    {
      class Class
      {
        static int [,] Input (out int n, out int m)
        {
          Console.WriteLine("введите размерность массива");
          Console.Write("n = ");
          n=int.Parse(Console.ReadLine());
          Console.Write("m = ");
          m=int.Parse(Console.ReadLine());
          int [,]a=new int[n, m];
          for (int i = 0; i < n; ++i) 
            for (int j = 0; j < m; ++j)
            {
              Console.Write("a[{0},{1}]= ", i, j);
              a[i, j]=int.Parse(Console.ReadLine());
            }
          return a;
        }
    
        static void Print(int[,] a, int n, int m) 
        {
          for (int i = 0; i < n; ++i,Console.WriteLine() )
            for (int j = 0; j < m; ++j)
              Console.Write("{0,5} ", a[i, j]);
        }
    
        static void DeleteArray(int[,] a, ref int n, int m, int k)
        {
          for (int i = k; i < n-1; ++i)
            for (int j = 0; j < m; ++j)
              a[i, j] = a[i+1, j];
          --n;
        }
    
        static void Main()
        {
          int n,m;
          int[,] myArray=Input(out n, out m);
          Console.WriteLine("Исходный массив:");
          Print(myArray, n, m);
          Console.WriteLine("Введите номер строки для удаления:");
          int k=int.Parse(Console.ReadLine());
          DeleteArray(myArray, ref n, m, k);
          Console.WriteLine("Измененный массив:");
          Print(myArray, n, m);
        }
      }
    }
    Задания.
  • Подумайте, какие исключительные ситуации могут возникнуть в данной программе и добавьте в нее соответствующие обработки исключительных ситуаций.
  • Измените программу так, чтобы она удаляла k -тый столбец в двумерном массиве.
  • Рассмотрим модификацию предыдущей программы, для случая, когда используется ступенчатый массив.

    using System;
    namespace ConsoleApplication
    {
      class Class
      {
        
        static int [][] Input (out int n, out int m)
        {
          Console.WriteLine("введите размерность массива");
          Console.Write("n = ");
          n=int.Parse(Console.ReadLine());
          Console.Write("m = ");
          m=int.Parse(Console.ReadLine());
          int [] []a=new int[n][];
          for (int i = 0; i < n; ++i)
          {
            a[i]=new int[m];
            for (int j = 0; j < m; ++j)
            {
              Console.Write("a[{0},{1}]= ", i, j);
              a[i][j]=int.Parse(Console.ReadLine());
            }
          }
          return a;
        }
    
        static void Print(int[][] a, int n, int m) 
        {
          for (int i = 0; i < n; ++i,Console.WriteLine() )
            for (int j = 0; j < m; ++j)
              Console.Write("{0,5} ", a[i] [j]);
        }
    
        static void DeleteArray(int[][] a, ref int n, int k)
        {
          for (int i = k; i < n-1; ++i)//производим сдвиг ссылок
            a[i] = a[i+1];
          --n;
        }
    
        static void Main()
        {
          int n,m;
          int[][] myArray=Input(out n, out m);
          Console.WriteLine("Исходный массив:");
          Print(myArray, n, m);
          Console.WriteLine("Введите номер строки для удаления:");
          int k=int.Parse(Console.ReadLine());
          DeleteArray(myArray, ref n, k);
          Console.WriteLine("Измененный массив:");
          Print(myArray, n, m);
        }
      }
    }

    Вернемся к массиву, определенному в самом первом примере. И подумаем теперь, что значит добавить элемент в одномерный массив в позицию с номером k? В этом случае все элементы, начиная с k -ого, должны быть сдвинуты вправо на одну позицию. Однако сдвиг нужно начинать с конца, т.е. на первом шаге на n -е место поставить n-1 -ый элемент, потом на n-1 -ое место поставить n-2 -й элемент, …, наконец, на k+ 1 место вставить k-й элемент. Таким образом, копия k -го элемента будет на k+1 -м месте и на k -е место можно поставить новый элемент. Затем необходимо увеличить текущее количество элементов на 1.

    Рассмотрим массив из примера 1 и в качестве k зададим значение равное 3. В этом случае массив будет выглядеть следующим образом:

    k=3 0 1 2 3 4 5 6 7 8 9
    а 0 1 4 9 9 16 0 0 0 0

    Теперь в позицию с номером 3 можно поместить новое значение. А текущее количество элементов в массиве становится равным 6. Подумайте, почему сдвиг нужно выполнять с конца массива, а не с начала, как мы это делали в случае удаления элемента из массива.

    Рассмотрим программную реализацию данного алгоритма:

    using System;
    namespace ConsoleApplication
    {
      class Class
      {
        static int [] Input (out int n)
        {
          Console.WriteLine("введите размерность массива");
          n=int.Parse(Console.ReadLine());
          int []a=new int[2*n]; //выделяем памяти больше чем требуется
          for (int i = 0; i < n; ++i) 
          {
            Console.Write("a[{0}]= ", i);
            a[i]=int.Parse(Console.ReadLine());
          }
          return a;
        }
    
        static void Print(int[] a, int n) 
        {
          for (int i = 0; i < n; ++i) Console.Write("{0} ", a[i]);
          Console.WriteLine();
        }
    
        static void AddArray(int[] a, ref int n, int m)
        {
          for (int i = n; i >= m; --i)
            a[i] = a[i-1];
          ++n;
          Console.WriteLine("Введите значение нового элемента");
          a[m]=int.Parse(Console.ReadLine());
        }
    
        static void Main()
        {
          int n;
          int[] myArray=Input(out n);
          Console.WriteLine("Исходный массив:");
          Print(myArray, n);
          Console.WriteLine("Введите номер элемента для вставки:");
          int m=int.Parse(Console.ReadLine());
          AddArray(myArray, ref n,m);
          Console.WriteLine("Измененный массив:");
          Print(myArray, n);
        }
      }
    }

    Теперь рассмотрим добавление строки в двумерный массив. Для этого все строки после строки с номером k передвигаем на 1 строку вниз. Затем увеличиваем количество строк на 1. После этого копия строки с номером k будет находиться в столбце с номером k+1. И, следовательно, k -тый столбец можно заполнить новыми значениями. Рассмотрим программную реализацию алгоритма:

    using System;
    namespace ConsoleApplication
    {
      class Class
      {
        
        static int [,] Input (out int n, out int m)
        {
          Console.WriteLine("введите размерность массива");
          Console.Write("n = ");
          n=int.Parse(Console.ReadLine());
          Console.Write("m = ");
          m=int.Parse(Console.ReadLine());
    //выделяем памяти больше чем необходимо
          int [,]a=new int[2*n, m]; 
          for (int i = 0; i < n; ++i) 
            for (int j = 0; j < m; ++j)
            {
              Console.Write("a[{0},{1}]= ", i, j);
              a[i, j]=int.Parse(Console.ReadLine());
            }
          return a;
        }
    
    
        static void Print(int[,] a, int n, int m) 
        {
          for (int i = 0; i < n; ++i,Console.WriteLine() )
            for (int j = 0; j < m; ++j)
              Console.Write("{0,5} ", a[i, j]);
        }
    
        static void AddArray(int[,] a, ref int n, int m, int k)
        {
          for (int i = n; i >=k; --i)
            for (int j = 0; j < m; ++j)
              a[i+1, j] = a[i, j];
          ++n;
          Console.WriteLine("Введите элементы новой строки");
          for (int j=0; j<m;++j)
          {
            Console.Write("a[{0},{1}]=", k, j);
            a[k, j]=int.Parse(Console.ReadLine());
          }
        }
    
        static void Main()
        {
          int n,m;
          int[,] myArray=Input(out n, out m);
          Console.WriteLine("Исходный массив:");
          Print(myArray, n, m);
          Console.WriteLine("Введите номер строки для добавления:");
          int k=int.Parse(Console.ReadLine());
          AddArray(myArray, ref n, m, k);
          Console.WriteLine("Измененный массив:");
          Print(myArray, n, m);
        }
      }
    }
    Задания.
  • Подумайте, какие исключительные ситуации могут возникнуть в данной программе и добавьте в нее соответствующие обработки исключительных ситуаций.
  • Измените программу так, чтобы она добавляла k -тый столбец в двумерном массиве.
  • Рассмотрим модификацию предыдущей программы для случая, когда используется ступенчатый массив.

    using System;
    namespace ConsoleApplication
    {
      class Class
      {
        
        static int [][] Input (out int n, out int m)
        {
          Console.WriteLine("введите размерность массива");
          Console.Write("n = ");
          n=int.Parse(Console.ReadLine());
          Console.Write("m = ");
          m=int.Parse(Console.ReadLine());
    //выделяем памяти больше чем неообходимо
          int [][]a=new int[2*n][]; 
          for (int i = 0; i < n; ++i)
          {
            a[i]=new int [m];
            for (int j = 0; j < m; ++j)
            {
              Console.Write("a[{0}][{1}]= ", i, j);
              a[i][j]=int.Parse(Console.ReadLine());
            }
          }
          return a;
        }
    
        static void Print(int[][] a, int n, int m) 
        {
          for (int i = 0; i < n; ++i,Console.WriteLine() )
            for (int j = 0; j < m; ++j)
              Console.Write("{0,5} ", a[i][j]);
        }
    
        static void AddArray(int[][] a, ref int n, int m, int k)
        {
          for (int i = n; i >=k; --i)//выполняем сдвиг ссылок
            a[i+1] = a[i];
          ++n;
          a[k]=new int[m]; //создаем новую строку
          Console.WriteLine("Введите элементы новой строки");
          for (int j=0; j<m;++j)
          {
            Console.Write("a[{0}][{1}]=", k, j);
            a[k][j]=int.Parse(Console.ReadLine());
          }
        }
    
        static void Main()
        {
          int n,m;
          int[][] myArray=Input(out n, out m);
          Console.WriteLine("Исходный массив:");
          Print(myArray, n, m);
          Console.WriteLine("Введите номер строки для добавления:");
          int k=int.Parse(Console.ReadLine());
          AddArray(myArray, ref n, m, k);
          Console.WriteLine("Измененный массив:");
          Print(myArray, n, m);
        }
      }
    }

    Практические задания

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