Методы заполнения двумерных массивов в windows form

Урок и задания по теме программирование с двумерными массивами в c# (sharp)

Лабораторные работы си шарп и задания по теме «Язык программирования c sharp: двумерные массивы»

Содержание:

  • Теория
  • Задания и лабораторные работы
    • Дополнительные задания

Теория

    В примере ниже показан код для объявления двумерного массива из пяти строк и трех столбцов (5 х 3).

  • Объявление массива:
  • int[,] arr = new int[5, 3];
  • Инициализация массива значениями:
  • // 1. Инициализация массива при объявлении:
    int[,] arr1 = new int[,] { { 1, 2 }, { 3, 4 }, { 5, 6 }, { 7, 8 } };
    // Тот же массив с заданными размерами:
    int[,] arr1 = new int[4, 2] { { 1, 2 }, { 3, 4 }, { 5, 6 }, { 7, 8 } };
     
    // 2. Инициализация массива без указания размерности:
    int[,] arr2 = { { 1, 2 }, { 3, 4 }, { 5, 6 }, { 7, 8 } };
     
    // 3. Инициализация массива после его объявления:
    int[,] arr;
    arr = new int[,] { { 1, 2 }, { 3, 4 }, { 5, 6 }, { 7, 8 } };
     
    // Присваивание значения конкретному элементу массива:
    arr[2, 1] = 25;
  • Доступ к элементам массива:
  • int[,] arr1 = new int[,] { { 1, 2 }, { 3, 4 }, { 5, 6 }, { 7, 8 } };
    System.Console.WriteLine(arr1[0, 0]); //1
    System.Console.WriteLine(arr1[0, 1]); //2
    System.Console.WriteLine(arr1[1, 0]); //3
    System.Console.WriteLine(arr1[1, 1]); //4
    System.Console.WriteLine(arr1[3, 0]); //7
  • Получение значения определенного элемента массива и присвоение его переменной:
  • int elementValue = arr1[2, 1];
  • Получение общего количества элементов (или размерности массива):
  • int[,] arr = new int[,] { { 1, 2 }, { 3, 4 }, { 5, 6 }, { 7, 8 } };
    var arrayLength = arr.Length;
    var total = 1;
    for (int i = 0; i < arr.Rank; i++) {
        total *= arr.GetLength(i);
    }
    System.Console.WriteLine("{0} равно {1}", arrayLength, total); // 8 равно 8
  • Получение количества строк и столбцов:
  • int[,] matrix = new int[,] { { 1, 2 }, { 3, 4 }, { 5, 6 }, { 7, 8 } };
    int r=matrix.GetLength(0); // строки
    int c=matrix.GetLength(1); // столбцы

Задания и лабораторные работы

Лабораторная работа 1.

  
Выполнить: Инициализируйте двумерный массив* с именем arr2d заданными целочисленными значениями: ((1, 2); (3, 4); (5, 6)).
1) Сначала выведите все элементы массива.
2) После этого выведите следующие элементы в консоль (элементы для вывода отмечены синим цветом):

(1, 2)
(3, 4) 
(5, 6)

* Двумерный массив может называться матрицей.

Пример выполнения:

Массив:
1  2
3  4
5  6
1-й элемент = 3, 2-й элемент = 5

[Название проекта: Lesson_10Lab1, название файла L10Lab1.cs]

✍ Алгоритм:

  • Создайте новый проект с именем файла, как указано в задаче.
  • Подключите следующую библиотеку, чтобы не печатать каждый раз название класса console:
  • using static System.Console;
    
  • Чтобы объявить двумерный массив целочисленного типа с именем arr2d, мы можем использовать оператор int[,] arr2;. Сразу в этой же строке инициализируем массив значениями. Для этого добавьте следующий код в функцию Main:
  • int[,] arr2d= { {1, 2}, {3, 4}, {5, 6} };
    

    Теперь у нас есть двумерный массив со значениями.

  • Чтобы вывести все элементы массива, мы должны использовать вложенные циклы; внешний цикл должен перебирать строки, а внутренний цикл должен перебирать элементы в каждой строке. Внутри внутреннего цикла будем выводить значения элементов. Чтобы получить доступ к каждому элементу по его индексу, необходимо использовать счетчики цикла в качестве индексов элемента:
  • for (int i = 0; i < arr2d.GetLength(0); i++)
                {
                    for (int j = 0; j < arr2d.GetLength(1); j++)
                    {
                        Console.Write($"{arr2d[i, j]}  ");
                    }
                    Console.WriteLine();
                }
    

    Чтобы вывести значение конкретного элемента в окно консоли, нам нужно понять, в какой строке и столбце находится элемент. Обратите внимание, что индексы начинаются со значения 0. Итак, к элементу со значением 3 можно получить доступ как arr2[1,0] (где 1 — строка и 0 — столбец), а к элементу со значением 5 можно получить доступ так: arr2[2,0].

  • Вывод элементов:
  • Console.WriteLine($"1-й элемент = {arr2d[1,0]}, 2-й элемент = {arr2d[2, 0]}");
    
  • Запустите приложение еще раз и проверьте выходные данные.
  • Поэкспериментируйте с различными значениями.
  • Добавьте комментарий с текстом задачи и сохраните проект.

Задание 1:
Приведены значения температуры воздуха за 4 дня; значения взяты с трех метеостанций, расположенных в разных регионах страны:

Station number 1-й день 2-й день 3-й день 4-й день
1 -8 -14 -19 -18
2 25 28 26 20
3 11 18 20 25

То есть в двумерном массиве это выглядело бы так:

t[0,0]=-8; t[0,1]=-14; t[0,2]=-19; t[0,3]=-18;
t[1,0]=25; t[1,1]=28; t[1,2]=26; t[1,3]=20;
t[2,0]=11; t[2,1]=18; t[2,2]=20; t[2,3]=25;

  
Указание: Инициализация массива:

 int [,] t = {
                {-8,-14,-19,-18},
                { 25,28, 26, 20},
                { 11,18, 20, 25}
                };

Выполнить:

  1. Выведите значение температуры на 2-й метеостанции в течение 4-го дня и на 3-й метеостанции в течение 1-го дня (результат должен быть 20 и 11).
  2. Выведите значения температуры всех метеостанций в течение 2-го дня (необходим for цикла).
  3. Выведите значения температуры всех метеостанций в течение всех дней.
  4. Рассчитайте среднюю температуру на 3-й метеостанции (необходим for цикла).
  5. Выведите дни и номера метеостанций, где температура была в диапазоне 2426 градусов.

  
Пример вывода:

1-е задание: 20  and  11
2-е задание: 25 28 26 20
3-е задание:
-8  -14  -19  -18
25   28   26   20
11   18   20   25

4-е задание: 18
5-е задание:
станция 1  день 0
станция 1  день 2
станция 2  день 3
     
[Название проекта: Lesson_10Task1, название файла L10Task1.cs]

Задание 2:

To do: Вводятся элементы двумерного массива 2 х 3 ([2,3]). Посчитайте сумму элементов.

   
Указание 1: Для объявления массива размерностью 2 х 3 используйте код: 

int[,] arr=new int[2, 3];

 
Указание 2: Для ввода значений элементов массива и перебора элементов, воспользуйтесь вложенными циклами:

for (int i = 0; i < 2; i++)
            {
                for (int j = 0; j < 3; j++)
                {
                   ...
                }
            }

  
Пример вывода:

Введите 6 значений для матрицы 2 х 3
2
5
1
6
7
8
Матрица:
2  5  1
6  7  8
Сумма =  29

[Название проекта: Lesson_10Task2, название файла L10Task2.cs]

Задание 3:

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

 
Пример вывода:

Пожалуйста, введите значения матрицы 4 х 3
2  5  -1  6  7  8  1  8  6  -3  1  -6
Матрица:
2   5  -1
6   7   8
1   8   6
-3  1  -6
кол-во положительных = 9

[Название проекта: Lesson_10Task3, название файла L10Task3.cs]

Лабораторная работа 2. Использование функции Random

Выполнить: Создайте метод FillMatrix для заполнения двумерного массива случайными числами в диапазоне от -10 до 10.

Указание: Заголовок функции FillMatrix должен быть таким:

FillMatrix(matrix, minValue, maxValue);

Пример выполнения:

Введите кол-во строк:
3
Введите кол-во столбцов:
4
Массив:
-10 -7 -3 -4
-6   1  4  0
-5  -8 -1 -5

[Название проекта: Lesson_10Lab2, название файла L10Lab2.cs]

✍ Алгоритм:

  • Создайте новый проект с названием файла, которое указано в задании.
  • Подключите следующую библиотеку чтобы не указывать название класса console:
  • using static System.Console;
    
  • В функции Main добавьте код для того, чтобы попросить пользователя ввести количество строк и количество столбцов матрицы. Присвойте введенные значения переменным:
  • ...
    Console.WriteLine("введите кол-во строк");
    int rows = int.Parse(ReadLine());
    Console.WriteLine("введите кол-во столбцов");
    int columns = int.Parse(ReadLine());
    
  • Объявите матрицу:
  • int[,] matrix = new int[rows,columns];
    
  • Инициализируйте значениями переменные для границ генерируемого диапазона:
  •   int minValue=-10;
      int maxValue=10;
    

    Чтобы сделать программу более эффективной лучше использовать ReSharper (для инициализации метода):

  • Вызовите метод FillMatrix в коде функции Main (несмотря на то, что мы еще ее не создали). В функцию Main() введите следующий код:
  • FillMatrix(matrix, minValue, maxValue);
    
  • Название функции подчеркнуто. Если поднести курсор мыши, вы увидите изображение с желтой лампочкой. Значит, мы можем использовать ReSharper comments, щелкнув по лампочке (или Alt+Enter). Следует выбрать пункт «Генерировать метод Program.FillMatrix».
  • Заголовок функции есть в задании.
  • Change the code:
  • FillMatrix(int[,] matrix, int minValue = -10, int maxValue = 10); 
    
  • Метод с тремя параметрами:
  • matrix — a declared matrix without initialization;
    minValue -устанавливать нижнюю границу для функции Random, значение по умолчанию — -10
    maxValue — устанавливать верхнюю границу для функции Random, значение по умолчанию 10

  • Внутри созданной функции установите генератор случайных чисел:
  • Random rand = new Random();
    
  • Сгенерируйте значения для матрицы и присвойте их элементам (границы генерируемых чисел: от minValue до maxValue):
  • ...
    for (int i = 0; i < matrix.GetLength(0); i++)
                {
                    for (int j = 0; j < matrix.GetLength(1); j++)
                    {
                        matrix[i, j] = rand.Next(minValue, maxValue);
                        Write(matrix[i, j].ToString().PadLeft(4));
                    }
                    WriteLine();
                }
    

    Обратите внимание, что matrix.GetLength(0) означает число столбцов, а matrix.GetLength(1)означает число столбцов.

    Для прохода по элементам матрицы необходимо использовать вложенный цикл. Счетчики циклов должны быть разными переменными, можно использовать для их названий i и j. Метод GetLength(0) возвращает кол-во строк матрицы, метод GetLength(1) возвращает кол-во столбцов.

  • Щелкните CTRL+a, CTRL+k, CTRL+F для форматирования вашего кода.
  • Запустите программу.
  • Добавьте комментарии. Загрузите файл L10Lab2.cs.

Задание 4:

Выполнить: Создайте метод FillMatrix для заполнения двумерного массива случайными числами от -15 до 15. Создайте еще один метод для нахождения минимального и максимального элементов массива (FindMinMaxArr).

   
Указание 1: Сигнатура (заголовок) метода FindMinMaxArr должен быть таким: 

private static void FindMinMaxArr(int[,] matrix, ref int min, ref int max)

  
Указание 2: Алгоритм поиска минимального и максимального элемента можно посмотреть в одном из прошлых уроков Урок 5 -> Лаб. раб. 4.

  
Пример вывода:

введите кол-во строк
4
введите кол-во столбцов
5
Массив:
10   2   9  3  4
-3 -10 -14 -4  2
 2  -9  11  3 -10
-1 -13  -5 -2  3
min = -14, max = 11

[Название проекта: Lesson_10Task4, название файла L10Task4.cs]

Лабораторная работа 3. Обмен определенных столбцов матрицы

Выполнить: Создайте метод ChangeColumns для обмена определенных столбцов матрицы размера 3 х 4 (порядковые номера столбцов вводятся).

Указание: Помимо метода ChangeColumns необходимо создать метод FillMatrix для заполнения матрицы случайными числами, и метод PrintMatrix для вывода элементов матрицы.

Пример вывода:

Матрица:
-10 -7 -3 -4
-6   1  4  0
-5  -8 -1 -5
введите номера столбцов для обмена (первый столбец - 0-й):
1
2
Результирующая матрица:
-10 -3 -7 -4
-6   4  1  0
-5  -1 -8 -5

[Название проекта: Lesson_10Lab3, название файла L10Lab3.cs]

✍ Fkujhbnv:

  • Создайте новый проект и переименуйте главный файл согласно заданию.
  • Необходимо создать матрицу с тремя строками и четырьмя столбцами. Объявите матрицу в функции Main:
  • int[,] matrix = new int[3, 4];
  • Скопируйте код метода FillMatrix из Лабораторной работы 2 и вставьте его в текущий проект. Или создайте метод заново. После этого у Вас будет код:
  • static void FillMatrix(int[,] matrix, int minValue = -10, int maxValue = 10) {
                Random rand = new Random();
                for (int i = 0; i < matrix.GetLength(0); i++)
                {
                    for (int j = 0; j < matrix.GetLength(1); j++)
                    {
                        matrix[i, j] = rand.Next(minValue, maxValue);
                     }
                }
            }
    
  • Создайте метод PrintMatrix для вывода элементов матрицы. Метод принимает один параметр — саму матрицу:
  • static void PrintMatrix(int[,] m)
            {
                for (int i = 0; i < m.GetLength(0); i++)
                {
                    for (int j = 0; j < m.GetLength(1); j++)
                    {
                       Console.Write(m[i, j].ToString().PadLeft(4));
                    }
                    Console.WriteLine();
                }
            }
    

    Чтобы выводить элементы с одинаковыми отступами построчно мы конвертировали их в строкой тип данных и использовали метод PadLeft для формирования одинаковых отступов слева.

  • Затем в функции Main необходимо вызвать созданные методы: сначала — метод FillMatrix и затем — метод PrintMatrix.
  • ...
    FillMatrix(matrix);
    Console.WriteLine("Матрица 3 x 4: ");
    PrintMatrix(matrix);
    
  • Затем необходимо ввести номера столбцов для обмена:
  • ...
    Console.WriteLine("введите номера столбцов для обмена (первый столбец - 0-й):");
    int col1= int.Parse(Console.ReadLine());
    int col2 = int.Parse(Console.ReadLine());
    
  • Создайте метод ChangeColumns для обмена столбцов с указанными номерами:
  • static void ChangeColumns(int[,] matrix, int col1, int col2)
            {
                System.Diagnostics.Debug.Assert((col1 < matrix.GetLength(1)) && (col2 < matrix.GetLength(1)), "указанный номер столбца выходит за границы размерности массива!");
                for (int i = 0; i < matrix.GetLength(0); i++)
                {
                    int temp = matrix[i, col1];
                    matrix[i, col1] = matrix[i, col2];
                    matrix[i, col2] = temp;
                   // если используется Visual studio 2019:
                   // (matrix[i, col1], matrix[i, col2]) = (matrix[i, col2], matrix[i, col1]);
                }
            }
    

    Счетчик i цикла проходится по строкам матрицы и в то же время каждый элемент col1 обменивается значениями с элементом col2 в каждой строке.

    System.Diagnostics.Debug.Assert используется для того, чтобы вызвать исключение при вводе значения большего, чем кол-во столбцов матрицы.

  • Вызовите метод в функции main. Затем вызовите метод PrintMatrix , чтобы увидеть результат:
  • ...
    ChangeColumns(matrix, col1, col2);
    Console.WriteLine("The resulting matrix:");
    PrintMatrix(matrix);
    
  • Запустите программу, нажав горячие клавиши CTRL+F5.
  • Загрузите файл L10Lab3.cs.

Задание 5:

To do: Создайте метод PlaceZero, который замещает некоторые элементы матрицы (5 х 5) нулями (0). Посмотрите на пример вывода, чтобы понять, какие элементы должны быть замещены нулями.

   
Указание 1: Создайте методы для заполнения и вывода матрицы.
Указание 2: Заголовок метода PlaceZero должен быть следующим: 

static void PlaceZero(int[,] matrix)
  

Указание 3: Для замены элементов нулями используйте циклы.

  
Пример вывода:

Матрица:
10 2  9  3  6 
3  10 14 4  8
2  9  11 3  2
1  13 5  2  7
12 3  11 4  5

Результирующая матрица:
0  0  0  0  0 
0  10 14 4  0
0  9  11 3  0
0  13 5  2  0
0  0  0  0  0

[Название проекта: Lesson_10Task5, название файла L10Task5.cs]

Задание 6:

To do: Создайте метод FindProductOfColumn для нахождения произведения элементов матрицы M-го столбца (матрица 3 х 4) (M вводится). M — это параметр out (вывода).

Note: Сигнатура метода FindProductOfColumn должна быть следующей:

static void FindProductOfColumn(int[,] matrix, int M,out int product)

Пример вывода:

Матрица:
-10 -3 -7 -4
-6   4  1  0
-5  -1 -8 -5
Введите номер столбца (первый столбец - 0-й):
2
Произведение элементов 2-го столбца = -64

[Название проекта: Lesson_10Task6, название файла L10Task6.cs]

Главная и побочная диагонали

  
В алгебре главная диагональ матрицы A — это все элементы матрицы Ai,j , для которых i=j. Элементы вне главной диагонали обозначены нулями, а элементы главной диагонали обозначены красными единицами:

Побочная диагональ матрицы B размерности N — это элементы Bi,j, для которых i+j=N+1 для всех 1<=i,j<=N. Но если i и j начинаются с нуля, то формула будет i+j=N-1:

Лабораторная работа 4. Работа с диагоналями матрицы

Выполнить: Создайте квадратную матрицу M-х-M (значение M вводится). Посчитайте сумму элементов побочной диагонали матрицы.

Примерный вывод:

Введите размерность матрицы:
3 
Матрица 3-х-3:
10 -7 -3 
6   1  4 
5  -8 -1 
сумма элементов побочной диагонали = 3

[Название проекта: Lesson_10Lab4, название файла L10Lab4.cs]

✍ Алгоритм:

  • Создайте новый проект и измените название главного файла согласно заданию.
  • Попросите пользователя ввести размерность матрицы и присвойте введенное значение переменной M:
  • Console.WriteLine("Введите размерность матрицы:");
    int M = int.Parse(Console.ReadLine());
    
  • Мы собираемся создать матрицу размерностью M-х-M. Объявите матрицу в коде функции Main:
  • int[,] matrix = new int[M, M];
    
  • Скопируйте код метода FillMatrix с предыдущей лабораторной работы и вставьте его до или после функции Main.
  • Скопируйте код метода PrintMatrix и также вставьте его после метода FillMatrix.
  • Создайте метод AntidiagonalSum, который будет суммировать элементы побочной диагонали матрицы.
  • static int AntidiagonalSum(int[,] matrix) 
    {
    ...
    }
    
  • Вспомним, что для индексов элементов побочной диагонали следует использовать формулу: i+j=M-1. Для прохода по элементам матрицы будем использовать вложенные циклы:
  • ...
    int sum = 0;
    for (int i = 0; i < matrix.GetLength(0); i++)
                {
                    for (int j = 0; j < matrix.GetLength(1); j++)
                    {
                        if ((i+j == M-1)
                           {
                             sum+ = matrix[i,j];
                           }
                     }
                }
    
  • Метод должен возвратить значение суммы, поэтому будем использовать ключевое слово return:
  • ...
    return sum;
    
  • Вызовите метод внутри функции Main:
  • int result = AntidiagonalSum(matrix);
    Console.WriteLine($"сумма элементов побочной диагонали = {result}");
    
  • Запустите программу без отладки (CTRL+F5) и проверьте результат.
  • Добавьте комментарий с заданием и загрузите главный файл.

Задание 7:

Выполнить: Create square matrix M-by-M (M is inputted). Calculate a product of its elements within a main diagonal.

Указание: a main diagonal elements are such as i=j.

Примерный вывод:

Введите размерность матрицы:
3 
Матрица 3-х-3:
10 -7 -3 
6   1  4 
5  -8 -1 
Произведение элементов главной диагонали = -10

[Название проекта: Lesson_10Task7, название файла L10Task7.cs]

Дополнительные задания

Доп. задание 1:

Выполнить: Запрашиваются натуральные M и N. Создайте метод FillMatrix для заполнения матрицы размерностью M-х-N; все элементы J-го столбца вычисляются по формуле X*J (J — номер столбца, J = 1, …, N), а X — число — аргумент метода.

  
Указание: заголовок метода должен быть следующим:

static int[,] FillMatrix(int M, int N, int X)

Примерный вывод:

введите кол-во строк:
3
введите кол-во столбцов:
4
Введите значение множителя (аргумента):
3 
Матрица 3-х-3:
3 6 9 12
3 6 9 12
3 6 9 12 

 
[Название проекта: Lesson_10ExTask1, название файла L10ExTask1.cs]

Доп. задание 2:

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

  
Указание: Заголовок метода:

static int[,] SumMat(int[,] a, int[,] b)

Примерный вывод:

Matrix 1:
-3 8 3
-9 -6 4
6 4 -2
Matrix 2:
4 -4 1
-5 1 -1
4 8 -10
Result matrix:
1 4 4
-14 -5 3
10 12 -12

 
[Название проекта: Lesson_10ExTask2, название файла L10ExTask2.cs]

Часто в задачах нужно ввести числа или другие данные в двумерный массив (матрицу) и иметь возможность их обрабатывать.

В работе реализован аналог компонента TStringGrid используемого в Delphi для представления данных в виде двумерной таблицы строк. Для этого в C# используется двумерный массив элементов управления типа TextBox.


Содержание

  • Условие задачи
  • Выполнение
    • 1. Запуск Microsoft Visual Studio. Создание проекта
    • 2. Создание главной формы Form1
    • 3. Создание второстепенной формы Form2
    • 4. Ввод внутренних переменных
    • 5. Программирование события Load формы Form1
    • 6. Разработка дополнительного метода обнуления данных в матрице MatrText
    • 7. Программирование события клика на кнопке button1 («Ввод матрицы 1 …»)
    • 8. Программирование события клика на кнопке button2 («Ввод матрицы 2…»)
    • 9. Программирование события Leave потери фокуса ввода элементом управления textBox1
    • 10. Программирование события клика на кнопке button3 («Результат»)
    • 11. Программирование события клика на кнопке button4 («Сохранить в файле «Res_Matr.txt»»)
    • 12. Запуск приложения на выполнение

Поиск на других ресурсах:

Условие задачи

Составить программу, которая осуществляет произведение двух матриц размерностью n. Матрицы вводятся из клавиатуры в отдельной форме и заносятся во внутренние структуры данных. Пользователь имеет возможность просмотреть результирующую матрицу.

Также есть возможность сохранения результирующей матрицы в текстовом файле “Res_Matrix.txt”.

 


Выполнение

1. Запуск Microsoft Visual Studio. Создание проекта

Подробный пример запуска Microsoft Visual Studio и создания приложения по шаблону Windows Forms Application описывается в теме:

  • Создание приложения Windows Forms Application в MS Visual Studio

Сохранить проект под любым именем.

 

2. Создание главной формы Form1

Создать форму, как показано на рисунке 1.

Разместить на форме элементы управления следующих типов:

  • четыре элемента управления типа Button. Автоматически будут созданы четыре объекта (переменные) с именами button1, button2, button3, button4;
  • три элемента управления типа Label с именами label1, label2, label3;
  • один элемент управления типа TextBox, доступ к которому можно получить по имени textBox1.

Сформировать свойства элементов управления типа Button и Label:

  • в объекте button1 свойство Text = “Ввод матрицы 1 …«;
  • в объекте button2 свойство Text = “Ввод матрицы 2 …«;
  • в объекте button3 свойство Text = “Результат …»;
  • в объекте button4 свойство Text = “Сохранить в файле “Res_Matr.txt” ”;
  • в элементе управления label1 свойство Text = “n = ”.

Для настройки вида и поведения формы нужно выполнить следующие действия:

  • установить название формы. Для этого свойство Text = “Произведение матриц”;
  • свойство StartPosition = “CenterScreen” (форма размещается по центру экрана);
  • свойство MaximizeBox = “false” (убрать кнопку развертывания на весь экран).

C# Windows Forms Форма приложенияРис. 1. Форма приложения

 

3. Создание второстепенной формы Form2

Во второстепенной форме Form2 будут вводиться данные в матрицы и выводиться исходный результат.

Пример создания новой формы в MS Visual Studio – C# подробно описан здесь.

Добавить новую форму к приложению, вызвав команду

Project -> Add Windows Form …

В открывшемся окне выбрать «Windows Form». Имя файла оставить без изменений «Form2.cs».



Разместить на форме в любом месте элемент управления типа Button (рис. 2). В результате будет получен объект с именем button1.

В элементе управления button1 нужно установить следующие свойства:

  • свойство Text = “OK”;
  • свойство DialogResult = “OK” (рис. 3). Это означает, что при нажатии (клике «мышкой») на button1, окно закроется с кодом возвращения равным “OK”;
  • свойство Modifiers = “Public”. Это означает, что кнопка button1 будет видимой из других модулей (из формы Form1).

Настроить свойства формы Form2:

  • свойство Text = “Ввод матрицы”;
  • свойство StartPosition = “CenterScreen” (форма размещается по центру экрана);
  • свойство MaximizeBox = “false” (убрать кнопку развертывания на весь экран).

C# Windows Forms Форма Form2Рис. 2. Форма Form2 после настройки

C# Windows Forms Свойство DialogResult элемент управления ButtonРис. 3. Свойство DialogResult элемента управления button1 формы Form2

 

4. Ввод внутренних переменных

Следующий шаг – введение внутренних переменных в текст модуля “Form1.cs”.

Для этого сначала нужно активировать модуль “Form1.cs”.

В тексте модуля “Form1.cs” добавляем следующий код:

...

namespace WindowsFormsApplication1
{
    public partial class Form1 : Form
    {
        const int MaxN = 10; // максимально допустимая размерность матрицы
        int n = 3; // текущая размерность матрицы
        TextBox[,] MatrText = null; // матрица элементов типа TextBox
        double[,] Matr1 = new double[MaxN, MaxN]; // матрица 1 чисел с плавающей точкой
        double[,] Matr2 = new double[MaxN, MaxN]; // матрица 2 чисел с плавающей точкой
        double[,] Matr3 = new double[MaxN, MaxN]; // матрица результатов
        bool f1; // флажок, который указывает о вводе данных в матрицу Matr1
        bool f2; // флажок, который указывает о вводе данных в матрицу Matr2
        int dx = 40, dy = 20; // ширина и высота ячейки в MatrText[,]
        Form2 form2 = null;   // экземпляр (объект) класса формы Form2

        public Form1()
        {
            InitializeComponent();
        }
    }
}
...

Объясним некоторые значения переменных:

  • Max – максимально-допустимая размерность матрицы;
  • n – размерность матрицы, введенная пользователем из клавиатуры в элементе управления TextBox1;
  • MatrText – двумерная матрица элементов управления типа TextBox. В эту матрицу будут вводиться элементы матрицы в виде строк. Ввод данных будет формироваться в форме Form2;
  • Matr1, Matr2 – матрицы элементов типа double, в которые будут копироваться данные из матрицы MatrText;
  • Matr3 – результирующая матрица, которая равная произведению матриц Matr1 и Matr2;
  • f1, f2 – переменные, определяющие были ли введенные данные соответственно в матрицы Matr1 и Matr2;
  • dx, dy – габариты одной ячейки типа TextBox в матрице MatrText;
  • form2 – объект класса формы Form2, по которыму будет получен доступ к этой форме.

 

5. Программирование события Load формы Form1

Процесс программирования любого события в Microsoft Visual C# подробно описан здесь.

Листинг обработчика события Load формы Form1 следующий:

private void Form1_Load(object sender, EventArgs e)
{
  // І. Инициализация элементов управления и внутренних переменных
  textBox1.Text = "";
  f1 = f2 = false; // матрицы еще не заполнены
  label2.Text = "false";
  label3.Text = "false";

  // ІІ. Выделение памяти и настройка MatrText
  int i, j;

  // 1. Выделение памяти для формы Form2
  form2 = new Form2();

  // 2. Выделение памяти под самую матрицу
  MatrText = new TextBox[MaxN, MaxN];

  // 3. Выделение памяти для каждой ячейки матрицы и ее настройка
  for (i = 0; i < MaxN; i++)
    for (j = 0; j < MaxN; j++)
    {
      // 3.1. Выделить память
      MatrText[i, j] = new TextBox();

      // 3.2. Обнулить эту ячейку
      MatrText[i, j].Text = "0";

      // 3.3. Установить позицию ячейки в форме Form2
      MatrText[i, j].Location = new System.Drawing.Point(10 + i * dx, 10 + j * dy);

      // 3.4. Установить размер ячейки
      MatrText[i, j].Size = new System.Drawing.Size(dx, dy);

      // 3.5. Пока что спрятать ячейку
      MatrText[i, j].Visible = false;

      // 3.6. Добавить MatrText[i,j] в форму form2
      form2.Controls.Add(MatrText[i, j]);
    }
}

Объясним некоторые фрагменты кода в методе Form1_Load().

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

В обработчике события Form1_Load() выделяется память для двумерной матрицы строк MatrText один лишь раз. При завершении приложения эта память будет автоматически освобождена.

Память выделяется в два этапа:

  • для самой матрицы MatrText – как двумерного массива;
  • для каждого элемента матрицы, который есть сложным объектом типа TextBox.

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

Также каждая созданная ячейка добавляется (размещается) на форму Form2 с помощью метода Add() из класса Controls. Каждая новая ячейка может быть добавлена в любую другую форму приложения.

 

6. Разработка дополнительного метода обнуления данных в матрице MatrText

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

Листинг метода Clear_MatText() следующий:

private void Clear_MatrText()
{
  // Обнуление ячеек MatrText
  for (int i = 0; i < n; i++)
    for (int j = 0; j < n; j++)
      MatrText[i, j].Text = "0";
}

 

7. Программирование события клика на кнопке button1Ввод матрицы 1 …»)

При нажатии (клике) на button1 должно вызываться окно ввода новой матрицы. Размер матрицы зависит от значения n.

Листинг обработчика события клика на кнопке button1 следующий:

private void button1_Click(object sender, EventArgs e)
{
  // 1. Чтение размерности матрицы
  if (textBox1.Text == "") return;
  n = int.Parse(textBox1.Text);

  // 2. Обнуление ячейки MatrText
  Clear_MatrText();

  // 3. Настройка свойств ячеек матрицы MatrText
  //    с привязкой к значению n и форме Form2
  for (int i = 0; i < n; i++)
    for (int j = 0; j < n; j++)
    {
      // 3.1. Порядок табуляции
      MatrText[i, j].TabIndex = i * n + j + 1;

      // 3.2. Сделать ячейку видимой
      MatrText[i, j].Visible = true;
    }

  // 4. Корректировка размеров формы
  form2.Width = 10 + n * dx + 20;
  form2.Height = 10 + n * dy + form2.button1.Height + 50 ;

  // 5. Корректировка позиции и размеров кнопки на форме Form2
  form2.button1.Left = 10;
  form2.button1.Top = 10 + n * dy + 10;
  form2.button1.Width = form2.Width - 30;

  // 6. Вызов формы Form2
  if (form2.ShowDialog() == DialogResult.OK)
  {
    // 7. Перенос строк из формы Form2 в матрицу Matr1
    for (int i = 0; i < n; i++)
      for (int j = 0; j < n; j++)
        if (MatrText[i, j].Text != "")
          Matr1[i, j] = Double.Parse(MatrText[i, j].Text);
        else
          Matr1[i, j] = 0;
        // 8. Данные в матрицу Matr1 внесены
        f1 = true;
        label2.Text = "true";
  }
}

В вышеприведенном листинге читается значение n. После этого осуществляется настройка ячеек матрицы строк MatrText.

На основе введенного значения n формируются размеры формы form2 и позиция кнопки button1.

Если в форме Form2 пользователь нажал на кнопке OK (button2), то строки с MatrText переносятся в двумерную матрицу вещественных чисел Matr1. Преобразование из строки в соответствующее вещественное число выполняется методом Parse() из класса Double.

Также формируется переменная f1, которая указывает что данные в матрицу Matr1 внесены.

 

8. Программирование события клика на кнопке button2 (“Ввод матрицы 2…«)

Листинг обработчика события клика на кнопке button2 подобен листингу обработчика события клика на кнопке button1. Только он отличается шагами 7-8. На этом участке формируются матрица Matr2 и переменная f2.

private void button2_Click(object sender, EventArgs e)
{
  // 1. Чтение размерности матрицы
  if (textBox1.Text == "") return;
  n = int.Parse(textBox1.Text);

  // 2. Обнулить ячейки MatrText
  Clear_MatrText();

  // 3. Настройка свойств ячеек матрицы MatrText
  //    с привязкой к значению n и форме Form2
  for (int i = 0; i < n; i++)
    for (int j = 0; j < n; j++)
    {
      // 3.1. Порядок табуляции
      MatrText[i, j].TabIndex = i * n + j + 1;

      // 3.2. Сделать ячейку видимой
      MatrText[i, j].Visible = true;
    }

  // 4. Корректировка размеров формы
  form2.Width = 10 + n * dx + 20;
  form2.Height = 10 + n * dy + form2.button1.Height + 50;

  // 5. Корректировка позиции и размеров кнопки на форме Form2
  form2.button1.Left = 10;
  form2.button1.Top = 10 + n * dy + 10;
  form2.button1.Width = form2.Width - 30;

  // 6. Вызов формы Form2
  if (form2.ShowDialog() == DialogResult.OK)
  {
    // 7. Перенос строк из формы Form2 в матрицу Matr2
    for (int i = 0; i < n; i++)
      for (int j = 0; j < n; j++)
        Matr2[i, j] = Double.Parse(MatrText[i, j].Text);

    // 8. Матрица Matr2 сформирована
    f2 = true;
    label3.Text = "true";
  }
}

 

9. Программирование события Leave потери фокуса ввода элементом управления textBox1

В приложении может возникнуть ситуация, когда пользователь изменяет значение n на новое. В этом случае должны заново формироваться флажки f1 и f2. Также изменяется размер матрицы MatrText, которая выводится в форме Form2.

Изменение значения n можно проконтролировать с помощью события Leave элемента управление textBox1. Событие Leave генерируется в момент потери фокуса ввода элементом управления textBox1 (рис. 4).

C# Windows Forms Событие Leave элемента управления textBox1Рис. 4. Событие Leave элемента управления textBox1

Листинг обработчика события Leave следующий:

private void textBox1_Leave(object sender, EventArgs e)
{
  int nn;
  nn = Int16.Parse(textBox1.Text);
  if (nn != n)
  {
    f1 = f2 = false;
    label2.Text = "false";
    label3.Text = "false";
  }
}

 

10. Программирование события клика на кнопке button3Результат»)

Вывод результата будет осуществляться в ту же форму, в которой вводились матрицы Matr1 и Matr2. Сначала произведение этих матриц будет сформировано в матрице Matr3. Потом значение с Matr3 переносится в MatrText и отображается на форме Form2.

Листинг обработчика события клика на кнопке button3.

private void button3_Click(object sender, EventArgs e)
{
  // 1. Проверка, введены ли данные в обеих матрицах
  if (!((f1 == true) && (f2 == true))) return;

  // 2. Вычисление произведения матриц. Результат в Matr3
  for (int i = 0; i < n; i++)
    for (int j = 0; j < n; j++)
    {
      Matr3[j,i] = 0;
      for (int k = 0; k < n; k++)
        Matr3[j, i] = Matr3[j, i] + Matr1[k, i] * Matr2[j, k];
    }

  // 3. Внесение данных в MatrText
  for (int i = 0; i < n; i++)
    for (int j = 0; j < n; j++)
    {
      // 3.1. Порядок табуляции
      MatrText[i, j].TabIndex = i * n + j + 1;

      // 3.2. Перевести число в строку
      MatrText[i, j].Text = Matr3[i, j].ToString();
    }

  // 4. Вывод формы
  form2.ShowDialog();
}

 

11. Программирование события клика на кнопке button4Сохранить в файле «Res_Matr.txt””)

Для сохранения результирующей матрицы Matr3 можно использовать возможности класса FileStream.

Класс FileStream описан в модуле System.IO. Поэтому в начале приложения нужно добавить следующий код:

using System.IO;

Листинг обработчика события клика на кнопке button4 следующий:

private void button4_Click(object sender, EventArgs e)
{
  FileStream fw = null;
  string msg;
  byte[] msgByte = null; // байтовый массив

  // 1. Открыть файл для записи
  fw = new FileStream("Res_Matr.txt", FileMode.Create);

  // 2. Запись матрицы результата в файл
  // 2.1. Сначала записать число элементов матрицы Matr3
  msg = n.ToString() + "rn";
  // перевод строки msg в байтовый массив msgByte
  msgByte = Encoding.Default.GetBytes(msg);

  // запись массива msgByte в файл
  fw.Write(msgByte, 0, msgByte.Length);

  // 2.2. Теперь записать саму матрицу
  msg = "";
  for (int i = 0; i < n; i++)
  {
    // формируем строку msg из элементов матрицы
    for (int j = 0; j < n; j++)
      msg = msg + Matr3[i, j].ToString() + "  ";
    msg = msg + "rn"; // добавить перевод строки
  }

  // 3. Перевод строки msg в байтовый массив msgByte
  msgByte = Encoding.Default.GetBytes(msg);

  // 4. запись строк матрицы в файл
  fw.Write(msgByte, 0, msgByte.Length);

  // 5. Закрыть файл
  if (fw != null) fw.Close();
}

 

12. Запуск приложения на выполнение

После этого можно запускать приложение на выполнение и тестировать его работу.

 


Ключевые слова:

Двумерный массив— массив, у которого 2 индекса, например: А(3,3); В( 2, 5) и т. п.

Матрица – в математике – аналог двумерного массива – квадратная или прямоугольная таблица, состоящая из строк и столбцов:

2мерный массив

Размер двумерного массива — количество элементов в массиве M*N,

где М – число строк, N – число столбцов (натураль – ные числа).

Квадратная матрица – матрица с равным числом строк и столбцов.

Порядок матрицы – число строк (столбцов) квадратной матрицы.

диагонали матрицы

1. Описание двумерного массива

Двумерный массив – это массив массивов, т. е. двумерная таблица. Оперировать можно как с отдельными элементами массива, так и с массивом в целом.

В языке Pascal индексы заключаются в квадратные скобки:

А[1,1], A[1,2],..A[1,n].

Возможны 2 способа описания 2-мерного массива:

1 Описание массива в разделе переменных VAR:

объявление 2мерного массива

где

iнач..iкон, jнач..jкон – диапазоны индексов (строк, столбцов);

t – тип элементов.

Например:

VAR y: [1..5, 1..5] of integer ;

VAR F: array [1..30] of array [1..20] of real;

VAR mb: array [1..100, 1..5] of real ;

CONST Max = 4;

VAR C: array [1..Max, 1..Max] OF string[10] ;

CONST M= 4; N=2;

VAR A: array [1..M, 1..N] OF integer ;

2 Описание массива в разделе описания типов TYPE:

Например:

TYPE mas = array[1..20, 1..5] of integer;

VAR A, g: mas;

CONST M=10; N=20;

TYPE t = ARRAY[1..M, 1..N] OF REAL;

VAR a, b, c : t;

2. Заполнение 2-мерных массивов

Заполнение двумерного массива возможно по строкам и столбцам, каждый из элементов можно вводить:

1 с клавиатуры;

2 с помощью генератора случайных чисел;

3 объявление массива как CONST;

4 по формуле.

Заполнение по строкам:

А[1,1] А[1,2] А[1,3] А[1,4] А[1,5]
А[2,1]

Для заполнения матрицы организуется наружный цикл по i, внутренний – по j (при условии, что i – строки, j –столбцы). При этом индекс строки i меняется медленнее индекса столбца j за счет того, что происходит постепенный перебор всех элементов строки, т. е. столбцов i-й строки.

Заполнение по столбцам:

А[1,1] А[1,2]
А[2,1]
А[3,1]
A[4,1]

Упражнения на заполнение 2-мерных массивов

Упражнение mas1: Заполнить матрицу А( 5, 10) по строкам методом генерирования случайных чисел.

program mas_1; {заполнение матрицы по строкам}

Uses Crt;

var

A: array [1..5, 1..10] of INTEGER;

i, j: byte;

BEGIN

ClrScr;

randomize;

writeLn(‘Матрица А:’);

FOR i:= 1 to 5 DO {наружный цикл по строкам}

begin

FOR j:=1 TO 10 DO {внутренний цикл по столбцам}

begin

A[i, j]:= random(10);

write(A[i, j]:3); {печатаем подряд всю строку}

end;

writeLn; {переходим на новую строку}

end;

readLn;

END.

Упражнение mas2: Заполнить матрицу А(3, 4) по столбцам методом ввода чисел с клавиатуры.

program mas_2; {заполнение матрицы по столбцам}

Uses Crt;

Const N =4; M =3;

Var A: array [1..N, 1..M] of INTEGER;

i, j: byte;

BEGIN

ClrScr;

FOR j:= 1 to M DO {наружный цикл по столбцам }

begin

FOR i:=1 TO N DO {внутренний цикл по строкам}

begin

write(‘Введите элемент A[‘,i,’,’,j,’]=’);

readLn(A[i, j]);

end;

writeLn;

end;

writeLn(‘Результирующая матрица A:’);

for i:=1 to N do {Вывод матрицы}

begin

for j:=1 to M do

write(A[i, j],’ ‘);

writeLn;

end;

readLn;

END.

Упражнение mas3: Дана матрица A( N? M), состоящая из натуральных чисел. Определить ее максимальный элемент и его индексы.

program mas_3; {Max элемент матрицы}

Uses Crt;

CONST t= 10; r=10;

var

A: array [1..t, 1..r] of INTEGER;

i, j: byte;

n, m, Max, iMax, jMax, k: integer;

BEGIN

ClrScr;

randomize;

write(‘Введите число строк N=’); readLn(N);

write(‘Введите число столбцов M=’); readLn(M);

writeLn(‘Матрица:’);

FOR i:= 1 to N DO {заполнение массива генерированием случайных чисел}

begin

FOR j:=1 TO M DO

begin

A[i, j]:= random(10);

write(A[i, j]:3);

end;

writeLn;

end;

Max:= A[1,1]; iMax:=1; jMax:=1; k:=0; {принимаем начальное значение Мах = значению 1-го эл-та}

For i:=1 to N do

For j:=1 to M do

IF A[i, j] > Max then

begin

Max:= A[i, j]; iMax:=i; jMax:=j; k:=1

End;

WriteLn(‘Max= ’ ,Max,’ в строке: ‘,imax, ‘ столбце :’, jmax);

readLn;

END.

Основная задача переноса данных из таблицы элемента DataGridView в соответствующий массив не вызывает проблем. Конструкция Rows[i].Cells[j] позволяет добраться до нужного элемента таблицы, после чего остается присвоить его значение элементу массива.

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

Первый подход демонстрируется на примере ввода элементов матрицы A. Как обычно, преобразование данных, введенных пользователем, в значение, допустимое для элементов матрицы А, помещается в охраняемый блок. Если данные некорректны и возникает исключительная ситуация, то она перехватывается универсальным обработчиком catch(Exception). Заметьте, в данном варианте нет цикла, работающего до тех пор, пока не будет введено корректное значение. Обработчик исключения просто прерывает работу по переносу данных, вызывая оператор return. Но предварительно он формирует информационное сообщение об ошибке и выводит его в форму. (Помните, специально для этих целей у формы были заготовлены две метки). В сообщении пользователю предлагается исправить некорректно заданный элемент и повторить ввод – повторно нажать командную кнопку «перенести данные в массив». Этот подход понятен и легко реализуем. Недостатком является его неэффективность, поскольку повторно будут переноситься в массив все элементы, в том числе и те, что были введены вполне корректно. У программиста такая ситуация может вызывать чувство неудовлетворенности своей работой.

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

При проектировании диалогового окна значение свойства формы FormBorderStyle, установленное по умолчанию как «sizeable» следует заменить значением «FixedDialog», что влияет на внешний вид и поведение формы. Важно отметить, что форма, представляющее диалоговое окно, должна вызываться не методом Show, а методом ShowDialog. Иначе произойдет зацикливание, начнут порождаться десятки диалоговых окон, прежде чем успеете нажать спасительную в таких случаях комбинацию Ctrl+ Alt + Del.

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

Рис. 3.6. Информационное сообщение о некорректных значениях матрицы А.

После появления подобного сообщения пользователь должен исправить некорректное значение (одно или несколько) и повторить процесс переноса данных. На рис. 3.7. показана ситуация, когда некорректно заданное значение исправляется в открывшемся окне диалога.

Рис. 3.7. Диалоговое окно для корректировки значений элементов матрицы В.

Обработчик события «Click» командной кнопки «Умножить матрицы» выполняет ответственные задачи – реализует умножение матриц и отображает полученный результат в таблице соответствующего элемента DataGridView. Но оба эти действия выполняются естественным образом, не требуя кроме циклов никаких специальных средств и программистских ухищрений. Программный код без дополнительных комментариев:

private void button3_Click(object sender, EventArgs e)

{

MultMatr(A, B, C); FillDG();

}

void MultMatr(double[,] A, double[,] B, double[,] C)

{

int m = A.GetLength(0); int n = A.GetLength(1); int p = B.GetLength(1); double S =0;

for(int i=0; i < m; i++) for (int j = 0; j < p; j++)

{

S = 0;

for (int k = 0; k < n; k++) S += A[i, k] * B[k, j];

C[i, j] = S;

}

}

void FillDG()

{

for (int i = 0; i < m; i++) for (int j = 0; j < p; j++)

dataGridView3.Rows[i].Cells[j].Value

=C[i, j].ToString();}

4.Содержание отчёта

Отчёт должен содержать название и цель. Ход работы с комментариями и выполненное задания из ПРИЛОЖЕНИЕ А. Выводы.

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

1.Что такое массивы?

2.Особенности работы с массивами в C#.

3.Компоненты работы с массивами в Windows Form

4.Методы заполнения двумерных массивов в Windows Form

5.Опишите принципы работы ListBox в Windows Form

6.Опишите принципы работы CheckedListBox в Windows Form

7.Опишите принципы работы ComboBox в Windows Form

8.Опишите принципы работы DataGridView в Windows Form

ПРИЛОЖЕНИЕ А

1.Дан массив размера N и целые числа K и L (1 < K ≤ L ≤ N). Найти сумму всех элементов массива, кроме элементов с номерами от K до L включительно. Организуйте в Windows приложении ввод массива и вывод результата.

2.Организуйте в Windows приложении ввод массива «Сотрудники», содержащего фамилии сотрудников. Введите массив «Заявка», элементы которого содержат фамилии сотрудников и, следовательно, должны содержаться в массиве сотрудников. Обеспечьте контроль корректности ввода данных и выведите массив «Заявка».

3.Организуйте в Windows приложении ввод массива «Сотрудники», содержащего фамилии сотрудников. Создайте массив «Заявка», элементы которого должны содержаться в массиве сотрудников. Для создания массива «Заявка» постройте форму «Два списка», содержащую два элемента ListBox, источником данных для первого из них служит массив «Сотрудники». Пользователь переносит данные из первого списка во второй, формируя данные для массива «Заявка». После формирования данные переносятся в массив.

4.Организуйте в Windows приложении ввод массива «Студенты» из двух столбцов, содержащего фамилии и имена студентов. Введите массив «Общежитие» той же структуры, элементы которого должны содержаться в массиве сотрудников. Обеспечьте контроль корректности ввода данных. Организуйте вывод обоих массивов.

5.Организуйте в Windows приложении ввод и вывод массива «Машины», содержащего 4 столбца: «Владелец», «Марка», «Номер», «Год Выпуска». При вводе данных обеспечьте их корректность. Поле «Владелец» должно быть строкой в формате «фамилия имя», где фамилия и имя должны начинаться с большой буквы и состоять из букв алфавита кириллицы, включая дефис. Номер машины должен соответствовать формату, принятому для номеров машин. При выводе сохраняйте структуру массива.

6.Организуйте в Windows приложении ввод массива «Студенты», содержащего фамилии студентов, и массива «Стипендия». Обеспечьте контроль корректности ввода данных о стипендии, проверяя диапазон возможных значений, диапазон задается в полях на форме.

7.Организуйте в Windows приложении ввод и вывод матрицы — двумерного массива арифметического типа. Реализовать систему автоматического заполнения массива случайными числами.

8.Организуйте в Windows приложении ввод массива декартовых координат n точек на плоскости. Вычислите массив полярных

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

9.Дана матрица размера M × N. Поменять местами столбец с номером N и последний из столбцов, содержащих только положительные элементы. Если требуемых столбцов нет, то вывести матрицу без изменений.

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

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

12.Даны целые положительные числа M и N. Сформировать целочисленную матрицу размера M × N, у которой все элементы J-го столбца имеют значение5·J(J= 1, …, N). Обеспечьте контроль вводимых значений. Заполнить массив случайными числами и вывести его в соответствии с заданием.

13.Заполнить матрицу случайными числами размера M × N и целое число K(1 ≤ K ≤ M). Вывести элементы K-й строки данной матрицы. Обеспечьте контроль вводимых значений. Обеспечьте контроль вводимых значений.

14.Дана матрица размера M × N. Для каждой строки матрицы найти сумму ее элементов. Обеспечьте контроль вводимых значений.

15.Дана матрица размера M × N. В каждом столбце матрицы найти максимальный элемент. Обеспечьте контроль вводимых значений.

16.Дана матрица размера M × N. В каждой ее строке найти количество элементов, меньших среднего арифметического всех элементов этой строки. Обеспечьте контроль вводимых значений.

17.Дана матрица размера M × N и целые числа K1 и K2(1 ≤ K1< K2 ≤ M). Поменять местами строки матрицы с номерами K1 и K2. Обеспечьте контроль вводимых значений.

18.Дана матрица размера M × N. Преобразовать матрицу, поменяв местами минимальный и максимальный элемент в каждой строке.

19.Дана матрица размера M × N и целое число K(1 ≤ K ≤ N). Удалить столбец матрицы с номером K.

20.Дана матрица размера M × N и целое число K(1 ≤ K ≤ M). Перед строкой матрицы с номером K вставить строку из значений S. Обеспечьте контроль вводимых значений.

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]

  • #
  • #
  • #
  • #
  • #
  • #
  • #
  • #
  • #
  • #
  • #

Есть массив NxN, нужно ввести его по след формату
массив размером N = 3

1 2 3  
4 5 6  
7 8 9

Начал с

int[,] a = new int[101,101]; // исправил)

string[] s = new string[101];  
 for (int i = 0; i < N; i++)  
   s[i] = Console.ReadLine();

теперь нужно..

s[i] в int a[i]

как?

задан 16 ноя 2013 в 8:58

ixe's user avatar

ixeixe

1191 золотой знак2 серебряных знака8 бронзовых знаков

3

Массив size х size

        Console.Write("Введите размер массива: ");
        int size = int.Parse(Console.ReadLine());
        Console.WriteLine();
        int[,] myMassive = new int[size, size];
        for (int i = 0; i < myMassive.GetLength(0); i++)
        {
            string enterString = Console.ReadLine();
            string[] massiveString = enterString.Split(new Char[] { ' ' });
            for (int j = 0; j < massiveString.Length; j++)
            {
                myMassive[i, j] = int.Parse(massiveString[j]);
            }
        }

ответ дан 16 ноя 2013 в 9:24

Freezze's user avatar

FreezzeFreezze

6771 золотой знак4 серебряных знака11 бронзовых знаков

7

Если нужен ввод в одну строку, то можно сделать так:

    Console.WriteLine("Input first dimension");
    string rawFirstDimension = Console.ReadLine();
    Console.WriteLine("Input second dimension");
    string rawSecondDimension = Console.ReadLine();

    int firstDimension;
    int secondDimension;

    // провекрка корректности размеров массива
    if (!int.TryParse(rawFirstDimension, out firstDimension) ||
        !int.TryParse(rawSecondDimension, out secondDimension))
        throw new Exception("Parsing failed");

    var array = new int[firstDimension, secondDimension];

    string rawStr = Console.ReadLine();
    if (rawStr == null) // проверка массива на пустоту
        throw new Exception("Array is empty");

    var rawArray = rawStr.Split(' ');

    // проверка на соответствие массива требуемой размерности
    if(rawArray.Length != firstDimension * secondDimension)
        throw new Exception("Wrong array size");

    for (int i = 0; i < firstDimension; i++)
    {
        for (int j = 0; j < secondDimension; j++)
        {
            int next;
            if (int.TryParse(rawArray[i * secondDimension + j], out next))
                array[i, j] = next;
            else
              throw new Exception("Parsing failed");//если очередной элемент не число
        } 
    }

    Console.WriteLine("Array is");
    for (int i = 0; i < firstDimension; i++)
    {
        for (int j = 0; j < secondDimension; j++)
            Console.Write(array[i, j]);
        Console.WriteLine();
    }

ответ дан 16 ноя 2013 в 10:04

DreamChild's user avatar

DreamChildDreamChild

35.9k2 золотых знака44 серебряных знака85 бронзовых знаков

1

Ввод с клавиатуры массива 2х2 и вывод в консоль

        int[,] numbers = new int[2,2];

        for (int n = 0; n < 2; n++)
        {
            for (int m = 0; m < 2; m++)
            {
                Console.WriteLine("Enter number: ");
                numbers[n,m] = Convert.ToInt32(Console.ReadLine());
            }
            Console.WriteLine();
        }


        for (int i = 0; i < 2; i++)
        {
            for (int j = 0; j < 2; j++)
            {
                Console.Write(numbers[i, j] + " ");
            }
            Console.WriteLine();

ответ дан 22 июл 2016 в 17:17

jag's user avatar

ГЛАВА 7. Массивы и строки

В этой главе речь вновь пойдет о типах данных в С#.
В ней рассматриваются массивы и тип string, а так­
же оператор цикла foreach.

Массивы

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

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

Массивами в C# можно пользоваться практически так
же, как и в других языках программирования. Тем не менее
у них имеется одна особенность: они реализованы в виде
объектов. Именно поэтому их рассмотрение было отло­
жено до тех пор, пока в этой книге не были представлены
объекты. Реализация массивов в виде объектов дает ряд существенных преимуществ,
и далеко не самым последним среди них является возможность утилизировать неис­
пользуемые массивы средствам «сборки мусора».

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

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

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

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

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

ПРИМЕЧАНИЕ
Если у вас имеется некоторый опыт программирования на С или C++, обратите особое
внимание на то, как объявляются массивы в С#. В частности, квадратные скобки следуют
после названия типа, а не имени массива.

Обратимся к конкретному примеру. В приведенной ниже строке кода создается
массив типа int, который составляется из десяти элементов и связывается с перемен­
ной ссылки на массив, именуемой sample.

int[] sample = new int[10];

В переменной sample хранится ссылка на область памяти, выделяемой для массива
оператором new. Эта область памяти должна быть достаточно большой, чтобы в ней
могли храниться десять элементов массива типа int.

Как и при создании экземпляра класса, приведенное выше объявление массива
можно разделить на два отдельных оператора. Например:

int[] sample;
sample = new int[10];

В данном случае переменная sample не ссылается на какой-то определенный фи­
зический объект, когда она создается в первом операторе. И лишь после выполнения
второго оператора эта переменная ссылается на массив.

Доступ к отдельному элементу массива осуществляется по индексу: Индекс обозна­
чает положение элемента в массиве. В языке C# индекс первого элемента всех массивов
оказывается нулевым. В частности, массив sample состоит из 10 элементов с индекса­
ми от 0 до 9. Для индексирования массива достаточно указать номер требуемого эле­
мента в квадратных скобках. Так, первый элемент массива sample обозначается как
sample [0], а последний его элемент — как sample[9]. Ниже приведен пример про­
граммы, в которой заполняются все 10 элементов массива sample.

// Продемонстрировать одномерный массив.
using System;

class ArrayDemo {
    static void Main() {
        int[] sample = new int[10];
        int i;
        for(i = 0; i < 10; i = i+1)
            sample[i] = i;
        for(i = 0; i < 10; i = i+1)
            Console.WriteLine("sample[" + i + "]: " + sample[i]);
    }
}

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

sample[0]: 0
sample[1]: 1
sample[2]: 2
sample[3]: 3
sample[4]: 4
sample[5]: 5
sample[6]: 6
sample[7]: 7
sample[8]: 8
sample[9]: 9

Схематически массив sample можно представить таким образом.

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

// Вычислить среднее арифметическое ряда значений.
using System;

class Average {
    static void Main() {
        int[] nums = new int[10];
        int avg = 0;
        nums[0] = 99;
        nums[1] = 10;
        nums[2] = 100;
        nums[3] = 18;
        nums[4] = 78;
        nums[5] = 23;
        nums[6] = 63;
        nums[7] = 9;
        nums[8] = 87;
        nums[9] = 49;
        for(int i=0; i < 10; i++)
            avg = avg + nums[i];
        avg = avg / 10;
        Console.WriteLine("Среднее: " + avg);
    }
}

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

Инициализация массива

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

тип[] имя_массива = {vall, val2, val3, ..., valN};

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

// Вычислить среднее арифметическое ряда значений.
using System;

class Average {
    static void Main() {
        int[] nums = { 99, 10, 100, 18, 78, 23,
                        63, 9, 87, 49 };
        int avg = 0;
        for(int i=0; i < 10; i++)
            avg = avg + nums[i];
        avg = avg / 10;
        Console.WriteLine("Среднее: " + avg);
    }
}

Любопытно, что при инициализации массива можно также воспользоваться опе­
ратором new, хотя особой надобности в этом нет. Например, приведенный ниже фраг­
мент кода считается верным, но избыточным для инициализации массива nums в упо­
мянутой выше программе.

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

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

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

В данном случае переменная nums объявляется в первом операторе и инициализи­
руется во втором.

И последнее замечание: при инициализации массива его размер можно указывать
явным образом, но этот размер должен совпадать с числом инициализаторов. В каче­
стве примера ниже приведен еще один способ инициализации массива nums.

int[] nums = new int[10] { 99, 10, 100, 18, 78, 23,
                            63, 9, 87, 49 );

В этом объявлении размер массива nums задается равным 10 явно.

Соблюдение границ массива

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

// Продемонстрировать превышение границ массива.
using System;

class ArrayErr {
    static void Main() {
        int[] sample = new int[10];
        int i;
        // Воссоздать превышение границ массива.
        for(i = 0; i < 100; i = i+1)
            sample[i] = i;
    }
}

Как только значение переменной i достигает 10, возникнет исключительная ситуа­
ция типа IndexOutOfRangeException, связанная с выходом за пределы индексирова­
ния массива, и программа преждевременно завершится. (Подробнее об исключитель­
ных ситуациях и их обработке речь пойдет в главе 13.)

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

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

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

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

В следующей строке кода объявляется двумерный массив integer размерами
10×20.

int[,] table = new int[10, 20];

Обратите особое внимание на объявление этого массива. Как видите, оба его разме­
ра разделяются запятой. В первой части этого объявления синтаксическое обозначение

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

В данном объявлении создается массив размерами 10×20, но и в этом случае его раз­
меры разделяются запятой.

Для доступа к элементу двумерного массива следует указать оба индекса, разделив
их запятой. Например, в следующей строке кода элементу массива table с координа­
тами местоположения (3,5) присваивается значение 10.

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

// Продемонстрировать двумерный массив.
using System;

class TwoD {
    static void Main() {
        int t, i;
        int[,] table = new int[3, 4];
        for(t=0; t < 3; ++t) {
            for(i=0; i < 4; ++i) {
                table[t,i] = (t*4)+i+1;
                Console.Write(table[t,i] + " ");
            }
            Console.WriteLine();
        }
    }
}

В данном примере элемент массива table[0,0] будет иметь значение 1, элемент
массива table[0,1] — значение 2, элемент массива table[0,2] — значение 3 и т.д.
А значение элемента массива table[2,3] окажется равным 12. На рис. 7.1 показано
схематически расположение элементов этого массива и их значений.

Рис. 7.1. Схематическое представление массива table, созданного в программе TwoD

СОВЕТ
Если вам приходилось раньше программировать на С, C++ или Java, то будьте особенно
внимательны, объявляя или организуя доступ к многомерным массивам в С#. В этих языках
программирования размеры массива и индексы указываются в отдельных квадратных
скобках, тогда как в C# они разделяются запятой.

Массивы трех и более измерений

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

тип[,...,] имя_массива = new тип[размер1, размер2, ... размерN];

Например, в приведенном ниже объявлении создается трехмерный целочислен­
ный массив размерами 4×10×3.

int[,,] multidim = new int[4, 10, 3];

А в следующем операторе элементу массива multidim с координатами местополо­
жения (2,4,1) присваивается значение 100.

Ниже приведен пример программы, в которой сначала организуется трехмерный
массив, содержащий матрицу значений 3×3×3, а затем значения элементов этого мас­
сива суммируются по одной из диагоналей матрицы.

// Суммировать значения по одной из диагоналей матрицы 3×3×3.
using System;

class ThreeDMatrix {
    static void Main() {
        int[,,] m = new int[3, 3, 3];
        int sum = 0;
        int n = 1;
        for(int x=0; x < 3; x++)
            for(int y=0; у < 3; y++)
                for(int z=0; z < 3; z++)
                    m[x, y, z] = n++;
        sum = m[0, 0, 0] + m[1, 1, 1] + m[2, 2, 2];
        Console.WriteLine("Сумма значений по первой диагонали: " + sum);
    }
}

Вот какой результат дает выполнение этой программы.

Сумма значений по первой диагонали: 42

Инициализация многомерных массивов

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

тип[,] имя_массива = {
    {val, val, val, ..., val},
    {val, val, val, ..., val},

    {val, val, val, ..., val}
};

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

В качестве примера ниже приведена программа, в которой двумерный массив sqrs
инициализируется числами от 1 до 10 и квадратами этих чисел.

// Инициализировать двумерный массив.
using System;

class Squares {
    static void Main() {
        int[,] sqrs = {
            { 1, 1 },
            { 2, 4 },
            { 3, 9 },
            { 4, 16 },
            { 5, 25 },
            { 6, 36 },
            { 7, 49 },
            { 8, 64 },
            { 9, 81 },
            { 10, 100 }
        };
        int i, j;
        for(i=0; i < 10; i++) {
            for(j=0; j < 2; j++)
                Console.Write(sqrs[i,j] + " ");
            Console.WriteLine();
        }
    }
}

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

1 1
2 4
3 9
4 16
5 25
6 36
7 49
8 64
9 81
10 100

Ступенчатые массивы

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

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

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

где размер обозначает число строк в массиве. Память для самих строк распределяется
индивидуально, и поэтому длина строк может быть разной. Например, в приведенном
ниже фрагменте кода объявляется ступенчатый массив jagged. Память сначала рас­
пределяется для его первого измерения автоматически, а затем для второго измерения
вручную.

int[][] jagged = new int[3][];
jagged[0] = new int[4];
jagged[1] = new int[3];
jagged[2] = new int[5];

После выполнения этого фрагмента кода массив jagged выглядит так, как показа­
но ниже.

Теперь нетрудно понять, почему такие массивы называются ступенчатыми! После
создания ступенчатого массива доступ к его элементам осуществляется по индексу,
указываемому в отдельных квадратных скобках. Например, в следующей строке кода
элементу массива jagged, находящемуся на позиции с координатами (2,1), присваи­
вается значение 10.

Обратите внимание на синтаксические отличия в доступе к элементу ступенчатого
и прямоугольного массива.

В приведенном ниже примере программы демонстрируется создание двумерного
ступенчатого массива.

// Продемонстрировать применение ступенчатых массивов.
using System;

class Jagged {
    static void Main() {
        int[][] jagged = new int[3][];
        jagged[0] = new int[4];
        jagged[1] = new int[3];
        jagged[2] = new int[5];
        int i;
        // Сохранить значения в первом массиве.
        for(i=0; i < 4; i++)
            jagged[0] [i] = i;
        // Сохранить значения во втором массиве.
        for(i=0; i < 3; i++)
            jagged[1][i] = i;
        jagged [0][0]
        jagged [1][0]
        jagged [2][0]
        jagged [0][1]
        jagged [1][1]
        jagged [2][1]
        jagged [0][2] jagged [0][3]
        jagged [1][2]
        jagged [2][2] jagged [2][3] jagged [2][4]
        // Сохранить значения в третьем массиве.
        for(i=0; i < 5; i++)
            jagged[2][i] = i;
        // Вывести значения из первого массива.
        for(i=0; i < 4; i++)
            Console.Write(jagged[0][i] + " ");
        Console.WriteLine();

        // Вывести значения из второго массива.
        for(i=0; i < 3; i++)
            Console.Write(jagged[1][i] + " ");
        Console.WriteLine();

        // Вывести значения из третьего массива.
        for(i=0; i < 5; i++)
            Console.Write(jagged [2] [i ] + " ") ;
        Console.WriteLine();
    }
}

Выполнение этой программы приводит к следующему результату.

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

И последнее замечание: ступенчатые массивы представляют собой массивы масси­
вов, и поэтому они не обязательно должны состоять из одномерных массивов. Напри­
мер, в приведенной ниже строке кода создается массив двумерных массивов.

int[][,] jagged = new int[3][,];

В следующей строке кода элементу массива jagged[0] присваивается ссылка на
массив размерами 4×2.

jagged[0] = new int[4, 2];

А в приведенной ниже строке кода элементу массива jagged[0][1,0] присваива­
ется значение переменной i.

Присваивание ссылок на массивы

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

// Присваивание ссылок на массивы.
using System;

class AssignARef {
    static void Main() {
        int i;
        int[] nums1 = new int[10];
        int[] nums2 = new int [10];
        for(i=0; i < 10; i++) nums1[i] = i;
        for(i=0; i < 10; i++) nums2[i] = -i;
        Console.Write("Содержимое массива nums1: ");
        for(i=0; i < 10; i++)
            Console.Write(nums1[i] + " ");
        Console.WriteLine();

        Console.Write("Содержимое массива nums2: ");
        for(i=0; i < 10; i++)
            Console.Write(nums2[i] + " ");
        Console.WriteLine();

        nums2 = nums1; // теперь nums2 ссылается на nums1
        Console.Write("Содержимое массива nums2n" + "после присваивания: ");
        for(i=0; i < 10; i++)
            Console.Write(nums2[i] + " ");
        Console.WriteLine();

        // Далее оперировать массивом nums1 посредством
        // переменной ссылки на массив nums2.
        nums2[3] = 99;
        Console.Write("Содержимое массива nums1 после измененияn" +
                    "посредством переменной nums2: ");
        for(i=0; i < 10; i++)
            Console.Write(numsl[i] + " ");
        Console.WriteLine();
    }
}

Выполнение этой программы приводит к следующему результату.

Содержимое массива nums1: 0 1 2 3 4 5 6 7 8 9
Содержимое массива nums2: 0 -1 -2 -3 -4 -5 -6 -7 -8 -9
Содержимое массива nums2
после присваивания: 0 1 2 3 4 5 6 7 8 9
Содержимое массива nums1 после изменения
посредством переменной nums2: 0 1 2 99 4 5 6 7 8 9

Как видите, после присваивания переменной nums2 значения переменной nums1
обе переменные ссылки на массив ссылаются на один и тот же объект.

Применение свойства Length

Реализация в C# массивов в виде объектов дает целый ряд преимуществ. Одно из
них заключается в том, что с каждым массивом связано свойство Length, содержащее
число элементов, из которых может состоять массив. Следовательно, у каждого масси­
ва имеется специальное свойство, позволяющее определить его длину. Ниже приведен
пример программы, в которой демонстрируется это свойство.

// Использовать свойство Length массива.
using System;

class LengthDemo {
    static void Main() {
        int[] nums = new int[10];
        Console.WriteLine("Длина массива nums равна " + nums.Length);
        // Использовать свойство Length для инициализации массива nums.
        for (int i=0; i < nums.Length; i++)
            nums[i] = i * i;
        // А теперь воспользоваться свойством Length
        // для вывода содержимого массива nums.
        Console.Write("Содержимое массива nums: ");
        for(int i=0; i < nums.Length; i++)
            Console.Write(nums[i] + " ");
        Console.WriteLine();
    }
}

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

Длина массива nums равна 10
Содержимое массива nums: 0 1 4 9 16 25 36 49 64 81

Обратите внимание на то, как в классе LengthDemo свойство nums.Length исполь­
зуется в циклах for для управления числом повторяющихся шагов цикла. У каждого
массива имеется своя длина, поэтому вместо отслеживания размера массива вручную
можно использовать информацию о его длине. Следует, однако, иметь в виду, что зна­
чение свойства Length никак не отражает число элементов, которые в нем использу­
ются на самом деле. Свойство Length содержит лишь число элементов, из которых
может состоять массив.

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

// Использовать свойство Length трехмерного массива.
using System;

class LengthDemo3D {
    static void Main() {
        int[,,] nums = new int[10, 5, 6];
        Console.WriteLine("Длина массива nums равна " + nums.Length);
    }
}

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

Длина массива nums равна 300

Как подтверждает приведенный выше результат, свойство Length содержит число
элементов, из которых может состоять массив (в данном случае — 300 (10×5×6) эле­
ментов). Тем не менее свойство Length нельзя использовать для определения длины
массива в отдельном его измерении.

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

// Поменять местами содержимое элементов массива.
using System;

class RevCopy {
    static void Main() {
        int i, j;
        int[] nums1 = new int[10];
        int[] nums2 = new int[10];
        for(i=0; i < nums1.Length; i++) nums1[i] = i;
        Console.Write("Исходное содержимое массива: ");
        for(i=0; i < nums2.Length; i++)
            Console.Write(nums1[i] + " ");
        Console.WriteLine();

        // Скопировать элементы массива nums1 в массив nums2 в обратном порядке.
        if(nums2.Length >= nums1.Length) // проверить, достаточно ли
        // длины массива nums2
        for(i=0, j=nums1.Length-1; i < nums1.Length; i++, j--)
            nums2[j] = nums1[i];
        Console.Write("Содержимое массива в обратном порядке: ");
        for(i=0; i < nums2.Length; i++)
            Console.Write(nums2[i] + " ");
        Console.WriteLine();
    }
}

Выполнение этой программы дает следующий результат.

Исходное содержимое массива: 0 1 2 3 4 5 6 7 8 9
Содержимое массива в обратном порядке: 9 8 7 6 5 4 3 2 1 0

В данном примере свойство Length помогает выполнить две важные функции. Во-
первых, оно позволяет убедиться в том, что длины целевого массива достаточно для
хранения содержимого исходного массива. И во-вторых, оно предоставляет условие
для завершения цикла for, в котором выполняется копирование исходного массива в
обратном порядке. Конечно, в этом простом примере размеры массивов нетрудно вы­
яснить и без свойства Length, но аналогичный подход может быть применен в целом
ряде других, более сложных ситуаций.

Применение свойства Length при обращении со ступенчатыми массивами

Особый случай представляет применение свойства Length при обращении со сту­
пенчатыми массивами. В этом случае с помощью данного свойства можно получить
длину каждого массива, составляющего ступенчатый массив. В качестве примера рас­
смотрим следующую программу, в которой имитируется работа центрального про­
цессора (ЦП) в сети, состоящей из четырех узлов.

// Продемонстрировать применение свойства Length
// при обращении со ступенчатыми массивами.
using System;

class Jagged {
    static void Main() {
        int[][] network_nodes = new int[4][];
        network_nodes[0] = new int[3];
        network_nodes[1] = new int[7];
        network_nodes[2] = new int[2];
        network_nodes[3] = new int[5];
        int i, j;
        // Сфабриковать данные об использовании ЦП.
        for(i=0; i < network_nodes.Length; i++)
            for(j=0; j < network_nodes[i].Length; j++)
                network_nodes[i][j] = i * j + 70;
        Console.WriteLine("Общее количество узлов сети: " +
                        network_nodes.Length + "n");
        for(i=0; i < network_nodes.Length; i++) {
            for(j=0; j < network_nodes[i].Length; j++) {
                Console.Write("Использование в узле сети " + i +
                            " ЦП " + j + ": ") ;
                Console.Write(network_nodes[i][j] + "% ");
                Console.WriteLine();
            }
            Console.WriteLine();
        }
    }
}

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

Общее количество узлов сети: 4
Использование в узле 0 ЦП 0: 70%
Использование в узле 0 ЦП 1: 70%
Использование в узле 0 ЦП 2: 70%
Использование в узле 1 ЦП 0: 70%
Использование в узле 1 ЦП 1: 71%
Использование в узле 1 ЦП 2: 72%
Использование в узле 1 ЦП 3: 73%
Использование в узле 1 ЦП 4: 74%
Использование в узле 1 ЦП 5: 75%
Использование в узле 1 ЦП 6: 76%
Использование в узле 2 ЦП 0: 70%
Использование в узле 2 ЦП 1: 72%
Использование в узле 3 ЦП 0: 70%
Использование в узле 3 ЦП 1: 73%
Использование в узле 3 ЦП 2: 76%
Использование в узле 3 ЦП 3: 79%
Использование в узле 3 ЦП 4: 82%

Обратите особое внимание на то, как свойство Length используется в ступенчатом
массиве network_nodes. Напомним, что двумерный ступенчатый массив представля­
ет собой массив массивов. Следовательно, когда используется выражение

то в нем определяется число массивов, хранящихся в массиве network_nodes (в дан­
ном случае — четыре массива). А для получения длины любого отдельного массива,
составляющего ступенчатый массив, служит следующее выражение.

В данном случае это длина первого массива.

Неявно типизированные массивы

Как пояснялось в главе 3, в версии C# 3.0 появилась возможность объявлять неявно
типизированные переменные с помощью ключевого слова var. Это переменные, тип
которых определяется компилятором, исходя из типа инициализирующего выраже­
ния. Следовательно, все неявно типизированные переменные должны быть непремен­
но инициализированы. Используя тот же самый механизм, можно создать и неявно
типизированный массив. Как правило, неявно типизированные массивы предназна­
чены для применения в определенного рода вызовах, включающих в себя элементы
языка LINQ, о котором речь пойдет в главе 19. А в большинстве остальных случаев
используется «обычное» объявление массивов. Неявно типизированные массивы рас­
сматриваются здесь лишь ради полноты представления о возможностях языка С#.

Неявно типизированный массив объявляется с помощью ключевого слова var, но
без последующих квадратных скобок []. Кроме того, неявно типизированный мас­
сив должен быть непременно инициализирован, поскольку по типу инициализато­
ров определяется тип элементов данного массива. Все инициализаторы должны быть
одного и того же согласованного типа. Ниже приведен пример объявления неявно ти­
пизированного массива.

var vals = new[] { 1, 2, 3, 4, 5 };

В данном примере создается массив типа int, состоящий из пяти элементов. Ссыл­
ка на этот массив присваивается переменной vals. Следовательно, тип этой перемен­
ной соответствует типу int массива, состоящего из пяти элементов. Обратите внима­
ние на то, что в левой части приведенного выше выражения отсутствуют квадратные
скобки []. А в правой части этого выражения, где происходит инициализация масси­
ва, квадратные скобки присутствуют. В данном контексте они обязательны.

Рассмотрим еще один пример, в котором создается двумерный массив типа
double.

var vals = new[,] { {1.1, 2.2}, {3.3, 4.4},{ 5.5, 6.6} };

В данном случае получается массив vals размерами 2×3.

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

// Продемонстрировать неявно типизированный ступенчатый массив.
using System;

class Jagged {
    static void Main() {
        var jagged = new[] {
            new[] { 1, 2, 3, 4 },
            new[] { 9, 8, 7 ),
            new[] { 11, 12, 13, 14, 15 }
        };
        for(int j = 0; j < jagged.Length; j++) {
            for(int i=0; i < jagged[j].Length; i++)
                Console.Write(jagged[j][i] + " ");
            Console.WriteLine();
        }
    }
}

Выполнение этой программы дает следующий результат.

1 2 3 4
9 8 7
11 12 13 14 15

Обратите особое внимание на объявление массива jagged.

var jagged = new[] {
    new[] { 1, 2, 3, 4 },
    new[] { 9, 8, 7 },
    new[] { 11, 12, 13, 14, 15 }
};

Как видите, оператор new[] используется в этом объявлении двояким образом.
Во-первых, этот оператор создает массив массивов. И во-вторых, он создает каждый
массив в отдельности, исходя из количества инициализаторов и их типа. Как и следо­
вало ожидать, все инициализаторы отдельных массивов должны быть одного и того
же типа. Таким образом, к объявлению любого неявно типизированного ступенчатого
массива применяется тот же самый общий подход, что и к объявлению обычных сту­
пенчатых массивов.

Как упоминалось выше, неявно типизированные массивы чаще всего применяются
в LINQ-ориентированных запросах. А в остальных случаях следует использовать явно
типизированные массивы.

Оператор цикла foreach

Как упоминалось в главе 5, в языке C# определен оператор цикла foreach, но его рас­
смотрение было отложено до более подходящего момента. Теперь этот момент настал.

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

foreach (тип имя_переменной_цикла in коллекция) оператор;

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

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

Следует, однако, иметь в виду, что переменная цикла в операторе foreach служит
только для чтения. Это означает, что, присваивая этой переменной новое значение,
нельзя изменить содержимое массива.

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

// Использовать оператор цикла foreach.
using System;

class ForeachDemo {
    static void Main() {
        int sum = 0;
        int[] nums = new int[10];
        // Задать первоначальные значения элементов массива nums.
        for(int i = 0; i < 10; i++)
            nums[i] = i;
        // Использовать цикл foreach для вывода значений
        // элементов массива и подсчета их суммы.
        foreach(int х in nums) {
            Console.WriteLine("Значение элемента равно: " + х);
            sum += х;
        }
        Console.WriteLine("Сумма равна: " + sum);
    }
}

Выполнение приведенного выше кода дает следующий результат.

Значение элемента равно: 0
Значение элемента равно: 1
Значение элемента равно: 2
Значение элемента равно: 3
Значение элемента равно: 4
Значение элемента равно: 5
Значение элемента равно: 6
Значение элемента равно: 7
Значение элемента равно: 8
Значение элемента равно: 9
Сумма равна: 45

Как видите, оператор foreach циклически опрашивает массив по порядку индек­
сир
ования от самого первого до самого последнего его элемента.
Несмотря на то что цикл foreach повторяется до тех пор, пока не будут опрошены
все элементы массива, его можно завершить преждевременно, воспользовавшись опе­
ратором break. Ниже приведен пример программы, в которой суммируются только
пять первых элементов массива nums.

// Использовать оператор break для преждевременного завершения цикла
// foreach.
using System;

class ForeachDemo {
    static void Main() {
        int sum = 0;
        int[] nums = new int[10];
        // Задать первоначальные значения элементов массива nums.
        for(int i = 0; i < 10; i++)
            nums[i] = i;
        // Использовать цикл foreach для вывода значений
        // элементов массива и подсчета их суммы.
        foreach(int x in nums) {
            Console.WriteLine("Значение элемента равно: " + x);
            sum += x;
            if(x == 4) break; // прервать цикл, как только индекс массива достигнет 4
        }
        Console.WriteLine("Сумма первых 5 элементов: " + sum);
    }
}

Вот какой результат дает выполнение этой программы.

Значение элемента равно: 0
Значение элемента равно: 1
Значение элемента равно: 2
Значение элемента равно: 3
Значение элемента равно: 4
Сумма первых 5 элементов: 10

Совершенно очевидно, что цикл foreach завершается после выбора и вывода зна­
чения пятого элемента массива.

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

// Использовать оператор цикла foreach для обращения к двумерному массиву.
using System;
class ForeachDemo2 {
    static void Main() {
        int sum = 0;
        int[,] nums = new int[3,5];
        // Задать первоначальные значения элементов массива nums.
        for(int i = 0; i < 3; i++)
            for(int j=0; j < 5; j++)
                nums[i,j] = (i+1)*(j+1);
        // Использовать цикл foreach для вывода значений
        // элементов массива и подсчета их суммы.
        foreach(int х in nums) {
            Console.WriteLine("Значение элемента равно: " + х);
            sum += х;
        }
        Console.WriteLine("Сумма равна: " + sum);
    }
}

Выполнение этой программы дает следующий результат.

Значение элемента равно: 1
Значение элемента равно: 2
Значение элемента равно: 3
Значение элемента равно: 4
Значение элемента равно: 5
Значение элемента равно: 2
Значение элемента равно: 4
Значение элемента равно: 6
Значение элемента равно: 8
Значение элемента равно: 10
Значение элемента равно: 3
Значение элемента равно: 6
Значение элемента равно: 9
Значение элемента равно: 12
Значение элемента равно: 15
Сумма равна: 90

Оператор foreach допускает циклическое обращение к массиву только в опреде­
ленном порядке: от начала и до конца массива, поэтому его применение кажется, на
первый взгляд, ограниченным. Но на самом деле это не так. В большом числе алго­
ритмов, самым распространенным из которых является алгоритм поиска, требуется
именно такой механизм. В качестве примера ниже приведена программа, в которой
цикл foreach используется для поиска в массиве определенного значения. Как только
это значение будет найдено, цикл прервется.

// Поиск в массиве с помощью оператора цикла foreach.
using System;

class Search {
    static void Main() {
        int[] nums = new int[10];
        int val;
        bool found = false;
        // Задать первоначальные значения элементов массива nums.
        for(int i = 0; i < 10; i++)
            nums[i] = i;
        val = 5;
        // Использовать цикл foreach для поиска заданного
        // значения в массиве nums.
        foreach(int х in nums) {
            if(x == val) (
            found = true;
            break;
        }
        if(found)
            Console.WriteLine("Значение найдено!");
    }
}

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

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

Строки

С точки зрения регулярного программирования строковый тип данных string от­
носится к числу самых важных в С#. Этот тип определяет и поддерживает символьные
строки. В целом ряде других языков программирования строка представляет собой
массив символов. А в C# строки являются объектами. Следовательно, тип string от­
носится к числу ссылочных. И хотя string является встроенным в C# типом данных,
его рассмотрение пришлось отложить до тех пор, пока не были представлены классы
и объекты.

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

Console.WriteLine("В C# строки являются объектами.");

текстовая строка «В C# строки являются объектами.» автоматически преобра­
зуется в строковый объект средствами С#. Следовательно, применение класса типа
string происходило в предыдущих примерах программ неявным образом. А в этом
разделе будет показано, как обращаться со строками явным образом.

Построение строк

Самый простой способ построить символьную строку — воспользоваться строко­
вым литералом. Например, в следующей строке кода переменной ссылки на строку
str присваивается ссылка на строковый литерал.

string str = "Строки в C# весьма эффективны.";

В данном случае переменная str инициализируется последовательностью симво­
лов «Строки в C# весьма эффективны.».

Объект типа string можно также создать из массива типа char. Например:

char[] charray = {'t', 'е', 's', 't'};
string str = new string(charray);

Как только объект типа string будет создан, его можно использовать везде, где
только требуется строка текста, заключенного в кавычки. Как показано в приведенном
ниже примере программы, объект типа string может служить в качестве аргумента
при вызове метода WriteLine().

// Создать и вывести символьную строку.
using System;

class StringDemo {
    static void Main() {
        char[] charray = {'Э', 't', 'o', ' ', 'с', 't', 'p', 'o', 'к', 'a',
        string strl = new string(charray);
        string str2 = "Еще одна строка.";
        Console.WriteLine(strl);
        Console.WriteLine(str2);
    }
}

Результат выполнения этой программы приведен ниже.

Это строка.
Еще одна строка.

Обращение со строками

Класс типа string содержит ряд методов для обращения со строками. Некото­
рые из этих методов перечислены в табл. 7.1. Обратите внимание на то, что некото­
рые методы принимают параметр типа StringComparison. Это перечислимый
тип, определяющий различные значения, которые определяют порядок сравнения
символьных строк. (О перечислениях речь пойдет в главе 12, но для применения типа
StringComparison к символьным строкам знать о перечислениях необязательно.)
Нетрудно догадаться, что символьные строки можно сравнивать разными способа­
ми. Например, их можно сравнивать на основании двоичных значений символов, из
которых они состоят. Такое сравнение называется порядковым. Строки можно также
сравнивать с учетом различных особенностей культурной среды, например, в лекси­
кографическом порядке. Это так называемое сравнение с учетом культурной среды.
(Учитывать культурную среду особенно важно в локализуемых приложениях.) Кроме
того, строки можно сравнивать с учетом или без учета регистра. Несмотря на то что
существуют перегружаемые варианты методов Compare(), Equals(), IndexOf()
и LastIndexOf(), обеспечивающие используемый по умолчанию подход к сравне­
нию символьных строк, в настоящее время считается более приемлемым явно указы­
вать способ требуемого сравнения, чтобы избежать неоднозначности, а также упро­
стить локализацию приложений. Именно поэтому здесь рассматривают разные спо­
собы сравнения символьных строк.

Как правило и за рядом исключений, для сравнения символьных строк с уче­
том культурной среды (т.е. языковых и региональных стандартов) применяется
способ StringComparison.CurrentCulture. Если же требуется сравнить стро­
ки только на основании значений их символов, то лучше воспользоваться спосо­
бом StringComparison.Ordinal, а для сравнения строк без учета регистра — од­
ним из двух способов: StringComparison.CurrentCultureIgnoreCase или
StringComparison.OrdinalIgnoreCase. Кроме того, можно указать сравнение
строк без учета культурной среды (подробнее об этом — в главе 22).

Обратите внимание на то, что метод Compare() объявляется в табл. 7.1 как static.
Подробнее о модификаторе static речь пойдет в главе 8, а до тех пор вкратце по­
ясним, что он обозначает следующее: метод Compare() вызывается по имени своего
класса, а не по его экземпляру. Следовательно, для вызова метода Compare() служит
следующая общая форма:

результат = string.Compare(str1, str2, способ);

где способ обозначает конкретный подход к сравнению символьных строк.

ПРИМЕЧАНИЕ
Дополнительные сведения о способах сравнения и поиска символьных строк, включая
и особое значение выбора подходящего способа, приведены в главе 22, где подробно
рассматривается обработка строк.

Обратите также внимание на методы ToUpper() и ToLower(), преобразующие со­
держимое строки в символы верхнего и нижнего регистра соответственно. Их формы,
представленные в табл. 7.1, содержат параметр CultureInfо, относящийся к классу,
в котором описываются атрибуты культурной среды, применяемые для сравнения.
В примерах, приведенных в этой книге, используются текущие настройки культурной
среды (т.е. текущие языковые и региональные стандарты). Эти настройки указываются
при передаче методу аргумента CultureInfo.CurrentCulture. Класс CultureInfo
относится к пространству имен System.Globalization. Любопытно, имеются вари­
анты рассматриваемых здесь методов, в которых текущая культурная среда исполь­
зуется по умолчанию, но во избежание неоднозначности в примерах из этой книги
аргумент CultureInfo.CurrentCulture указывается явно.

Объекты типа string содержат также свойство Length, где хранится длина строки.

Таблица 7.1. Некоторые общеупотребительные методы обращения со строками

Метод Описание
static int Compare(string strA, string strB, StringComparison comparisonType) Возвращает отрицательное значение, если строка strA меньше строки strB; положительное значение, если строка strA больше строки strВ; и нуль, если сравниваемые строки равны. Способ сравнения определяется аргументом comparisonType
bool Equals(string value, StringComparison comparisonType) Возвращает логическое значение true, если вызывающая строка имеет такое же значение, как и у аргумента value. Способ сравнения определяется аргументом comparisonType
int IndexOf(char value) Осуществляет поиск в вызывающей строке первого вхождения символа, определяемого аргументом value. Применяется порядковый способ поиска. Возвращает индекс первого совпадения с искомым символом или -1, если он не обнаружен
int IndexOf(string value, StringComparison comparisonType) Осуществляет поиск в вызывающей строке перво­ го вхождения подстроки, определяемой аргументом value. Возвращает индекс первого совпадения с искомой подстрокой или -1, если она не обнаружена. Способ поиска определяется аргументом comparisonType
int LastIndexOf(char value) Осуществляет поиск в вызывающей строке последнего вхождения символа, определяемого аргументом value. Применяется порядковый способ поиска. Возвращает индекс последнего совпадения с искомым символом или -1, если он не обнаружен
int LastIndexOf(string value, StringComparison comparisonType) Осуществляет поиск в вызывающей строке последнего вхождения подстроки, определяемой аргументом value. Возвращает индекс последнего совпадения с искомой подстрокой или -1, если она не обнаружена. Способ поиска определяется аргументом comparisonType
string ToLower(CultureInfo.CurrentCulture culture) Возвращает вариант вызывающей строки в нижнем регистре. Способ преобразования определяется аргументом culture
string ToUpper(CultureInfo.CurrentCulture culture) Возвращает вариант вызывающей строки в верхнем регистре. Способ преобразования определяется аргументом culture

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

string str = "тест";
Console.WriteLine(str[0]);

В этом фрагменте кода выводится символ «т», который является первым в строке
«тест». Как и в массивах, индексирование строк начинается с нуля. Следует, однако,
иметь в виду, что с помощью индекса нельзя присвоить новое значение символу в стро­
ке. Индекс может служить только для выборки символа из строки.

Для проверки двух строк на равенство служит оператор ==. Как правило, если опе­
ратор == применяется к ссылкам на объект, то он определяет, являются ли они ссыл­
ками на один и тот же объект. Совсем иначе обстоит дело с объектами типа string.
Когда оператор == применяется к ссылкам на две строки, он сравнивает содержимое
этих строк. Это же относится и к оператору !=. В обоих случаях выполняется поряд­
ковое сравнение. Для проверки двух строк на равенство с учетом культурной среды
служит метод Equals(), где непременно нужно указать способ сравнения в виде ар­
гумента StringComparison.CurrentCulture. Следует также иметь в виду, что ме­
тод Compare() служит для сравнения строк с целью определить отношение порядка,
например для сортировки. Если же требуется проверить символьные строки на ра­
венство, то для этой цели лучше воспользоваться методом Equals() или строковыми
операторами.

В приведенном ниже примере программы демонстрируется несколько операций
со строками.

// Некоторые операции со строками.
using System;
using System.Globalization;

class StrOps {
	static void Main() {
		string str1 = "Программировать в .NET лучше всего на С#.";
		string str2 = "Программировать в .NET лучше всего на С#.";
		string str3 = "Строки в C# весьма эффективны.";
		string strUp, strLow;
		int result, idx;
		Console.WriteLine("str1: " + str1);
		Console.WriteLine("Длина строки str1: " + str1.Length);
		// Создать варианты строки str1, набранные
		// прописными и строчными буквами.
		strLow = str1.ToLower(CultureInfo.CurrentCulture);
		strUp = str1.ToUpper(CultureInfo.CurrentCulture);
		Console.WriteLine("Вариант строки str1, " +
						"набранный строчными буквами:n " + strLow);
		Console.WriteLine("Вариант строки str1, " +
						"набранный прописными буквами:n " + strUp);
		Console.WriteLine();

		// Вывести строку str1 посимвольно.
		Console.WriteLine("Вывод строки str1 посимвольно.");
		for (int i=0; i < str1.Length; i++)
			Console.Write(str1[i]);
		Console.WriteLine("n");

		// Сравнить строки способом порядкового сравнения.
		if(str1 == str2)
			Console.WriteLine("str1 == str2");
		else
			Console.WriteLine("str1 != str2");
		if(str1 == str3)
			Console.WriteLine("str1 == str3");
		else
			Console.WriteLine("str1 != str3");
		// Сравнить строки с учетом культурной среды.
		result = string.Compare(str3, str1, StringComparison.CurrentCulture);
		if(result == 0)
			Console.WriteLine("Строки str1 и str3 равны");
		else if (result < 0)
			Console.WriteLine("Строка str1 меньше строки str3");
		else
			Console.WriteLine("Строка str1 больше строки str3");
		Console.WriteLine();

		// Присвоить новую строку переменной str2.
		str2 = "Один Два Три Один";
		// Поиск подстроки.
		idx = str2.IndexOf("Один", StringComparison.Ordinal);
		Console.WriteLine("Индекс первого вхождения подстроки <Один>: " + idx);
		idx = str2.LastIndexOf("Один", StringComparison.Ordinal);
		Console.WriteLine("Индекс последнего вхождения подстроки <Один>: " +
						idx);
	}
}

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

str1: Программировать в .NET лучше всего на С#.
Длина строки str1: 41
Вариант строки str1, набранный строчными буквами:
программировать в .net лучше всего на c#.
Вариант строки str1, набранный прописными буквами:
программировать в .net лучше всего на c#.

Вывод строки str1 посимвольно.
Программировать в .NET лучше всего на С#.

str1 == str2
str1 != str3
Строка str1 больше строки str3
Индекс первого вхождения подстроки <Один>: 0
Индекс последнего вхождения подстроки <Один>: 13

Прежде чем читать дальше, обратите внимание на то, что метод Compare() вызы­
вается следующим образом.

result = string.Compare(str1, str3, StringComparison.CurrentCulture);

Как пояснялось ранее, метод Compare() объявляется как static, и поэтому он вы­
зывается по имени, а не по экземпляру своего класса.

С помощью оператора + можно сцепить (т.е. объединить вместе) две строки.
Например, в следующем фрагменте кода:

string str1 = "Один";
string str2 = "Два";
string str3 = "Три";
string str4 = str1 + str2 + str3;

переменная str4 инициализируется строкой «ОдинДваТри».

И еще одно замечание: ключевое слово string является псевдонимом класса
System.String, определенного в библиотеке классов для среды .NET Framework,
т.е. оно устанавливает прямое соответствие с этим классом. Следовательно, поля
и методы, определяемые типом string, относятся непосредственно к классу
System.String, в который входят и многие другие компоненты. Подробнее о классе
System.String речь пойдет в части II этой книги.

Массивы строк

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

// Продемонстрировать массивы строк.
using System;

class StringArrays {
	static void Main() {
		string[] str = { "Это", "очень", "простой", "тест." };
		Console.WriteLine("Исходный массив: ");
		for(int i=0; i < str.Length; i++)
			Console.Write(str[i] + " ");
		Console.WriteLine("n");
		// Изменить строку.
		str[l] = "тоже";
		str[3] = "до предела тест!";
		Console.WriteLine("Видоизмененный массив: ");
		for(int i=0; i < str.Length; i++)
			Console.Write(str[i] + " ");
	}
}

Вот какой результат дает выполнение приведенного выше кода.

Исходный массив:
Это очень простой тест.

Видоизмененный массив:
Это тоже простой до предела тест!

Рассмотрим более интересный пример. В приведенной ниже программе целое чис­
ло выводится словами. Например, число 19 выводится словами «один девять».

// Вывести отдельные цифры целого числа словами.
using System;

class ConvertDigitsToWords {
	static void Main() {
		int num;
		int nextdigit;
		int numdigits;
		int[] n = new int[20];
		string[] digits = { "нуль", "один", "два",
			"три", "четыре", "пять",
			"шесть", "семь", "восемь",
			"девять" };
		num = 1908;
		Console.WriteLine("Число: " + num);
		Console.Write("Число словами: ");
		nextdigit = 0;
		numdigits = 0;
		// Получить отдельные цифры и сохранить их в массиве n.
		// Эти цифры сохраняются в обратном порядке.
		do {
			nextdigit = num % 10;
			n[numdigits] = nextdigit;
			numdigits++;
			num = num / 10;
		} while(num > 0);
		numdigits--;
		// Вывести полученные слова.
		for( ; numdigits >= 0; numdigits--)
			Console.Write(digits[n[numdigits]] + " ");
		Console.WriteLine();
	}
}

Выполнение этой программы приводит к следующему результату.

Число: 1908
Число словами: один девять нуль восемь

В данной программе использован массив строк digits для хранения словесных
обозначений цифр от 0 до 9. По ходу выполнения программы целое число преобразу­
ется в слова. Для этого сначала получаются отдельные цифры числа, а затем они сохра­
няются в обратном порядке следования в массиве n типа int. После этого выполняется
циклический опрос массива n в обратном порядке. При этом каждое целое значение
из массива п служит в качестве индекса, указывающего на слова, соответствующие по­
лученным цифрам числа и выводимые как строки.

Постоянство строк

Как ни странно, содержимое объекта типа string не подлежит изменению. Это
означает, что однажды созданную последовательность символов изменить нельзя. Но
данное ограничение способствует более эффективной реализации символьных строк.
Поэтому этот, на первый взгляд, очевидный недостаток на самом деле превращается в
преимущество. Так, если требуется строка в качестве разновидности уже имеющейся
строки, то для этой цели следует создать новую строку, содержащую все необходимые
изменения. А поскольку неиспользуемые строковые объекты автоматически собирают­
ся в «мусор», то о дальнейшей судьбе ненужных строк можно даже не беспокоиться.

Следует, однако, подчеркнуть, что переменные ссылки на строки (т.е. объекты типа
string) подлежат изменению, а следовательно, они могут ссылаться на другой объект.
Но содержимое самого объекта типа string не меняется после его создания.

Для того чтобы стало понятнее, почему неизменяемые строки не являются помехой,
воспользуемся еще одним методом обращения со строками: Substring(). Этот метод
возвращает новую строку, содержащую часть вызывающей строки. В итоге создает­
ся новый строковый объект, содержащий выбранную подстроку, тогда как исходная
строка не меняется, а следовательно, соблюдается принцип постоянства строк. Ниже
приведена рассматриваемая здесь форма метода Substring():

string Substring(int индекс_начала, int длина)

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

Ниже приведена программа, в которой принцип постоянства строк демонстри­
руется на примере использования метода Substring().

// Применить метод Substring().
using System;

class SubStr {
	static void Main() {
		string orgstr = "В C# упрощается обращение со строками.";
		// сформировать подстроку
		string substr = orgstr.Substring(5, 20);
		Console.WriteLine("orgstr: " + orgstr);
		Console.WriteLine("substr: " + substr);
	}
}

Вот к какому результату приводит выполнение этой программы.

orgstr: В C# упрощается обращение со строками.
substr: упрощается обращение

Как видите, исходная строка из переменной orgstr не меняется, а выбранная из
нее подстрока содержится в переменной substr.

И последнее замечание: несмотря на то, что постоянство строк обычно не являет­
ся ни ограничением, ни помехой для программирования на С#, иногда оказывается
полезно иметь возможность видоизменять строки. Для этой цели в C# имеется класс
StringBuilder, который определен в пространстве имен System.Text. Этот класс
позволяет создавать строковые объекты, которые можно изменять. Но, как правило,
в программировании на C# используется тип string, а не класс StringBuilder.

Применение строк в операторах switch

Объекты типа string могут использоваться для управления оператором switch.
Это единственный нецелочисленный тип данных, который допускается применять
в операторе switch. Благодаря такому применению строк в некоторых сложных си­
туациях удается найти более простой выход из положения, чем может показаться на
первый взгляд. Например, в приведенной ниже программе выводятся отдельные циф­
ры, соответствующие словам «один», «два» и «три».

// Продемонстрировать управление оператором switch посредством строк.
using System;

class StringSwitch {
	static void Main() {
		string[] strs = { "один", "два", "три", "два", "один" };
		foreach(string s in strs) {
			switch(s) {
				case "один":
					Console.Write(1);
					break;
				case "два":
					Console.Write(2);
					break;
				case "три":
					Console.Write(3);
					break;
			}
		}
		Console.WriteLine();
	}
}

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

Понравилась статья? Поделить с друзьями:
  • Микрософт офисе ворд 2003 скачать бесплатно для windows 10
  • Мерцает экран после обновления на windows 10
  • Миграция windows server 2012 r2 на windows server 2019
  • Метод расширенного восстановления системы windows 10 через командную строку
  • Микрософт офисе 2020 скачать бесплатно для windows 10 торрент