THE BELL

Есть те, кто прочитали эту новость раньше вас.
Подпишитесь, чтобы получать статьи свежими.
Email
Имя
Фамилия
Как вы хотите читать The Bell
Без спама

Массивы

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

Массивами в C# можно пользоваться практически так же, как и в других языках программирования. Тем не менее у них имеется одна особенность: они реализованы в виде объектов.

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

Using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace ConsoleApplication1 { class Program { static void Main(string args) { // Объявляем массив int myArr = new int; // Инициализируем каждый элемент массива вручную myArr = 100; myArr = 23; myArr = 25; myArr = 31; myArr = 1; foreach (int i in myArr) Console.WriteLine(i); Console.ReadLine(); } } }

Следует иметь в виду, что если массив только объявляется, но явно не инициализируется, каждый его элемент будет установлен в значение, принятое по умолчанию для соответствующего типа данных (например, элементы массива типа bool будут устанавливаться в false, а элементы массива типа int - в 0).

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

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

// Синтаксис инициализации массива с использованием // ключевого слова new int myArr = new int {10,20,30,40,50}; // Синтаксис инициализации массива без использования // ключевого слова new string info = { "Фамилия", "Имя", "Отчество" }; // Используем ключевое слово new и желаемый размер char symbol = new char { "X","Y","Z","M" };

Обратите внимание, что в случае применения синтаксиса с фигурными скобками размер массива указывать не требуется (как видно на примере создания переменной myArr), поскольку этот размер автоматически вычисляется на основе количества элементов внутри фигурных скобок. Кроме того, применять ключевое слово new не обязательно (как при создании массива info).

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

Using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace ConsoleApplication1 { class Program { static void Main(string args) { var arr1 = new { 1, 2, 3 }; Console.WriteLine("Тип массива arr1 - {0}",arr1.GetType()); var arr2 = new { "One", "Two", "Three" }; Console.WriteLine("Тип массива arr2 - {0}",arr2.GetType()); Console.ReadLine(); } } }

Разумеется, как и при создании массива с использованием явного синтаксиса C#, элементы, указываемые в списке инициализации массива, должны обязательно иметь один и тот же базовый тип (т.е. должны все быть int, string или MyCar).

Определение массива объектов

В большинстве случаев при определении массива тип элемента, содержащегося в массиве, указывается явно. Хотя на первый взгляд это выглядит довольно понятно, существует одна важная особенность. В основе каждого типа в системе типов.NET (в том числе фундаментальных типов данных) в конечном итоге лежит базовый класс System.Object . В результате получается, что в случае определения массива объектов находящиеся внутри него элементы могут представлять собой что угодно:

Using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace ConsoleApplication1 { class Program { static void Main(string args) { // Объявляем и инициализируем массив объектов object arrByObject = { true, 10, "Привет", 13.7m }; // Выведем в консоль тип каждого члена массива foreach (object me in arrByObject) Console.WriteLine("Тип {0} - {1}",me,me.GetType()); Console.ReadLine(); } } }

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

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

Массив характеризуется следующими основными понятиями:

Элемент массива (значение элемента массива) – значение, хранящееся в определенной ячейке памяти, расположенной в пределах массива, а также адрес этой ячейки памяти.
Каждый элемент массива характеризуется тремя величинами:

  • адресом элемента — адресом начальной ячейки памяти, в которой расположен этот элемент;
  • индексом элемента (порядковым номером элемента в массиве);
  • значением элемента.

Адрес массива – адрес начального элемента массива.

Имя массива – идентификатор, используемый для обращения к элементам массива.

Размер массива – количество элементов массива

Размер элемента – количество байт, занимаемых одним элементом массива.

Графически расположение массива в памяти компьютера можно представить в виде непрерывной ленты адресов.

Представленный на рисунке массив содержит q элементов с индексами от 0 до q-1 . Каждый элемент занимает в памяти компьютера k байт, причем расположение элементов в памяти последовательное.

Адреса i -го элемента массива имеет значение

Адрес массива представляет собой адрес начального (нулевого) элемента массива. Для обращения к элементам массива используется порядковый номер (индекс) элемента, начальное значение которого равно 0 . Так, если массив содержит q элементов, то индексы элементов массива меняются в пределах от 0 до q-1 .

Длина массива – количество байт, отводимое в памяти для хранения всех элементов массива.

ДлинаМассива = РазмерЭлемента * КоличествоЭлементов

Для определения размера элемента массива может использоваться функция

int sizeof (тип);

Например,

sizeof (char ) = 1;
sizeof (int ) = 4;
sizeof (float ) = 4;
sizeof (double ) = 8;

Объявление и инициализация массивов

Для объявления массива в языке Си используется следующий синтаксис:

тип имя[размерность]={инициализация};

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

int a = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; // массив a из 10 целых чисел

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

int b = {0}; // массив b из 10 элементов, инициализированных 0


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

int a = {1, 2, 3, 4, 5, 6, 7, 8, 9};

При обращении к элементам массива индекс требуемого элемента указывается в квадратных скобках .

Пример на Си

1
2
3
4
5
6
7
8

#include
int main()
{
int a = { 5, 4, 3, 2, 1 }; // массив a содержит 5 элементов
printf("%d %d %d %d %d\n" , a, a, a, a, a);
getchar();
return 0;
}

Результат выполнения программы:

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

int a;

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18


#include
int main()
{
int a;
int i;
// Ввод элементов массива
for (i = 0; i<5; i++)
{
printf("a[%d] = " , i);
scanf("%d" , &a[i]);
}
// Вывод элементов массива
for (i = 0; i<5; i++)
printf("%d " , a[i]); // пробел в формате печати обязателен
getchar(); getchar();
return 0;
}

Результат выполнения программы

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

В языке Си могут быть также объявлены многомерные массивы. Отличие многомерного массива от одномерного состоит в том, что в одномерном массиве положение элемента определяется одним индексом, а в многомерном - несколькими. Примером многомерного массива является матрица.

Общая форма объявления многомерного массива

тип имя[размерность1][размерность2]...[размерностьm];

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

int a;


будет расположен в памяти следующим образом

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

КоличествоСтрок * КоличествоСтолбцов = 2 * 3 = 6.

Количество байт памяти, требуемых для размещения массива, определится как

КоличествоЭлементов * РазмерЭлемента = 6 * 4 = 24 байта.

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

Значения элементов многомерного массива, как и в одномерном случае, могут быть заданы константными значениями при объявлении, заключенными в фигурные скобки {} . Однако в этом случае указание количества элементов в строках и столбцах должно быть обязательно указано в квадратных скобках .

Пример на Си

1
2
3
4
5
6
7
8
9

#include
int main()
{
int a = { 1, 2, 3, 4, 5, 6 };
printf("%d %d %d\n" , a, a, a);
getchar();
return 0;
}



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

Пример на Си

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27

#define _CRT_SECURE_NO_WARNINGS
#include
int main()
{
int a; // массив из 2 строк и 3 столбцов
int i, j;
// Ввод элементов массива
for (i = 0; i<2; i++) // цикл по строкам
{
for (j = 0; j<3; j++) // цикл по столбцам
{
printf("a[%d][%d] = " , i, j);
scanf("%d" , &a[i][j]);
}
}
// Вывод элементов массива
for (i = 0; i<2; i++) // цикл по строкам
{
for (j = 0; j<3; j++) // цикл по столбцам
{
printf("%d " , a[i][j]);
}
printf("\n" ); // перевод на новую строку
}
getchar(); getchar();
return 0;
}



Передача массива в функцию

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

  • адрес массива,
  • размер массива.

Исключение составляют функции обработки строк, в которые достаточно передать только адрес.

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

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

Пример на Си Дан массив из 10 элементов. Поменять местами наибольший и начальный элементы массива. Для операций поиска максимального элемента и обмена использовать функцию.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42

#define _CRT_SECURE_NO_WARNINGS
#include
// Функция обмена
void change(int *x, int n)
{
// x - указатель на массив (адрес массива)
// n - размер массива
int i;
int max, index;
max = x;
index = 0;
// Поиск максимального элемента
for (i = 1; i {
if (x[i]>max)
{
max = x[i];
index = i;
}
}
// Обмен
x = x;
x = max;
}
// Главная функция
int main()
{
int a;
int i;
for (i = 0; i<10; i++)
{
printf("a[%d] = " , i);
scanf("%d" , &a[i]);
}
change(a, 10); // вызов функции обмена
// Вывод элементов массива
for (i = 0; i<10; i++)
printf("%d " , a[i]);
getchar();
getchar();
return
p = p * x[i];
}
return p;
}
// Главная функция
int main()
{
int a; // объявлен массив a из 5 элементов
int i;
int pr;
// Ввод элементов массива
for (i = 0; i<5; i++)
{
printf("a[%d] = " , i);
scanf("%d" , &a[i]); // &a[i] - адрес i-го элемента массива
}
pr = func(a, 5); // вычисление произведения
printf("\n pr = %d" , pr); // вывод произведения четных элементов
getchar(); getchar();
return 0;
}



П усть нам необходимо работать с большим количеством однотипных данных. Например, у нас есть тысяча измерений координаты маятника с каким-то шагом по времени. Создавать 1000 переменных для хранения всех значений очень... обременительно. Вместо этого множество однотипных данных можно объединить под одним именем и обращаться к каждому конкретному элементу по его порядковому номеру.
Массив в си определяется следующим образом
<тип> <имя массива>[<размер>];
Например,
int a;
Мы получим массив с именем a , который содержит сто элементов типа int . Как и в случае с переменными, массив содержит мусор.
Для получения доступа до первого элемента, в квадратных скобках пишем его номер (индекс). Например

#include #include void main() { int a; a = 10; a = 333; a = 234; printf("%d %d %d", a, a, a); getch(); }

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

Рис. 1 Массив хранит адрес первого элемента. Индекс i элемента - это сдвиг на i*sizeof(тип) байт от начала

Индекс массива указывает, на сколько байт необходимо сместиться относительно начала массива, чтобы получить доступ до нужно элемента. Например, если массив A имеет тип int , то A означает, что мы сместились на 10*sizeof(int) байт относительно начала. Первый элемент находится в самом начале и у него смещение 0*sizeof(int) .
В си массив не хранит своего размера и не проверяет индекс массива на корректность. Это значит, что можно выйти за пределы массива и обратиться к памяти, находящейся дальше последнего элемента массива (или ближе).

Начальная инициализация массива.

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

#include #include void main() { int a = {1, 2, 5, 3, 9, 6, 7, 7, 2, 4}; unsigned i; int max; max = a; for (i = 1; i<10; i++) { if (a[i] >

Разберём пример. Сначала мы создаём массив и инициализируем его при создании. После этого присваиваем максимальному найденному элементу значение первого элемента массива.

Max = a;

После чего проходим по массиву. Так как мы уже просмотрели первый элемент (у него индекс 1), то нет смысла снова его просматривать.
Тот же пример, только теперь пользователь вводит значения

#include #include void main() { int a; unsigned i; int max; printf("Enter 10 numbers\n"); for (i = 0; i<10; i++) { printf("%d. ", i); scanf("%d", &a[i]); } max = a; for (i = 1; i<10; i++) { if (a[i] > max) { max = a[i]; } } printf("max element is %d", max); getch(); }

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

#include #include void main() { int a = {1,2,3}; unsigned i; for (i = 0; i<10; i++) { printf("%d ", a[i]); } getch(); }

Если необходимо заполнить весь массив нулями, тогда пишем

Int a = {0};

Можно не задавать размер массива явно, например

Int a = {1, 2, 3};

массив будет иметь размер 3

Размер массива

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

Printf("Enter length of array "); scanf("%d", &length); { float x; }

Создание динамических массивов будет рассмотрено дальше, при работе с указателями и памятью
В некоторых случаях можно узнать размер массива с помощью функции sizeof.

#include #include void main() { int A; //sizeof возвращает размер всего массива в байтах //Для определения количества элементов необходимо //разделить размер массива на размер его элемента int size = sizeof(A) / sizeof(int); printf("Size of array equals to %d", size); getch(); }

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

Переполнение массива

П ускай у вас есть такой код

Int A; int i; for (i=0; i<=10; i++) { A[i] = 1; }

Здесь цикл for задан с ошибкой. В некоторых старых версиях компиляторов этот код зацикливался. Дело в том, что переменная i располагалась при компиляции сразу за массивом A . При выходе за границы массива счётчик переводился в 1.
Массивы небезопасны, так как неправильная работа с индексом может приводить к доступу к произвольному участку памяти (Теоретически. Современные компиляторы сами заботятся о том, чтобы вы не копались в чужой памяти).
Если вы работаете с массивами, то необходимо следить за тем, чтобы счётчик не превышал размер массива и не был отрицательным. Для этого, как минимум,

  • 1. Используйте тип size_t для индексирования. Он обезопасит вас от отрицательных значений и его всегда хватит для массива любого размера.
  • 2. Помните, что массив начинается с нуля.
  • 3. Последний элемент массива имеет индекс (размер массива - 1)
Никаких полноценных способов проверки, вышли мы за пределы массива или нет, не существует. Поэтому либо мы точно знаем его размер, либо храним в переменной и считываем при надобности.

Примеры

Т еперь несколько типичных примеров работы с массивами
1. Переворачиваем массив.

#include #include //Это макрос. SIZE в коде будет заменено на 10u #define SIZE 10u void main() { int A = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; unsigned i, j; //счётчики unsigned half; //середина массива unsigned tmp; //временная переменная для обмена значениями half = SIZE / 2; //Один счётчик идёт слева напрво, другой справа налево for (i = 0, j = SIZE - 1; i < half; i++, j--) { tmp = A[i]; A[i] = A[j]; A[j] = tmp; } for (i = 0; i < SIZE; i++) { printf("%d ", A[i]); } getch(); }

Здесь незнакомая для вас конструкция

#define SIZE 10u

макрос. Во всём коде препроцессор автоматически заменит все вхождения SIZE на 10u.
2. Удаление элемента, выбранного пользователем.

#include #include #define SIZE 10u void main() { int A = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}; unsigned i; //счётчик int index; //индекс, введённый пользователем //Выводим массив for (i = 0; i < SIZE; i++) { printf("(%d)=%d ", i, A[i]); } //Просим пользователя ввести валидный индекс while (1) { printf("\nEnter index of element to delete "); scanf("%d", &index); if (index > 0 && index < SIZE) { break; } } //Копируем следующий элемент массива на место удаляемого //и так до конца for (i = index; i < SIZE-1; i++) { A[i] = A; } //Выводим результат for (i = 0; i < SIZE-1; i++) { printf("(%d)=%d ", i, A[i]); } getch(); }

Удаление элемента в данном случае, конечно, не происходит. Массив остаётся того же размера, что и раньше. Мы просто затираем удаляемый элемент следующим за ним и выводим SIZE-1 элементов.
3. Пользователь вводит значения в массив. После этого вывести все разные значения, которые он ввёл.
Пусть пользователь вводит конечное число элементов, допустим 10. Тогда заранее известно, что всего различных значений будет не более 10. Каждый раз, когда пользователь вводит число будем проходить по массиву и проверять, было ли такое число введено.

#include #include #define SIZE 10u void main() { int A = {0}; unsigned i, j; int counter = 1; //сколько разных чисел введено. Как минимум одно. int input; int wasntFound; //флаг, что введённое число не было найдено //Вводим первое число. Оно ещё не встречалось. printf("0. "); scanf("%d", &A); for (i = 1; i < SIZE; i++) { printf("%d. ", i); scanf("%d", &input); wasntFound = 1; //Проверяем, встречалось ли такое число. Если да, //то выставляем флаг и выходим из цикла for (j = 0; j <= counter; j++) { if (input == A[j]) { wasntFound = 0; break; } } //Если флаг был поднят, то заносим число в массив if (wasntFound) { A = input; counter++; } } for (i = 0; i < counter; i++) { printf("%d ", A[i]); } getch(); }

4. Пользователь вводит число - количество измерений (от 2 до 10). После этого вводит все измерения. Программа выдаёт среднее значение, дисперсию, погрешность.

#include #include #include #define SIZE 20u void main() { //Коэффициенты Стьюдента идут, начиная с двух измерений const float student = {12.7, 4.3, 3.2, 2.8, 2.6, 2.4, 2.4, 2.3, 2.3}; float A; unsigned i; unsigned limit; float tmp; float sum = .0f; float mean; float disp; float absError; float relError; do { printf("Enter number of measurements "); scanf("%u", &limit); if (limit > 1 && limit < 11) { break; } } while(1); for (i = 0; i < limit; i++) { printf("#%d: ", i); scanf("%f", &A[i]); sum += A[i]; } mean = sum / (float)limit; sum = .0f; for (i = 0; i < limit; i++) { tmp = A[i] - mean; sum += tmp * tmp; } disp = sum / (float)limit; absError = student * sqrt(sum / (float)(limit - 1)); relError = absError / mean * 100; printf("Mean = %.6f\n", mean); printf("Dispertion = %.6f\n", disp); printf("Abs. Error = %.6f\n", absError); printf("Rel. Error = %.4f%", relError); getch(); }

5. Сортировка массива пузырьком

#include #include #define SIZE 10 #define false 0 #define true !false void main() { float a = {1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f, 9.0f, 0.0f}; float tmp; unsigned i, j; char flag; //Выводи массив for (i = 0; i < SIZE; i++) { printf("%.3f ", a[i]); } printf("\n"); //Пока массив не отсортирован do { flag = false; //Проходим по массиву. Если следующий элемент больше предыдущего, то //меняем их местами и по новой проверяем массив for (i = 1; i < SIZE; i++) { if (a[i] > a) { tmp = a[i]; a[i] = a; a = tmp; flag = true; } } } while(flag == true); //Выводим отсортированный массив for (i = 0; i < SIZE; i++) { printf("%.3f ", a[i]); } getch(); }

6. Перемешаем массив. Воспользуемся для этого алгоритмом

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

Как объявлять массивы в си?

Как инициализировать массивы в си?

Массивы в Си для чайников.

Массивы в C

Массив в Си - это набор элементов одного типа, обратиться к которым можно по индексу. Элементы массивов в C расположены друг за другом в памяти компьютера.

Простой пример создания и заполнения массива в C:

// @author Subbotin B.P..h> void main(void) { int nArr; nArr = 1; nArr = 2; nArr = 3; printf("\n\tArray\n\n"); printf("nArr\t=\t%d\n", nArr); printf("nArr\t=\t%d\n", nArr); printf("nArr\t=\t%d\n", nArr); return 0; }

Получаем:

В примере объявляем массив, содержащий элементы типа int:

здесь имя массива nArr, количество элементов массива равно трём, тип элементов массива int.

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

Присвоим значение второму элементу массива, а второй элемент имеет индекс один:

Присвоим значение третьему элементу массива, а третий элемент имеет индекс два:

При выводе на экран элементов массива мы получаем их значения. Вот так:

printf("nArr\t=\t%d\n", nArr);

Чтоб получить элемент массива, надо указать имя массива и индекс элемента:

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

Присвоим значение третьего элемента массива переменной int a:

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

Теперь общее правило объявления массивов в Си: при объявлении массива нужно указать его имя, тип элементов, количество элементов. Количество элементов есть натуральное число, т.е. целое положительное. Ноль не может быть количеством элементов. Нельзя задавать переменное количество элементов массива. Вот примеры объявлений массивов в C:

int nArr; // Объявлен массив, предназначенный для хранения ста целых чисел;
float fArr; // Объявлен массив, предназначенный для хранения 5-ти чисел типа float;
char cArr; // Объявлен массив, предназначенный для хранения двух символов;

Ошибкой будет объявить массив с переменным количеством элементов:

Int varElem;
int nArr; // Ошибка! Количество элементов нельзя задавать переменной;

Но можно задавать количество элементов постоянной величиной: или непосредственным целым положительным числом 1, 2, 3... или константой:

Const int arrayLength = 3;
int nArr;

При объявлении массива в Си его сразу можно инициализировать:

int nMassiv = {1, 2, 3};

Можно не указывать количество элементов массива в квадратных скобках, если инициализируются все элементы массива:

int nMassiv = {1, 2, 3};

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

Можно определить лишь часть элементов массива при его объявлении:

int nMassiv = {1, 2};

в этом примере первые два элемента массива инициализированы, а третий не определен.

Пример массива символов:

char cArr = {"S", "B", "P"};

При объявлении массива нельзя указывать количество элементов переменной. Но можно использовать переменные при обращении к элементам массивов:

Int ind = 0;
char cr = cArr;

Это используется при работе с циклами. Пример:

// @author Subbotin B.P..h> void main(void) { const int arrayLength = 3; int nArr; for(int inn = 0; inn < 3; inn++) { nArr = inn + 1; } printf("\n\tArray\n\n"); for(int inn = 0; inn < 3; inn++) { printf("nArr[%d]\t=\t%d\n", inn, nArr); } return 0; }

В примере в первом цикле заполняем массив элементами типа int, а во втором цикле выводим эти элементы на экран.

Массивы предназначены для хранения множества значений одного типа. Например, в программе Fahrenheit to Celsius, мы высчитывали среднее значение температуры из трёх. Если значений не три, а намного больше, то тут как раз и нужно использовать массивы.

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

int array;

В этом коде мы определили массив с идентификатором (именем) array (массив) из десяти элементов типа int.
В таком виде, все элементы массива ещё неинициализированы. Чтобы инициализировать их при обьявлении, нужно использовать следующий синтаксис:

int array = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};

При этом, первому элементу массива присваивается значение 0, а последнему - значение 9.
Чтобы присвоить элементам массива значение, можно воспользоваться циклами. Самым подходящим для этого будет цикл for.

код на языке c++ int array; //определение массива for (int i = 0; i < 10; i++) { array[i] = i; }

Здесь мы обращаемся к каждому элементу массива через индекс - число стоящее в квадратных скобках. При каждой итерации цикла оно принимает значения от нуля до 9.

Заметьте, что нумерация индексов начинается с нуля. Поэтому число индексов всегда на единицу меньше числа элементов массива.

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

Строки

До сих пор мы могли хранить строки только в константах: "Пример константной строки". В переменных мы могли хранить только один символ - в типе char. В C++ используется два типа строк: массив элементов типа char и тип str. Сейчас мы сосредоточимся на первом варианте.

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

char string = {"с","т","р","о"."к","а"};

К счастью есть более простой способ:)

char string = "строка";

В данном случае автоматически создастся массив из семи элементов. Почему из семи? Дело в том что каждая строка должна заканчиваться символьной константой "\0", которая представляет пустой байт.

В предыдущих примерах, если мы попытаемся ввести в массив string строку большую чем шесть символов, то произойдёт переполнение массива т.к. нельзя изменять размер массива во время выполнения программы (хотя, не всегда):

char string; // string может хранить шесть символов и "\0"

string = "строка!"; // в строке содержится семь символов
Так делать не рекомендуется:)

Ещё один момент на который я хочу обратить ваше внимание. В случае, когда пользователь вводит строку, пробелы считаются за "\0". Мы пока не будем вводить строки в наших программах, поэтому я не буду подробно объяснять данный случай.

Массивы массивов (двумерные массивы)

Ну и наконец-то мы подошли к самому важному в этом выпуске.

Карта в стратегических (и не только) играх (RTS) делится на клетки (в английском - tile, плитка). Эти клетки удобно представлять с помощью двумерного массива.

В данном примере мы продолжим работать с программой pseudo_game и с помощью двумерного массива смоделируем карту по которой может перемещаться игрок. До сих пор "перемещиение" представлялось с помощью координат x, y.

Клетки мы будем представлять символами. Размер "карты" - 15x20. Пятнадцать в высоту, двадцвать в ширину. Игрока мы будем представлять символом Т.

Сначала добавьте заголовочный файл stdlib.h.

Усовершенствованная pseudo_game

Я приведу только куски кода. Желательно чтобы у вас перед глазами была полная программа. Найти её Вы можете в разделе "листинги программ" - pseudo_game_0_2. Она компилируется и запускается. Просто скопируйте её в редактор вашей IDE и следите за текстом.

Инициализация данных:

код на языке c++ char act; // переменная для считывания ввода пользователя int ch; // переменная для хранения приведённого значения переменной act int x = 0; // две переменные для хранения координат игрока int y = 0; char map; // массив для хранения игровой карты // инициализация массива for (int i = 0; i < 15; i++) { for (int j = 0; j < 20; j++) { map[i][j] = " "; } } map = "T";

Здесь новым оператором для нас является определение двумерного массива. Но оно почти ничем не отличается от одномерного, просто добавляется ещё одна пара квадратных скобок. В первых скобках мы указали количество строк, во второй - количество столбцов.

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

Приведу подробный пример: после нескольких итераций внешнего цикла, счётчик i становится равным 9. Начинает выполняться тело внешнего цикла: переменная j (счётчик внутреннего цикла) инициализируется нулём, проверяется условие и выполняется тело внутреннего цикла: map = " ";, То есть первому символу (индекс ноль) десятой строки (не забывайте что отсчёт ведётся с нуля) присваивается пробел. Затем, счётчику j присваивается 1, выполняется тело цикла... и так до тех пор пока счётчик j не станет равным 20 - условие не выполняется и происходит выход из внутреннего цикла. Затем инкрементируется внешний счётчик. Теперь он равен 10 и снова выполняется тело внешнего цикла...

После инициализации пробелами мы в первый столбец первой строки помещаем персонажа нашей игры.

В начале основного цикла мы вызываем функцию system() для очистки экрана от прошлого вывода.

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

Ну а дальше идёт ветвление в котором определяется какая клавиша нажата. Само ветвление мало изменилось с прошлого раза, а вот в содержимом блоков есть отличия: во-первых мы присваиваем координатам на которых стоит объект пробел. То есть мы очищаем предыдущее место. Затем мы изменяем одну из координат. И затем, элементу массива с новыми индексами, мы присваиваем символ "T".

Пример для кода "75" - движение влево:

код на языке c++ if else (ch == 75) { map[x][y] = " "; y--; map[x][y] = "T"; }

Ну, вот в общем и всё. На данный момент у нас есть карта 15х20 по которой с помощью стрелочек можно перемещать персонаж - букву "T". Для шестого урока неплохо! Данное приложение станет основой для всех наших консольных программ. Никаких графических улучшений не будет. Большего из досовской консоли просто не выжать, а консоль windows мы рассматривать не будем. Это существенно сэкономит время и силы.

Я подробно закомментировал программу pseudo_game и Вы скорее всего без труда в ней разберётесь. Если нет, то перечитывайте листинг программы и этот выпуск пока не разберётесь:). Закрепить материал вам помогут упражнения. Выполнение упражнений обязательно. Если что непонятно, пишите на мой e-mail - постараюсь помочь.

Упражнения:

1. В полном листинге программы я использовал ветвление switch. Здесь же показан код одного блока ветвления if. Допишите остальные блоки if.

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

3. Для практики создайте программу рисующую на экране два поля для морского боя. Первое - игрока, второе - противника. Второе поле должно располагаться справа от первого.
Внутренние клетки заполняйте пробелом. Для рисования границы используйте минус и прямую разделительную черту: -, |, а для углов - решётку #. Слева от каждого поля - стобик цифр; сверху - буквы.
Для инициализации всего поля вам может понадобиться несколько циклов. Вот как может выглядеть код для заполнения столбика цифр второго поля:

код на языке c++ int string; // переменная представляющая строки int column; // переменная представляющая столбцы char map; column = 15; for (string = 2; string < 12; string++) { map = string - 1; }

THE BELL

Есть те, кто прочитали эту новость раньше вас.
Подпишитесь, чтобы получать статьи свежими.
Email
Имя
Фамилия
Как вы хотите читать The Bell
Без спама