Как объявить массив для инт и флоат
КАК победить массив?
Вопрос: КАК применяются массивы?
Наверное, если раньше вы не встречались с этим словом, само понятие "массив" у вас вызывает исключительно архитектурные ассоциации: "жилой массив". Это своего рода набор зданий, расположенных на некоторой территории. Массив в программировании на любом языке — это набор данных одного типа (int, float, double. ), также объединённых на одной территории. КАК? Сейчас расскажу.
До сих пор мы задавали отдельно переменные: int a=9; float f=4.14, char *str="Машина". Однако, вы удивитесь, когда я скажу, что массивы мы давно уже используем. А вы-то и не знали. Когда мы задавали строчку:
мы объявляли массив типа char, иными словами резервировали некоторую область памяти, длиной в 6 ячеек или клеточек (0, 1, 2, 3, 4, 5), в которую записывали символы типа char. В каждой клеточке может храниться только один символ. В любой момент мы могли обратиться к любому символу, используя индексацию, номер этой клеточки. Так, команда:
даст нам на экране букву: "ш". Если же мы напишем такое выражение:
то в строке str (массиве str), будет записано: "пашина".
Идём дальше. Используя индексацию, мы можем вывести слово наоборот:
int i;
for(i=0; i<strlen(str)-1; i++) //вывод элементов массива
cout<<str[i]<<endl;
Меняя переменную цикла i от 0 до длины строки str -1, то есть до 6-1=5, мы последовательно выводим её содержимое на экран в столбик.
Так же можно осуществить и заполнение массива значениями:
int i;
for(i=0; i<strlen(str)-1; i++) //ввод элементов массива
cin>>str[i]>>endl;
Учтите, что число элементов массива меняться не может! Чтобы знать свои права, рассмотрим остальные свойства массивов.
Вопрос: КАКие свойства у массивов?
Свойства массивов:
1. В массиве хранятся отдельные значения, которые называются элементами.
2. Все элементы массива должны быть одного типа данных (int, float, char*. ).
3. Все элементы хранятся в памяти последовательно, и первый имеет нулевой адрес.
4. Имя массива является константой и содержит адрес первого элемента массива.
Массивы могут состоять не только из символов, но и из строк. Представьте себе, что вы пишите игру-говорилку, где игрок попадает в гости к симпатичной девушке, которая вступает с ним в диалог. От того, как он ответит на них, зависит обломится ему что-то или нет. Поскольку мы сами не можем говорить за электронную девушку, должен быть какой-то набор фраз, из которого случайным образом выбирается какая-то одна. Программным языком выражаясь, мы создаём массив строк. Выбирая случайным образом индекс i, мы выводим на экран фразу: cout<<massiv[i]; i может быть и 0 и 20 и 40, поэтому вопросы и высказывания девушки не предсказуемы. А задать такой массив можно так:
Обратите внимание, что объявляя массив, мы помещаем его элементы в фигурные скобки, разделяя их запятыми. В конце обязательно надо поставить ;
Вопрос: КАК объявляются и применяются массивы float?
Массивы float
Пример1. Найти среднее арифметическое элементов заданного массива.
#include<stdio.h>
#define TEN 10 //так объявляются константы. Менять значения TEN после этого объявления мы не имеем права
//Здесь же константе TEN мы присвоили значение 10
void main()
<
float a[TEN], s=0; //мы объявили массив типа float из TEN(десяти) элементов и переменную s
int i; //переменная цикла
printf( "Введите массив: " );
for(i=0; i<TEN; i++)
scanf("%d", m[i]); /*последовательный ввод массива*/
for(i=0; i<TEN; i++)
s = s+a[i]; /*нахождение суммы элементов*/
s=s/TEN; //нахождение среднего арифметического делением суммы на TEN, то есть на 10
printf( "s = %8.2f" , s);
>
Как видите, работа с массивами почти не отличается от работы с обычными числами. Удобно представлять массивы, как наборы чисел. Как правило инициализация, ввод и вывод элементов массива осуществляются через цикл for, так как в данном случае заранее известно число элементов.
Вопрос: КАК ещё объявляются массивы?
Вот примеры объявления массивов разных типов:
char masc4[]="Rock"; //когда заранее не известно сколько элементов
Вопрос: КАК с помомщью массива строк заставить компьютер говорить?
Игра-"Говорилка".
Хочется верить, что я заинтриговал вас словами об игре-говорилке, в которой ведётся диалог с компьютерной девушкой. В своё время я сам написал такую игру, под названием "Ночное рандеву". Теперь ваша очередь. Думаю, когда я дам вам в руки средства Windows, вы без труда сможете украсить свою игру полями ввода, кнопками, картинками и цветами. Пока же предлагаю вам заготовку. Строковый массив, элементы которого выводятся случайно. Заодно мы поговорим о случайных числах.
#include<iostream.h>
#include<iomanip.h>
#include<stdlib.h>
#include<string.h>
#include<time.h>
#define SIZE 4
srand(time(NULL)); //обнуляем генератор случайных чисел
//задаём цикл, который работает
do <
i=rand()%4;
cout<< "Компьютеp: " <<mas[i]<<endl<< "Человек: " ;
cin>>ans;
>while(strncmp(ans, "exit",10)!=0); //пока пользователь не введёт слово "exit"
Вопрос: КАК сортировать элементы массива? Метод пузырька.
Часто при хранении разного рода информации сталкиваются с проблемой её сортировки. Пусть мы храним фамилии целого взвода солдат в базе данных. Мы бы хотели, чтобы каждый раз они выводились на экран в алфавитном порядке. Тем не менее, введены они были, возможно вразнобой, и, кроме того, время от времени в базу данных добавляют новые фамилии, а старые удаляют. Программа же должна работать всегда. Есть много разных алгоритмов сортировки. Самый простой — метод пузырька, потому что наименьшее значение постоянно "всплывает", двигаясь к вершине массива, как пузырь воздуха двигается к поверхности воды. Для примера можем рассмотреть не строки, а простые числа типа int.
#include<iostream.h>
#include<iomanip.h>
#define SIZE 10
void main()
<
int mas[SIZE]=<2, 6, 4, 8, 10, 12, 89, 68, 45, 37>; //массив целых чисел
int hold; //переменная — буфер
cout<<"Элементы в исходном порядке: "<<endl;
for(int i=0; i<SIZE; i++) //выводим на экран массив mas
cout<<mas[i];
for(int p=1; p<SIZE; p++) //Запускаем 1-й цикл
for(i=0; i<SIZE-1; i++) //в котором выполняется второй
if(mas[i]>mas[i+1]) //Если предыдущее число больше последущего
<
hold=mas[i]; //предыдущее записывается в буфер
mas[i]=mas[i+1]; //в предыдущее записывается число из последующего
mas[i+1]=hold; //в последующее записывается число из буфера
>
cout<<"Элементы в исходном порядке "<<endl;
Существуют также двумерные и n-мерные массивы, применение которых требуется реже, чем одномерных массивов. Их мы рассмотрим в разделе "структуры данных".
Читать про массивы в теории — очень скучно. Гораздо приятнее использовать их на практике. Дав вам сейчас этот инструмент, я нераз буду слышать слова вашей благодарности за то, что рассказал про них.
Как объявить массив для инт и флоат
Наверное, если раньше вы не встречались с этим словом, само понятие "массив" у вас вызывает исключительно архитектурные ассоциации: "жилой массив". Это своего рода набор зданий, расположенных на некоторой территории. Массив в программировании на любом языке — это набор данных одного типа (int, float, double. ), также объединённых на одной территории. КАК? Сейчас расскажу.
До сих пор мы задавали отдельно переменные: int a=9; float f=4.14, char *str="Машина". Однако, вы удивитесь, когда я скажу, что массивы мы давно уже используем. А вы-то и не знали. Когда мы задавали строчку:
мы объявляли массив типа char, иными словами резервировали некоторую область памяти, длиной в 6 ячеек или клеточек (0, 1, 2, 3, 4, 5), в которую записывали символы типа char. В каждой клеточке может храниться только один символ. В любой момент мы могли обратиться к любому символу, используя индексацию, номер этой клеточки. Так, команда:
даст нам на экране букву: "ш". Если же мы напишем такое выражение:
то в строке str (массиве str), будет записано: "пашина".
Идём дальше. Используя индексацию, мы можем вывести слово наоборот:
int i;
for(i=0; i<strlen(str)-1; i++) //вывод элементов массива
cout<<str[i]<<endl;
Меняя переменную цикла i от 0 до длины строки str -1, то есть до 6-1=5, мы последовательно выводим её содержимое на экран в столбик.
Так же можно осуществить и заполнение массива значениями:
int i;
for(i=0; i<strlen(str)-1; i++) //ввод элементов массива
cin>>str[i]>>endl;
Учтите, что число элементов массива меняться не может! Чтобы знать свои права, рассмотрим остальные свойства массивов.
Вопрос: КАКие свойства у массивов?
Свойства массивов:
1. В массиве хранятся отдельные значения, которые называются элементами.
2. Все элементы массива должны быть одного типа данных (int, float, char*. ).
3. Все элементы хранятся в памяти последовательно, и первый имеет нулевой адрес.
4. Имя массива является константой и содержит адрес первого элемента массива.
Массивы могут состоять не только из символов, но и из строк. Представьте себе, что вы пишите игру-говорилку, где игрок попадает в гости к симпатичной девушке, которая вступает с ним в диалог. От того, как он ответит на них, зависит обломится ему что-то или нет. Поскольку мы сами не можем говорить за электронную девушку, должен быть какой-то набор фраз, из которого случайным образом выбирается какая-то одна. Программным языком выражаясь, мы создаём массив строк. Выбирая случайным образом индекс i, мы выводим на экран фразу: cout<<massiv[i]; i может быть и 0 и 20 и 40, поэтому вопросы и высказывания девушки не предсказуемы. А задать такой массив можно так:
Обратите внимание, что объявляя массив, мы помещаем его элементы в фигурные скобки, разделяя их запятыми. В конце обязательно надо поставить ;
Вопрос: КАК объявляются и применяются массивы float?
Массивы float
Пример1. Найти среднее арифметическое элементов заданного массива.
#include<stdio.h>
#define TEN 10 //так объявляются константы. Менять значения TEN после этого объявления мы не имеем права
//Здесь же константе TEN мы присвоили значение 10
void main()
Как видите, работа с массивами почти не отличается от работы с обычными числами. Удобно представлять массивы, как наборы чисел. Как правило инициализация, ввод и вывод элементов массива осуществляются через цикл for, так как в данном случае заранее известно число элементов.
Вопрос: КАК ещё объявляются массивы?
Вот примеры объявления массивов разных типов:
char masc4[]="Rock"; //когда заранее не известно сколько элементов
Вопрос: КАК с помомщью массива строк заставить компьютер говорить?
Игра-"Говорилка".
Хочется верить, что я заинтриговал вас словами об игре-говорилке, в которой ведётся диалог с компьютерной девушкой. В своё время я сам написал такую игру, под названием "Ночное рандеву". Теперь ваша очередь. Думаю, когда я дам вам в руки средства Windows, вы без труда сможете украсить свою игру полями ввода, кнопками, картинками и цветами. Пока же предлагаю вам заготовку. Строковый массив, элементы которого выводятся случайно. Заодно мы поговорим о случайных числах.
#include<iostream.h>
#include<iomanip.h>
#include<stdlib.h>
#include<string.h>
#include<time.h>
#define SIZE 4
srand(time(NULL)); //обнуляем генератор случайных чисел
//задаём цикл, который работает
do while(strncmp(ans, "exit",10)!=0); //пока пользователь не введёт слово "exit"
Вопрос: КАК сортировать элементы массива? Метод пузырька.
Часто при хранении разного рода информации сталкиваются с проблемой её сортировки. Пусть мы храним фамилии целого взвода солдат в базе данных. Мы бы хотели, чтобы каждый раз они выводились на экран в алфавитном порядке. Тем не менее, введены они были, возможно вразнобой, и, кроме того, время от времени в базу данных добавляют новые фамилии, а старые удаляют. Программа же должна работать всегда. Есть много разных алгоритмов сортировки. Самый простой — метод пузырька, потому что наименьшее значение постоянно "всплывает", двигаясь к вершине массива, как пузырь воздуха двигается к поверхности воды. Для примера можем рассмотреть не строки, а простые числа типа int.
#include<iostream.h>
#include<iomanip.h>
#define SIZE 10
void main()
; //массив целых чисел
int hold; //переменная — буфер
cout<<"Элементы в исходном порядке: "<<endl;
for(int i=0; i<SIZE; i++) //выводим на экран массив mas
cout<<mas[i];
for(int p=1; p<SIZE; p++) //Запускаем 1-й цикл
for(i=0; i<SIZE-1; i++) //в котором выполняется второй
if(mas[i]>mas[i+1]) //Если предыдущее число больше последущего
cout<<"Элементы в исходном порядке "<<endl;
Существуют также двумерные и n-мерные массивы, применение которых требуется реже, чем одномерных массивов. Их мы рассмотрим в разделе "структуры данных".
Читать про массивы в теории — очень скучно. Гораздо приятнее использовать их на практике. Дав вам сейчас этот инструмент, я нераз буду слышать слова вашей благодарности за то, что рассказал про них.
1. Массивы
больших объемов данных. При размещении большого количества данных в памяти возникает такая проблема: надо научиться обращаться к каждой ячейке с данными отдельно. При этом очень сложно дать каждой ячейке собственное имя и при этом не запутаться. Выкручиваются из этой ситуации так: дают имя не ячейке, а группе ячеек, в которой каждая ячейка имеет номер. Такая область памяти называется массивом.
Массив – это группа ячеек памяти одинакового типа, расположенных рядом и имеющих
общее имя. Каждая ячейка в группе имеет уникальный номер.
При работе с массивами надо научиться решать три задачи:
• выделять память нужного размера под массив
• записывать данные в нужную ячейку
• читать данные из ячейки
Объявление массива
Чтобы использовать массив, надо его объявить – выделить место в памяти. Типом массива
называется тип массива это тип входящих в него элементов. Массивы могут быть разных типов— int, float, char, и т.д. Массив объявляют так же, как и обычные переменные, но после имени массива в квадратных скобках записывается его размер.
Int a[10], b[20]; // 2 массива на 10 и 20 целых чисел
float C[12]; // массив из 12 вещественных чисел
При объявлении массива можно сразу заполнить его начальными значениями, перечисляя их внутри фигурных скобок:
Если в списке в фигурных скобках записано меньше чисел, чем элементов в массиве, то
оставшиеся элементы заполняются нулями. Если чисел больше, чем надо, транслятор сообщает об ошибке. Например,
int A[4] = ; // последние три элементы равны 0
Для повышения универсальности программы размер массива лучше определять через константу. В этом случае для переделки программы для массива другого размера надо только поменять значение этой константы:
В таблице показаны примеры правильного и неправильного объявления массива.

Обращение к элементу массива
Каждый элемент массива имеет свой порядковый номер. Чтобы обратиться к элементу
массива, надо написать имя массива и затем в квадратных скобках номер нужного элемента.Важно запомнить одно важное правило:Элементы массивов в языке Си нумеруются с нуля. Таким образом, если в массиве 10 элементов, он содержит элементы:
Номер элемента массива также называется его индексом. Вот примеры обращения к массиву A:
x = (A[3] + 5)*A[1]; // прочитать значения A[3] и A[1]
A[0] = x + 6; // записать новое значение в A[0]
В языке Си не контролируется выход за границы массива, то есть формально вы можете записать что-то в элемент с несуществующим индексом, например в A[345] или в A[-12]. Однако при этом вы стираете какую-то ячейку в памяти, не относящуюся к массиву, поэтому последствия такого шага непредсказуемы и во многих случаях программа «зависает».
Ввод с клавиатуры и вывод на экран
Как же ввести данные в массив? Существует много способов в зависимости от вашей задачи:
• элементы массива вводятся с клавиатуры вручную;
• массив заполняется случайными числами (например, для моделирования случайных процессов);
• элементы массива читаются из файла;
• элементы массива поступают через порт с внешнего устройства (например, сканера, модема и т.п.);
• массив заполняется в процессе вычислений.
Задача. Ввести с клавиатуры массив из 10 элементов, умножить все элементы на 2 и вывести полученный массив на экран.К сожалению, невозможно просто сказать компьютеру: «введи массив A». Мы должны каждый элемент прочитать отдельно.
Чтобы ввести массив в память, надо каждый его элемент обработать отдельно (например,
вызвав для него функцию ввода scanf).Ввод с клавиатуры применяется в простейших программах, когда объем вводимой информации невелик. Для ввода массива будем использовать цикл for. Напомним, что массив надо предварительно объявить, то есть выделить под него память. Вводить можно столько элементов массива, сколько ячеек памяти выделено. Помните, что элементы массива нумеруются с нуля, поэтому если массив имеет всего 10 элементов, то последний элемент имеет номер 9. Если пытаться записывать в 10-ый элемент, произойдет выход за границы массива, и программа может работать неверно (а, возможно, и «зависнет»). При вводе массива желательно выдать на экран общую подсказку для ввода всего массива и подсказки для каждого элемента.
Для умножения элементов массива на 2 надо снова использовать цикл, в котором за один
раз обрабатывается 1 элемент массива. Вывод массива на экран выполняется также в цикле for. Элементы выводятся по одному. Если в конце строки-формата в операторе printf поставить пробел, то элементы массива будут напечатаны в строчку, а если символ \n – то в столбик.
Понятие массива. Одномерные массивы
Массив – это набор (группа) однотипных элементов, объединенных одним именем. Массивы позволяют удобно группировать информацию и получать доступ к ней.
Массивы могут быть одномерными, двумерными и многомерными.
Позиция элемента в массиве называется индексом. В языке Java позиция первого элемента в массиве начинается с нуля.
Массив считается одномерным, если для определения местоположения элемента в массиве нужно указать значение одного индекса.
Массив считается двумерным, если для определения местоположения элемента в массиве нужно указать значения двух индексов.
⇑
2. Какие типы данных могут принимать элементы массива?
Элементы массива могут быть любого типа, допустимого в языке Java .
Этот тип определяет тип данных любого из элементов, которые составляют данный массив.
⇑
3. Как выглядит общая форма описания одномерного массива?
Общая форма описания одномерного массива:
- тип — означает тип элемента массива, который называется также базовым типом;
- имя_переменной — название массива, по которому будет осуществляться доступ к элементам массива.
После этого нужно выделить память под массив. Общая форма выделения памяти имеет вид:
- тип – базовый тип элементов массива;
- размер– число элементов массива.
Выделение памяти для элементов массива можно осуществлять сразу после его описания. В этом случае общая форма описания массива имеет вид:
При выделении памяти элементы массива заполняются:
- нулевыми значениями для числовых типов;
- значениями false для логического типа boolean ;
- пустыми значениями null для ссылочных типов.
Итак, процесс создания массива проходит в два этапа:
- объявляется переменная нужного типа массива;
- с помощью оператора new выделяется память для элементов массива.
⇑
4. Пример создания и использования одномерного массива с именем d , в котором есть 5 элементов типа int .
В данном примере создание массива можно осуществлять разными способами.
⇑
5. Пример создания и использования одномерного массива f , содержащего 10 элементов типа float .
⇑
6. Пример создания и использования одномерного массива x , в котором 20 элементов имеют тип double .
⇑
7. Пример фрагмента кода обнуления одномерного массива с именем x , содержащего 20 чисел типа double .
В данном примере обнуляется массив вещественных чисел типа double .
⇑
8. Пример вычисления суммы элементов одномерного массива M , в котором есть 50 вещественных чисел.
⇑
9. Пример поиска максимального значения в массиве из 100 целых чисел.
⇑
10. Пример сортировки одномерного массива вещественных чисел методом вставки.
⇑
11. Как в Java осуществить присвоение одного массива другому? Метод clone() .
Для глубокого копирования массивов используется метод clone() из библиотеки Java .
Пример присвоения одного массива другому с использованием метода clone() .
то обе переменные f и f2 будут указывать на один участок памяти.
⇑
12. Как осуществляется начальная инициализация одномерного массива?
В программах на Java массивы можно инициализировать во время их объявления. В этом случае указывается список выражений, которые разделяются символом запятая ‘ , ‘. Этот список выражений берется в фигурные скобки.
Примеры инициализации массивов разных размерностей и разных типов их элементов.
⇑
13. Пример описания одномерного массива классов.
Пусть задан класс с именем MyPoint . Нужно описать объект-переменную, который является массивом из 3 классов MyPoint .
⇑
14. Пример описания одномерного массива интерфейсов.
Пусть задан класс с именем MyPoint . Класс реализует интерфейс MyInterface . Нужно описать объект-переменную, которая есть массивом из 5 элементов типа интерфейс MyInterface .
⇑
15. Пример описания и использования одномерного массива строк
В языке Java для работы со строками введен особый класс String . В данном примере продемонстрированы операции:
Массивы в языке Си
При решении задач с большим количеством данных одинакового типа использование переменных с различными именами, не упорядоченных по адресам памяти, затрудняет программирование. В подобных случаях в языке Си используют объекты, называемые массивами.
Массив — это непрерывный участок памяти, содержащий последовательность объектов одинакового типа, обозначаемый одним именем.
Массив характеризуется следующими основными понятиями:
Элемент массива (значение элемента массива) – значение, хранящееся в определенной ячейке памяти, расположенной в пределах массива, а также адрес этой ячейки памяти.
Каждый элемент массива характеризуется тремя величинами:
- адресом элемента — адресом начальной ячейки памяти, в которой расположен этот элемент;
- индексом элемента (порядковым номером элемента в массиве);
- значением элемента.
Адрес массива – адрес начального элемента массива.
Имя массива – идентификатор, используемый для обращения к элементам массива.
Размер массива – количество элементов массива
Размер элемента – количество байт, занимаемых одним элементом массива.
Графически расположение массива в памяти компьютера можно представить в виде непрерывной ленты адресов. 
Представленный на рисунке массив содержит q элементов с индексами от 0 до q-1 . Каждый элемент занимает в памяти компьютера k байт, причем расположение элементов в памяти последовательное.
Адреса i -го элемента массива имеет значение
n+k·i
Адрес массива представляет собой адрес начального (нулевого) элемента массива. Для обращения к элементам массива используется порядковый номер (индекс) элемента, начальное значение которого равно 0 . Так, если массив содержит q элементов, то индексы элементов массива меняются в пределах от 0 до q-1 .
Длина массива – количество байт, отводимое в памяти для хранения всех элементов массива.
ДлинаМассива = РазмерЭлемента * КоличествоЭлементов
Для определения размера элемента массива может использоваться функция
Объявление и инициализация массивов
Для объявления массива в языке Си используется следующий синтаксис:
тип имя[размерность]= ;
Инициализация представляет собой набор начальных значений элементов массива, указанных в фигурных скобках, и разделенных запятыми.
Если количество инициализирующих значений, указанных в фигурных скобках, меньше, чем количество элементов массива, указанное в квадратных скобках, то все оставшиеся элементы в массиве (для которых не хватило инициализирующих значений) будут равны нулю. Это свойство удобно использовать для задания нулевых значений всем элементам массива.
Если массив проинициализирован при объявлении, то константные начальные значения его элементов указываются через запятую в фигурных скобках. В этом случае количество элементов в квадратных скобках может быть опущено.
При обращении к элементам массива индекс требуемого элемента указывается в квадратных скобках [] .
Результат выполнения программы: 
Однако часто требуется задавать значения элементов массива в процессе выполнения программы. При этом используется объявление массива без инициализации. В таком случае указание количества элементов в квадратных скобках обязательно.
Для задания начальных значений элементов массива очень часто используется параметрический цикл:
Результат выполнения программы 
Многомерные массивы
В языке Си могут быть также объявлены многомерные массивы. Отличие многомерного массива от одномерного состоит в том, что в одномерном массиве положение элемента определяется одним индексом, а в многомерном — несколькими. Примером многомерного массива является матрица.
Общая форма объявления многомерного массива
Элементы многомерного массива располагаются в последовательных ячейках оперативной памяти по возрастанию адресов. В памяти компьютера элементы многомерного массива располагаются подряд, например массив, имеющий 2 строки и 3 столбца,

Общее количество элементов в приведенном двумерном массиве определится как
КоличествоСтрок * КоличествоСтолбцов = 2 * 3 = 6.
Количество байт памяти, требуемых для размещения массива, определится как
КоличествоЭлементов * РазмерЭлемента = 6 * 4 = 24 байта.
Инициализация многомерных массивов
Значения элементов многомерного массива, как и в одномерном случае, могут быть заданы константными значениями при объявлении, заключенными в фигурные скобки <> . Однако в этом случае указание количества элементов в строках и столбцах должно быть обязательно указано в квадратных скобках [] .
Результат выполнения 
Однако чаще требуется вводить значения элементов многомерного массива в процессе выполнения программы. С этой целью удобно использовать вложенный параметрический цикл.
Результат выполнения 
Передача массива в функцию
Обработку массивов удобно организовывать с помощью специальных функций. Для обработки массива в качестве аргументов функции необходимо передать
- адрес массива,
- размер массива.
Исключение составляют функции обработки строк, в которые достаточно передать только адрес.
При передаче переменные в качестве аргументов функции данные передаются как копии. Это означает, что если внутри функции произойдет изменение значения параметра, то это никак не повлияет на его значение внутри вызывающей функции.
Если в функцию передается адрес переменной (или адрес массива), то все операции, выполняемые в функции с данными, находящимися в пределах видимости указанного адреса, производятся над оригиналом данных, поэтому исходный массив (или значение переменной) может быть изменено вызываемой функцией.
Пример на Си Дан массив из 10 элементов. Поменять местами наибольший и начальный элементы массива. Для операций поиска максимального элемента и обмена использовать функцию.
Результат выполнения

Пример на Си Дан массив размерности n. Вычислить произведение четных элементов
Результат выполнения 
Комментариев к записи: 139
else if (n > 100)
else
break ;
>
//введення елементів масиву B
for ( int i = 0; i < n; i++)
>
a = DInput( "Введіть a:" );
b = DInput( "Введіть b:" );
Массивы в C++
Продолжаем серию «C++, копаем вглубь». Цель этой серии — рассказать максимально подробно о разных особенностях языка, возможно довольно специальных. Это четвертая статья из серии, первые три, посвященные перегрузке в C++, находятся здесь, здесь и здесь.
Эта статья посвящена массивам. Массивы можно отнести к наиболее древним слоям C++, они пришли из первых версий C. Тем не менее, массивы вошли в объектно-ориентированную систему типов C++, хотя и с определенными оговорками. Программисту важно знать об этих особенностях, чтобы избежать потенциальных ошибок. В статье также рассмотрено другое наследие C – тривиальные типы и неинициализированные переменные. Часть нововведений C++11, С++14, С++17 затрагивают работу с массивами, все эти новые возможности также подробно описаны. Итак, попробуем рассказать о массивах все.
Оглавление
1. Общие положения
Массив является простейшим агрегатным типом. Он моделирует набор однотипных элементов, расположенных подряд в непрерывном отрезке памяти. Массивы в той или иной форме поддерживаются практически всеми языками программирования и неудивительно, что они появились в первых версиях C и затем стали частью C++.
1.1. Объявление массивов
Если T некоторый тип, N константа или выражение, вычисляемое во время компиляции, то инструкция
объявляет переменную a типа «массив из N элементов типа T » (array of N elements of the type T ). Тип N должен иметь неявное приведение к типу std::size_t , а его значение, называемое размером массива, должно быть больше нуля. Массив располагается в непрерывном отрезке памяти, под каждый элемент массива выделяется sizeof(T) байт, соответственно размер памяти, необходимой для размещения всего массива, равен N*sizeof(T) байт. Эта величина ограничена сверху платформой и компилятором. Тип массива обозначается как T[N] , то есть он включает тип элементов и размер массива. Таким образом, массивы, имеющие одинаковый тип элементов, но разный размер, будут иметь разный тип.
Такие массивы еще называют встроенными массивами (regular arrays), чтобы подчеркнуть отличие от других вариантов массивов, термин «массив» используется в программировании и в том числе в C++ достаточно широко.
Вот примеры правильных объявлений массивов:
А вот примеры некорректных объявлений массивов:
Доступ к элементам массива осуществляется через индексатор, значения индекса от 0 до N-1 . Вот пример:
Выход за границы массива не контролируется, ошибка может привести к неопределенному поведению.
В одной инструкции можно объявить несколько массивов, но размер должен быть указан для каждого.
Для типов массивов можно вводить псевдонимы. Можно использовать традиционный вариант с ключевым словом typedef :
или более современный (C++11) с ключевым словом using :
После этого массивы объявляются как простые переменные:
Это будет то же самое, что
1.2. Операторы и стандартные функции для работы с массивами
Для работы с массивами можно использовать оператор sizeof и несколько стандартных функций и макросов.
Оператор sizeof возвращает полный размер массива в байтах, то есть размер элемента умноженный на размер массива.
Макрос _countof() (в MSVS заголовочный файл <cstdlib> ) возвращает размер массива, то есть количество элементов. В С++17 появился стандартный шаблон функции std::size() , которая делает то же самое (а еще имеет перегруженную версию, которая определяет размер стандартного контейнера).
В C++11 в стандартной библиотеке появились свободные (не члены) шаблоны функций std::begin() и std::end() . Вызванная для массива std::begin() возвращает указатель на первый элемент массива, std::end() на past-the-last элемент. (Есть также константные версии: std::cbegin() , std::cend() .) Это позволяет использовать массивы в диапазонном for .
А также в стандартных алгоритмах:
1.3. Размещение в памяти
Если массив объявлен статически, то есть в глобальной области видимости, в области видимости пространства имен или в качестве статического члена класса, то он размещается в статической памяти. Массивам, объявленным локально, память выделяется на стеке. (Естественно, надо учитывать ограниченный размер стека при выборе размера локальных массивов.) Нестатические члены класса размещаются в границах экземпляра класса. Динамические массивы (см. раздел 6) размещаются в динамической памяти.
1.4. Ограничения на типы элементов массивов
Нельзя объявить массив, элементы которого имеют тип void .
Нельзя объявить массив ссылок.
Вместо этого можно использовать массив константных указателей.
(Синтаксис инициализации массивов будет обсуждаться в разделе 3.2.)
В C++11 появился шаблон std::reference_wrapper<> . Он эмулирует интерфейс ссылки, но экземпляры конкретизации можно хранить в контейнерах и встроенных массивах. Но все же эмуляция интерфейса ссылки не совсем полная, иногда приходится использовать функцию-член get() . Вот пример.
Нельзя объявить массив функций.
Вместо этого можно использовать массив указателей на функцию.
Шаблон std::reference_wrapper<> можно конкретизировать типом функции, но преимуществ перед указателем практически нет — функцию и так можно вызвать через указатель без разыменования, а инициализировать указатель именем функции без оператора & . Есть еще вариант эмулирования массива функций — это использование шаблона std::function<> , но этот шаблон является темой отдельного разговора.
Массив нельзя объявить с помощью ключевого слова auto .
Квалификатор const не применим к типу массива, а только к типам его элементов.
2. Сведение и копирование массивов
В данном разделе рассматриваются особенности массивов, которые выделяют их из общей системы типов C++.
2.1. Сведение
Как было сказано выше, размер массива является составной частью типа массива, но в определенных ситуациях она теряется и это делает тип массива в некотором смысле «неполноценным». Эта потеря называется сведение (decay, array-to-pointer decay). (Для перевода термина «decay» еще используется слово «низведение», также можно встретить «разложение».) Суть сведения заключается в том, что почти в любом контексте массив преобразуется к указателю на первый элемент и информация о размере теряется. Исключениями являются оператор sizeof , оператор & (взятия адреса) и инициализация ссылки на массив. Оператор sizeof рассматривался в разделе 1.2, указатели и ссылки на массивы будут подробно рассмотрены в разделе 4. Объявление с помощью ключевого слова decltype также правильно определяет тип массива, без сведения.
Конечно, тесную связь массивов и указателей отрицать нельзя. Вот стандартный (в стиле C) способ обработать все элементы массива:
Но все же сведение можно отнести к сишным архаизмам и с ним надо быть внимательным и аккуратным, иначе можно столкнуться с не самыми приятными неожиданностями.
Вот как сведение влияет на объявления функций. Функции
не являются перегруженными функциями — это одно и то же. Размер надо передавать дополнительным параметром или использовать специальное соглашение для определения размера (например, завершающий ноль для строк).
При внешнем связывании массива также происходит сведение.
Для размера также надо использовать дополнительную переменную или использовать специальное соглашение для определения размера.
При объявлении переменной с помощью ключевого слова auto также происходит сведение.
При конкретизации шаблона функции
тип параметра шаблонной функции также будет выведен как указатель, если аргумент является массивом.
Сведение вызывает дополнительные проблемы при использовании наследования. (В C ведь нет наследования.) Рассмотрим пример.
Следующий код компилируется без ошибок и предупреждений.
Но если sizeof(B) < sizeof(D) , то в теле Foo() смещение элементов массива d (кроме нулевого, конечно) будет определятся неправильно и, соответственно, почти всегда Foo() будет работать некорректно. Так что работать с массивами в полиморфном стиле, через указатель на базовый класс, нельзя.
2.2. Копирование
Наряду со сведением (и тесно связанная с ним) есть еще одна особенность типа массива, которая делает его в некотором смысле «неполноценным». Массивы не поддерживают привычный синтаксис инициализации и присваивания, основанный на семантике копирования:
Также функция не может возвращать массив.
Но если массив является членом класса/структуры/объединения, то копирующий конструктор и соответствующий оператор присваивания, генерируемые компилятором, выполняют поэлементное копирование такого массива.
Еще одна ситуация, когда происходит копирование массива — это захват массива по значению в лямбда-выражении.
Но если используется инициализирующий захват (C++14), то происходит сведение.
3. Инициализация массивов
Для описания правил инициализации массивов необходимо кратко рассказать о тривиальных типах.
3.1. Тривиальные типы и неинициализированные переменные
Конструкторы и деструкторы можно назвать ключевыми элементами объектной модели С++. При создании объекта обязательно вызывается конструктор, а при удалении — деструктор. Но проблемы совместимости с С вынудили сделать некоторое исключение, и это исключение называется тривиальные типы. Они введены для моделирования сишных типов и сишного жизненного цикла переменных, без обязательного вызова конструктора и деструктора. Сишный код, если он компилируется и выполняется в С++, должен работать так же как в С. К тривиальным типам относятся числовые типы, указатели, перечисления, а также классы, структуры, объединения и массивы, состоящие из тривиальных типов. Классы и структуры должны удовлетворять некоторым дополнительным условиям: отсутствие пользовательского конструктора, деструктора, копирования, присваивания, виртуальных функций.
Переменная тривиального типа будет неинициализированной, если не использовать какой-нибудь вариант явной инициализации. Для тривиального класса компилятор может сгенерировать конструктор по умолчанию и деструктор. Конструктор по умолчанию обнуляет объект, деструктор ничего не делает. Но этот конструктор будет сгенерирован и использован только, если использовать какой-нибудь вариант явной инициализации, иначе переменная останется неинициализированной.
Неинициализированная переменная устроена следующим образом: если она объявлена в области видимости пространства имен (глобально), будет иметь все биты нулевыми, если локально, или создана динамически, то получит случайный набор битов. Понятно, что использование такой переменной может привести к непредсказуемому поведению программы. Массивы достаточно часто имеют тривиальный тип и поэтому эта проблема для них весьма актуальна.
Неинициализированные константы тривиального типа выявляет компилятор, иногда он выявляет и другие неинициализированные переменные, но с этой задачей лучше справляются статические анализаторы кода.
В стандартной библиотеке С++11 есть шаблоны, называемые свойствами типов (заголовочный файл <type_traits> ). Один из них позволяет определить, является ли тип тривиальным. Выражение std::is_trivial<Т>::value имеет значение true , если T тривиальный тип и false в противном случае.
3.2. Синтаксис инициализации массивов
3.2.1. Общие положения
Если не использовать явную инициализацию, то для массивов нетривиального типа гарантируется вызов конструктора по умолчанию для каждого элемента. Естественно, что в этом случае такой конструктор должен быть, иначе возникает ошибка. Но для массивов тривиального типа или, если конструктор по умолчанию отсутствует или не устраивает, необходимо использовать явную инициализацию.
Со времен C массивы можно было инициализировать с помощью синтаксиса агрегатной инициализации:
В С++11 появилась универсальная инициализация (uniform initialization) и теперь можно инициализировать так:
Для универсальной инициализации также можно использовать =, и различать эти два типа инициализации не всегда просто, а, скорее всего, не очень нужно.
Размер массива можно не указывать, тогда он определится по числу инициализаторов.
Если размер массива указан, то число инициализаторов не должно быть больше размера массива. Если размер массива больше числа инициализаторов, то для оставшихся элементов гарантируется вызов конструктора по умолчанию (который, естественно, должен быть), в том числе и для тривиальных типов. Таким образам, указав пустой список инициализации, мы гарантируем вызов конструктора по умолчанию для всех элементов массива тривиального типа.
Массивы констант тривиального типа требуют обязательного списка инициализации.
Число инициализаторов может быть меньше размера массива, в этом случае оставшиеся элементы инициализируются конструктором по умолчанию.
Символьные массивы можно инициализировать строковым литералом.
Размер такого массива будет на единицу больше числа символов строки, нужно хранить завершающий нулевой символ.
3.2.2. Инициализация членов класса
В С++11 появилась возможность инициализировать массивы, являющиеся нестатическими членами класса. Это можно сделать двумя способами: непосредственно при объявлении или в списке инициализации членов при определении конструктора.
Правда в этом случае надо всегда явно задавать размер массива, неявное определение размера через список инициализации не разрешается.
Статические массивы, как и ранее, можно инициализировать только при определении, размер массива может быть определен через список инициализации.
В C++17 появилась возможность объявлять статические члены (включая массивы) как inline . Таки члены можно инициализировать при объявлении, определение не обязательно.
3.2.3. Требования к инициализаторам
Выражения, стоящие в списке инициализации, вычисляются непосредственно перед инициализацией, они не обязаны быть известными на стадии компиляции (конечно, за исключением массивов, объявленных как constexpr ). Требования к элементам списка инициализации такие же как и к аргументу функции, имеющей параметр того же типа, что и элемент массива — должно существовать неявное преобразование от типа элемента списка инициализации к типу элемента массива. Пусть у нас есть объявление массива:
Наличие нужного преобразования эквивалентно корректности инструкции
Элемент списка инициализации может быть сам списком инициализации. В этом случае корректность этой инструкции также гарантирует корректную инициализацию элемента массива.
Если мы объявим конструктор Int как explicit , то последнее объявление станет некорректным. В этом случае придется писать
Этот пример также демонстрирует как с помощью списка инициализации мы можем создать массив для типа у которого нет конструктора по умолчанию. Но в этом случае число инициализаторов должно совпадать с размером массива.
4. Указатели и ссылки на массивы
4.1. Указатели на массивы
Пусть у нас объявлен массив
Указатель на этот массив объявляется и инициализируется следующим образом:
Для получения указателя используется традиционный оператор & . Тип указателя на массива обозначается как T(*)[N] .
Обратим внимание на использование скобок, без них мы получим объявление массива из N элементов типа указатель на T .
Указатель на массив — это не указатель на первый элемент (хотя побитово они, конечно, совпадают), здесь нет никакого сведения. Это полноценный тип, который «знает» размер массива. Поэтому при инициализации размеры должны совпадать.
При инкременте указатель на массив увеличивается на размер всего массива, а не на размер элемента.
Для доступа к элементу массива через указатель надо использовать оператор * и индексатор.
При использовании псевдонимов можно получить более привычный синтаксис объявления указателя на массив.
Также можно использовать auto , компилятор правильно выводит тип переменной как указатель на массив исходя из типа инициализатора.
Понимание указателей на массивы необходимо для правильной работы с многомерными массивами, которые подробно будут рассмотрены далее.
4.2. Ссылки на массивы
Пусть у нас объявлен массив
Ссылка на этот массив объявляется и инициализируется следующим образом:
Как и для любой ссылки, инициализация переменной типа ссылка на массив является обязательной. Тип ссылки на массива обозначается как T(&)[N] .
Также ссылку на массив можно инициализировать разыменованным указателем на массив.
Как и указатель, ссылка «знает» размер массива. Поэтому при инициализации размеры должны совпадать.
Доступ к элементу массива через ссылку осуществляется так же, как и через идентификатор массива.
Ссылки на массивы как раз и являются теми средствами, с помощью которых можно обойти сведение.
ожидает аргументы типа T[N] , указатели для нее не подходят.
При использовании псевдонимов можно получить более привычный синтаксис объявления ссылки на массив.
Также можно использовать auto , компилятор выводит тип переменной как ссылка на массив.
Обратите внимание на наличие & после auto , без него произошло бы сведение, и тип ra вывелся бы как int* .
При конкретизации шаблона функции
тип параметра шаблонной функции также будет выведен как ссылка на массив, если аргумент является массивом.
Особенно удобно использовать шаблоны с выводом типа и размера массива.
При конкретизации такого шаблона компилятор выводит тип элементов T и размер массива N (который гарантировано больше нуля). В качестве аргументов можно использовать только массивы, указатели будут отвергнуты. Именно этот прием используется при реализации макроса _countof() и шаблона функции std::size() , а так же шаблонов функций std::begin() и std::end() , которые обеспечивают для массивов реализацию диапазонного for и делают более комфортной работу с алгоритмами. В разделе 5 приведен пример реализации такого шаблона.
5. Многомерные массивы
C++ не поддерживает настоящие многомерные массивы, то есть выражение a[N, M] некорректно, но многомерность моделируется в виде «массива массивов», то есть можно использовать выражение a[N][M] .
Если T некоторый тип, N и M выражения, допустимые для определения размера массива, то инструкция
объявляет a как массив массивов, массив из N элементов, каждый из которых является массивом из M элементов типа T . Такой массив будем называть двумерным массивом. Выражение a[i][j] , где i от 0 до N-1 , j от 0 до M-1 , дает доступ к элементам этого массива. Первый индекс выбирает массив из массива массивов, второй выбирает элемент в этом массиве. Значение N можно назвать внешним размером двумерного массива, M внутренним. Тип многомерного массива обозначается как T[N][M] .
Выражение a[i] является массивом из M элементов типа T . Соответственно к нему может быть применено сведение, у него можно взять адрес или использовать для инициализации ссылки.
Сведение преобразует массив к указателю на элемент. Для двумерного массива этот элемент сам является массивом, а значит двумерный массив сводится к указателю на массив.
Таким образом, при передаче двумерного массива в функцию следующие варианты объявления соответствующего параметра эквивалентны:
Это означает, что внешний размер двумерного массива теряется и его надо передавать отдельным параметром.
При использовании псевдонимов можно получить более лаконичный синтаксис объявления двумерных массивов.
Это то же самое, что
Двумерные массивы инициализируются следующим образом:
Если нужно гарантировать только инициализацию по умолчанию, то можно использовать пустой список инициализации <> . Определения размера по списку инициализации возможно только по внешнему размеру.
Можно получить указатель на двумерный массив:
Также можно получить ссылку. Вот пример использования ссылки на двумерный массив.
Двумерный массив хорошо согласуется с математическими матрицами. В объявлении
N можно интерпретировать как число строк матрицы, M как число столбцов, тогда mtx[i][j] это элемент матрицы находящийся на пересечении i -й строки и j -го столбца, а mtx[i] это массив размера M , который представляет i -ю строку матрицы. Соответственно, такая матрица располагается в памяти по строкам. Правда в математике принято нумеровать строки и столбцы с единицы, а не с нуля.
6. Динамические массивы
В C++ отсутствует тип «динамический массив». Имеются только операторы для создания и удаления динамического массива, доступ к нему осуществляется через указатели на начало массива (своего рода полное сведение). Размер такого массива надо хранить отдельно. Динамические массивы желательно инкапсулировать в C++ классы.
6.1. Создание и удаление динамического массива
Если T некоторый тип, n переменная, значение которой может определяются в процессе выполнения программы, то инструкция
создает массив в динамической памяти. Тип переменной n должен приводиться к std::size_t , значение может быть нулем. Размер памяти, необходимой для размещения массива, то есть n*sizeof(T) , ограничен сверху платформой и компилятором. Переменная pa указывает на первый элемент массива.
Если тип T тривиальный, то элементы будут иметь случайное значение, в противном случае для инициализации элементов будет использован конструктор по умолчанию.
В C++11 появилась возможность использовать список инициализации.
Если число инициализаторов больше размера массива, то лишние не используются (компилятор может выдать ошибку, если значение n известно на стадии компиляции). Если размер массива больше числа инициализаторов, то для оставшихся элементов гарантируется вызов конструктора по умолчанию, в том числе и для тривиальных типов. Таким образам, указав пустой список инициализации, мы гарантируем вызов конструктора по умолчанию для всех элементов массива тривиального типа.
Оператор new[] сначала выделяет память для всего массива. Если выделение прошло успешно, то, если T нетривиальный тип или есть список инициализации, вызывается конструктор для каждого элемента массива начиная с нулевого. Если какой-нибудь конструктор выбрасывает исключение, то для всех созданных элементов массива вызывается деструктор в порядке, обратном вызову конструктора, затем выделенная память освобождается. Стандартные функции выделения памяти при невозможности удовлетворить запрос выбрасывают исключение типа std::bad_alloc .
Динамический массив удаляется оператором delete[] , который применяется к указателю, возвращаемому оператором new[] .
При этом, если при создании массива использовался конструктор, то для всех элементов массива вызывается деструктор в порядке, обратном вызову конструктора (деструктор не должен выбрасывать исключений), затем выделенная память освобождается.
В остальных отношениях указатель pa , возвращаемый оператором new[] , является просто указателем на начало массива, через него нельзя (во всяком случае «законно») получить размер массива, этот размер надо хранить отдельно. Соответственно с динамическим массивом нельзя использовать диапазонный for . Указатели в C/C++ поддерживают индексатор (встроенный оператор [] ), поэтому доступ к элементам динамического массива выглядит так же, как и к обычному массиву, контроля за корректностью индекса нет.
6.2. Динамические массивы и интеллектуальные указатели
Стандартный интеллектуальный указатель std::unique_ptr<> можно использовать для управления жизненным циклом динамического массива (см. [Josuttis]). Он имеет частичную специализацию для массивов (см. раздел 7), которая перегружает оператор [] вместо операторов -> и * , а также использует оператор delete[] в качестве удалителя по умолчанию. Вот пример:
Эта поддержка не является полноценной: не хранится информация о размере массива, поэтому нет возможности контролировать корректностью индекса, не поддерживается интерфейс стандартных контейнеров и диапазонный for .
В C++14 появилась возможность создать динамический массив и инициализировать им экземпляр std::unique_ptr<> с помощью std::make_unique<> :
При этом гарантируется инициализация элементов массива по умолчанию, в том числе и для тривиальных типов.
Интеллектуальный указатель std::shared_ptr<> стал поддерживать такую специализацию только в C++17, а использование std::make_shared<> для этой специализации появилось только в C++20.
В качестве альтернативы такому использованию интеллектуальных указателей можно рекомендовать std::vector<> .
6.3. Многомерные динамические массивы
Динамический массив не может быть динамическим по нескольким измерениям, то есть выражение new T[n][m] , где оба значения n и m определяются в процессе выполнения программы, не корректно. Но мы можем создать динамический массив, каждый элемент которого является встроенным массивом с размером, известным на стадии компиляции. Если M выражение, допустимое для определения размера массива, то следующая инструкция создает такой массив:
Оператор new[] возвращает указатель на массив. Доступ к элементам такого массива будет осуществляться через выражение pa[i][j] , в свою очередь pa[i] будет массив из M элементов типа T .
При использовании псевдонимов можно получить более лаконичный синтаксис.
Используя перегрузку оператора [] легко создать класс, который хранит данные в одномерном массиве, но при этом предоставляет интерфейс многомерного массива. Вот пример предельно упрощенного класса матрицы.
Вот пример использования:
Более продвинутый класс матрицы может использовать специальный вложенный proxy-класс, представляющий строку, например RowProxy , и индексатор будет возвращать экземпляр этого класса. Такой класс может, например, контролировать значение индекса, предоставлять функции-члены begin() , end() , etc. Аналогичное решение может быть и для столбцов.
7. Использование массивов в шаблонах
Тип массива можно использовать в качестве шаблонных аргументов и для специализации шаблонов классов.
Можно определить частичную специализацию шаблона класса для массивов не задавая при этом размер массива, то есть для массивов «вообще». Для этого в качестве типа специализации надо использовать T[] . Конечно, можно определить частичную специализацию для массива с заданным размером. Вот пример.
В стандартной библиотеке частичная специализация интеллектуального указателя std::unique_ptr<> и std::shared_ptr<> для массивов используется для управления жизненным циклом динамического массива, подробнее см. раздел 6.2.
Для программирования шаблонов, использующих массивы в качестве шаблонных аргументов, в стандартной библиотеке (заголовочный файл <type_traits> ) имеется несколько свойст типов: std::is_array<> , std::extent<> , std::rank<> , std::remove_extent<> . Вот примеры их использования (в примерах используется появившаяся в C++17 возможность использовать суффикс _v вместо члена value ):
В качестве реального примера использования этих свойст типов приведем немного упрощенное определение перегруженного варианта шаблона функции std::make_unique<> для массивов (см. раздел 6.2):
Шаблоны функций не поддерживают частичную специализацию, поэтому здесь используется техника, которая называется отключение шаблонов (template disabling). Этот шаблон будет отключен, то есть не будет конкретизироваться, для любых аргументов шаблона, тип которых отличается от T[] . Соответственно, перегруженный вариант std::make_unique<> для аргументов шаблона остальных типов аналогичным способом будет отключен для T[] .
8. Стандартные альтернативы массивам
Стандартная библиотека предоставляет несколько классов (точнее шаблонов классов), которые рекомендуется использовать вместо массивов.
Вместо встроенных массивов рекомендуется использовать шаблон std::array<> . (Появился в C++11, см. [Josuttis].) Этот шаблон является объектной оберткой встроенного массива, он имеет два шаблонных параметра: тип элементов и размер. Размер должен быть известен на стадии компиляции, но в отличии от встроенного массива может быть нулевым. Вот пример:
Этот шаблон поддерживает индексатор и традиционный интерфейс стандартного контейнера.
Вместо динамических массивов рекомендуется использовать std::vector<> . Этот шаблон хорошо известен программистам, подробно описан в литературе (стандартный контейнер №1), поэтому каких-то дополнительных подробностей можно не приводить.
Есть еще довольно специфический и не особо популярный шаблон std::valarray<> . Он позволяет эмулировать интерфейс многомерных массивов.
Список литературы
[Josuttis]
Джосаттис, Николаи М. Стандартная библиотека C++: справочное руководство, 2-е изд.: Пер. с англ. — М.: ООО «И.Д. Вильямс», 2014.
Java Language
Массивы

report this ad
Массивы позволяют хранить и извлекать произвольное количество значений. Они аналогичны векторам в математике. Массивы массивов аналогичны матрицам и действуют как многомерные массивы. Массивы могут хранить любые данные любого типа: примитивы, такие как int или ссылочные типы, такие как Object .
Синтаксис
- ArrayType[] myArray; // Объявление массивов
- ArrayType myArray[]; // Другой допустимый синтаксис (менее часто используемый и обескураженный)
- ArrayType[][][] myArray; // Объявление многомерных зубчатых массивов (repeat [] s)
- ArrayType myVar = myArray[index]; // Доступ к элементу (считыванию) по индексу
- myArray[index] = value; // Присвоить значение index позиции массива
- ArrayType[] myArray = new ArrayType[arrayLength]; // Синтаксис инициализации массива
- int[] ints = <1, 2, 3>; // Синтаксис инициализации массива с предоставленными значениями, длина выводится из числа предоставленных значений:
- new int[] <4, -5, 6>// Can be used as argument, without a local variable
- int[] ints = new int[3]; // same as
- int[][] ints = <<1, 2>, <3>, null>; // Инициализация многомерных массивов. int [] extends Object (а также anyType []), поэтому значение null является допустимым.
параметры
| параметр | подробности |
|---|---|
| ArrayType | Тип массива. Это может быть примитивным ( int , long , byte ) или Object ( String , MyObject и т. Д.). |
| индекс | Индекс относится к позиции определенного объекта в массиве. |
| длина | Каждому массиву при создании требуется заданная длина. Это делается либо при создании пустого массива ( new int[3] ), либо подразумевается при указании значений ( <1, 2, 3>). |
Создание и инициализация массивов
Основные случаи
Массивы могут быть созданы с использованием любого примитивного или ссылочного типа.
В последнем примере обратите внимание, что подтипы объявленного типа массива разрешены в массиве.
Массивы для пользовательских типов также могут быть построены подобно примитивным типам
Массивы, коллекции и потоки
вступление
Массив — это структура данных, которая содержит фиксированное число примитивных значений или ссылок на экземпляры объектов.
Каждый элемент в массиве называется элементом, и каждый элемент получает доступ к его числовому индексу. Длина массива устанавливается при создании массива:
Размер массива фиксируется во время выполнения при инициализации. Он не может быть изменен после инициализации. Если размер должен быть изменен во время выполнения, вместо него следует использовать класс Collection такой как ArrayList . ArrayList хранит элементы в массиве и поддерживает изменение размера путем выделения нового массива и копирования элементов из старого массива.
Если массив имеет примитивный тип, т. Е.
значения сохраняются в самом массиве. В отсутствие инициализатора (как в array2 выше) значение по умолчанию, присвоенное каждому элементу, равно 0 (ноль).
Если тип массива является ссылкой на объект, как в
то массив содержит ссылки на объекты типа SomeClassOrInterface . Эти ссылки могут ссылаться на экземпляр SomeClassOrInterface или любого подкласса (для классов) или на реализацию класса (для интерфейсов) SomeClassOrInterface . Если объявление массива не имеет инициализатора, то каждому элементу присваивается значение по умолчанию null .
Поскольку все массивы являются int -индексированными, размер массива должен быть задан с помощью int . Размер массива не может быть задан как long :
В массивах используется индексная система с нулевым значением , что означает, что индексирование начинается с 0 и заканчивается на length — 1 .
Например, следующее изображение представляет массив с размером 10 . Здесь первый элемент находится в индексе 0 а последний элемент находится в индексе 9 , а первый элемент находится в индексе 1 и последний элемент в индексе 10 (см. Рисунок ниже).
Доступ к элементам массивов осуществляется в постоянное время . Это означает, что доступ к первому элементу массива имеет одинаковую стоимость (по времени) доступа к второму элементу, третьему элементу и так далее.
Java предлагает несколько способов определения и инициализации массивов, включая буквенные и конструкторские обозначения. При объявлении массивов с использованием new Type[length] каждый элемент будет инициализирован со следующими значениями по умолчанию:
- 0 для примитивных числовых типов : byte , short , int , long , float и double .
- '\u0000' (нулевой символ) для типа char .
- false для boolean типа.
- null для ссылочных типов .
Создание и инициализация массивов примитивных типов
При объявлении массива [] будет отображаться как часть типа в начале объявления (после имени типа) или как часть декларатора для определенной переменной (после имени переменной) или обоих:
В следующем примере обе декларации правильны и могут компилироваться и запускаться без каких-либо проблем. Однако как Конвенция по кодированию Java, так и Руководство по стилю Google Java препятствуют форме с помощью скобок после имени переменной — скобки идентифицируют тип массива и должны появляться с обозначением типа . То же самое следует использовать для сигнатур возврата метода.
Воспринимаемый тип предназначен для размещения переходных пользователей C , которые знакомы с синтаксисом C, который имеет скобки после имени переменной.
В Java возможно иметь массивы размером 0 :
Однако, поскольку это пустой массив, никакие элементы не могут быть прочитаны или назначены ему:
Такие пустые массивы обычно полезны в качестве возвращаемых значений, поэтому вызывающий код должен беспокоиться только о работе с массивом, а не о потенциальном null значении, которое может привести к исключению NullPointerException .
Длина массива должна быть неотрицательным целым числом:
Размер массива можно определить, используя публичное конечное поле с названием length :
Примечание . array.length возвращает фактический размер массива, а не количество элементов массива, которым было присвоено значение, в отличие от ArrayList.size() которое возвращает количество элементов массива, которым было присвоено значение.
Создание и инициализация многомерных массивов
Самый простой способ создания многомерного массива состоит в следующем:
Это создаст две три длины int arrays- а a[0] и a[1] . Это очень похоже на классическую инициализацию прямоугольных многомерных массивов в стиле C.
Вы можете создавать и инициализировать одновременно:
В отличие от C , где поддерживаются только прямоугольные многомерные массивы, внутренние массивы не должны быть одинаковой длины или даже определены:
Здесь, a[0] является одной длиной int массива, в то время как a[1] представляет собой две длины int массива и a[2] является null . Такие массивы называются зубчатыми массивами или оборванными массивами , то есть массивами массивов. Многомерные массивы в Java реализованы как массивы массивов, т. array[i][j][k] эквивалентен ((array[i])[j])[k] . В отличие от C # , синтаксический array[i,j] не поддерживается в Java.
Представление многомерного массива в Java
Создание и инициализация массивов ссылочных типов
В дополнение к String литералам и примитивам, показанным выше, синтаксис ярлыков для инициализации массива также работает с каноническими типами Object :
Поскольку массивы являются ковариантными, массив ссылочного типа может быть инициализирован как массив подкласса, хотя ArrayStoreException будет ArrayStoreException , если вы попытаетесь установить элемент в нечто иное, чем String :
Синтаксис ярлыка не может использоваться для этого, потому что синтаксис ярлыка будет иметь неявный тип Object[] .
Массив может быть инициализирован нулевыми элементами, используя String[] emptyArray = new String[0] . Например, массив с нулевой длиной, подобный этому, используется для создания Array из Collection когда методу нужен тип среды выполнения объекта.
В обоих примитивных и ссылочных типах пустая инициализация массива (например, String[] array8 = new String[3] ) инициализирует массив значением по умолчанию для каждого типа данных .
Создание и инициализация массивов типичного типа
В родовых классах массивы генерических типов не могут быть инициализированы, например, из-за стирания типа :
Вместо этого они могут быть созданы с использованием одного из следующих способов: (обратите внимание, что они будут генерировать непроверенные предупреждения)
Создав массив Object и переведя его в общий тип:
Это самый простой метод, но поскольку базовый массив по-прежнему имеет тип Object[] , этот метод не обеспечивает безопасность типов. Поэтому этот метод создания массива лучше всего использовать только в универсальном классе — не публично публиковаться.
Используя Array.newInstance с параметром класса:
Здесь класс T должен быть явно передан конструктору. Возвращаемый тип Array.newInstance всегда является Object . Однако этот метод более безопасен, потому что вновь созданный массив всегда имеет тип T[] и поэтому может быть безопасно экстернализирован.
Заполнение массива после инициализации
Arrays.fill() может использоваться для заполнения массива с тем же значением после инициализации:
fill() также может присваивать значение каждому элементу указанного диапазона массива:
Поскольку Java-версия 8, метод setAll и ее Concurrent эквивалент parallelSetAll , могут использоваться для установки каждого элемента массива на сгенерированные значения. Этим методам передается функция генератора, которая принимает индекс и возвращает желаемое значение для этой позиции.
Следующий пример создает целочисленный массив и устанавливает все его элементы в соответствующее значение индекса:
Отдельная декларация и инициализация массивов
Значение индекса для элемента массива должно быть целым числом (0, 1, 2, 3, 4, . ) и меньше длины массива (индексы основаны на нуле). В противном случае будет выбрано исключение ArrayIndexOutOfBoundsException :
Массивы не могут быть повторно инициализированы синтаксисом ярлыка инициализатора массива
Невозможно повторно инициализировать массив с помощью синтаксиса ярлыков с инициализатором массива, поскольку инициализатор массива может быть указан только в объявлении поля или объявлении локальной переменной или как часть выражения создания массива.
Тем не менее, можно создать новый массив и назначить его переменной, используемой для ссылки на старый массив. Хотя это приводит к тому, что массив, на который ссылается эта переменная, повторно инициализируется, содержимое переменной представляет собой совершенно новый массив. Для этого new оператор может использоваться с инициализатором массива и назначается переменной массива:
Создание массива из коллекции
Два метода в java.util.Collection создают массив из коллекции:
Object[] toArray() может использоваться следующим образом:
<T> T[] toArray(T[] a) можно использовать следующим образом:
Разница между ними больше, чем просто отсутствие нетипизированных или типизированных результатов. Их производительность может также отличаться (подробности см. В этом разделе анализа эффективности ):
- Object[] toArray() использует векторизованную arraycopy , которая намного быстрее, чем проверенная arraycopy используемая в T[] toArray(T[] a) .
- T[] toArray(new T[non-zero-size]) должен обнулить массив во время выполнения, а T[] toArray(new T[0]) . Такое избегание заставляет последнего звонить быстрее первого. Подробный анализ здесь: Массивы Мудрости Древних .
Начиная с Java SE 8+, где была введена концепция Stream , можно использовать Stream созданный сборкой, для создания нового массива с использованием метода Stream.toArray .
Примеры, взятые из двух ответов ( 1 , 2 ) на преобразование 'ArrayList в' String [] 'в Java на переполнение стека.
Массивы для строки
Начиная с Java 1.5 вы можете получить представление String содержимого указанного массива без итерации по каждому элементу. Просто используйте Arrays.toString(Object[]) или Arrays.deepToString(Object[]) для многомерных массивов:
Arrays.toString() использует метод Object.toString() для получения значений String каждого элемента в массиве, помимо массива примитивного типа, его можно использовать для всех типов массивов. Например:
Если для класса не существует переопределенного toString() , тогда будет использоваться унаследованная toString() из Object . Обычно выход не очень полезен, например:
Создание списка из массива
Метод Arrays.asList() может использоваться для возврата List фиксированного размера, содержащего элементы данного массива. Полученный List будет иметь тот же тип параметра, что и базовый тип массива.
Примечание . Этот список поддерживается ( представлением ) исходного массива, что означает, что любые изменения в списке изменят массив и наоборот. Однако изменения в списке, который изменит его размер (и, следовательно, длину массива), вызовут исключение.
Чтобы создать копию списка, используйте конструктор java.util.ArrayList взяв Collection в качестве аргумента:
В Java SE 7 и более поздних версиях может использоваться пара угловых скобок <> (пустой набор аргументов типа), который называется Diamond . Компилятор может определить аргументы типа из контекста. Это означает, что информация о типе может быть опущена при вызове конструктора ArrayList и будет автоматически выведена во время компиляции. Это называется Type Inference, который является частью Java Generics .
Точка стоит отметить о Даймонд , что она не может быть использована с классами Anonymous .
Важные замечания, связанные с использованием метода Arrays.asList ()
Этот метод возвращает List , который является экземпляром Arrays$ArrayList (статический внутренний класс Arrays ), а не java.util.ArrayList . Полученный List имеет фиксированный размер. Это означает, что добавление или удаление элементов не поддерживается и будет UnsupportedOperationException исключение UnsupportedOperationException :
Новый List можно создать, передав List с поддержкой массива в конструктор нового List . Это создает новую копию данных, которая имеет изменяемый размер и не поддерживается исходным массивом:
Вызов <T> List<T> asList(T. a) в примитивном массиве, такой как int[] , приведет к созданию List<int[]> , единственным элементом которого является исходный примитивный массив вместо фактических элементов исходного массива.
Причиной такого поведения является то, что примитивные типы не могут использоваться вместо параметров типового типа, поэтому весь примитивный массив заменяет параметр типового типа в этом случае. Чтобы преобразовать примитивный массив в List , прежде всего, преобразовать примитивный массив в массив соответствующего типа-оболочки (т. Arrays.asList в Integer[] вместо int[] ).
Поэтому это будет напечатать false :
С другой стороны, это будет true :
Это также напечатает true , потому что массив будет интерпретироваться как Integer[] ):
Многомерные и зубчатые массивы
Можно определить массив с более чем одним измерением. Вместо того, чтобы получать доступ, предоставляя единый индекс, доступ к многомерному массиву можно получить, указав индекс для каждого измерения.
Объявление многомерного массива можно сделать, добавив [] для каждого измерения к регулярному объявлению массива. Например, чтобы создать двумерный массив int , добавьте еще один набор скобок в объявление, например int[][] . Это продолжается для 3-мерных массивов ( int[][][] ) и т. Д.
Чтобы определить двумерный массив с тремя строками и тремя столбцами:
Массив можно индексировать и присваивать ему значения с помощью этой конструкции. Обратите внимание, что неназначенные значения являются значениями по умолчанию для типа массива, в этом случае 0 для int .
Также возможно одновременное создание измерений и даже создание непрямоугольных массивов. Они чаще всего называются зубчатыми массивами .
Важно отметить, что, хотя можно определить любой размер массива с зубчатым контуром, должен быть определен предшествующий уровень.
Как многомерные массивы представлены в Java
Литературная инициализация массива Jagged
Многомерные массивы и зубчатые массивы также могут быть инициализированы литеральным выражением. Следующее объявляет и заполняет массив 2×3 int :
Примечание : Subarrays с зубцами также может быть null . Например, следующий код объявляет и заполняет двумерный массив int чей первый подмассив имеет значение null , второй субарейр имеет нулевую длину, третий подмассив имеет одну длину, а последний подмассива представляет собой массив из двух длин:
Для многомерного массива можно выделить массивы измерения нижнего уровня по их индексам:
ArrayIndexOutOfBoundsException
ArrayIndexOutOfBoundsException генерируется при доступе к несуществующему индексу массива.
Массивы индексируются с нулевым индексом, поэтому индекс первого элемента равен 0 а индекс последнего элемента — array.length — 1 массива минус 1 (т. array.length — 1 ).
Поэтому любой запрос элемента массива индексом i должен удовлетворять условию 0 <= i < array.length , иначе будет 0 <= i < array.length ArrayIndexOutOfBoundsException .
Следующий код — простой пример, в котором генерируется ArrayIndexOutOfBoundsException .
Обратите внимание, что незаконный индекс, к которому обращаются, также включен в исключение ( 2 в примере); эта информация может быть полезна, чтобы найти причину исключения.
Чтобы этого избежать, просто проверьте, что индекс находится в пределах массива:
Получение длины массива
Массивы — это объекты, которые обеспечивают пространство для хранения до размера элементов указанного типа. Размер массива не может быть изменен после создания массива.
Поле length в массиве сохраняет размер массива. Это final поле и не может быть изменено.
Этот код показывает разницу между length массива и количеством объектов, хранящихся в массиве.
Сравнение массивов для равенства
Типы массивов наследуют реализации equals() (и hashCode() ) из java.lang.Object , поэтому equals() возвращает true только при сравнении с тем же самым объектом массива. Чтобы сравнить массивы для равенства на основе их значений, используйте java.util.Arrays.equals , который перегружен для всех типов массивов.
Когда тип элемента является ссылочным типом, Arrays.equals() вызывает equals() для элементов массива для определения равенства. В частности, если тип элемента сам по себе является типом массива, будет использоваться сравнение идентичности. Чтобы сравнить многомерные массивы для равенства, используйте Arrays.deepEquals() как Arrays.deepEquals() ниже:
Поскольку наборы и карты используют equals() и hashCode() , массивы обычно не полезны в качестве заданных элементов или клавиш карты. Либо оберните их в класс-помощник, который реализует equals() и hashCode() в терминах элементов массива или преобразует их в экземпляры List и сохраняет списки.
Массивы для потока
Преобразование массива объектов в Stream :
Преобразование массива примитивов в Stream с использованием Arrays.stream() преобразует массив в примитивную специализацию Stream:
Вы также можете ограничить Stream для диапазона элементов в массиве. Начальный индекс является включительным, а конечный индекс — исключительным:
В классе Stream появляется метод, аналогичный Arrays.stream() : Stream.of() . Разница в том, что Stream.of() использует параметр varargs, поэтому вы можете написать что-то вроде:
Итерация по массивам
Вы можете перебирать массивы либо с помощью расширенного цикла for (aka foreach), либо с использованием индексов массива:
Здесь стоит отметить, что нет прямого способа использовать Iterator в массиве, но через библиотеку Arrays его можно легко преобразовать в список, чтобы получить объект Iterable .
Для массивов в коробке используйте Arrays.asList :
Для примитивных массивов (с использованием java 8) используйте потоки (в частности, в этом примере — Arrays.stream -> IntStream ):
Если вы не можете использовать потоки (без java 8), вы можете использовать goava- библиотеку guava :
В двумерных массивах или более, обе методики могут быть использованы несколько более сложным образом.
Невозможно установить Array на любое неравномерное значение без использования цикла, основанного на индексе.
Конечно, вы также можете использовать while или do-while циклы при итерации с использованием индексов.
Одно примечание: при использовании индексов массива убедитесь, что индекс находится между 0 и array.length — 1 (оба array.length — 1 ). Не делайте жестко закодированные предположения относительно длины массива, иначе вы можете сломать свой код, если длина массива изменится, но ваши жестко закодированные значения не будут.
Это также лучше, если вы не используете причудливые вычисления для получения индекса, но используете индекс для итерации, и если вам нужны разные значения, подсчитайте их.
Доступ к массивам в обратном порядке
Использование временных массивов для уменьшения повторения кода
Итерация по временному массиву вместо повторения кода может сделать ваш код более чистым. Он может использоваться, когда одна и та же операция выполняется для нескольких переменных.
Имейте в виду, что этот код не должен использоваться в критически важных средах, поскольку массив создается каждый раз, когда вводится цикл, и что примитивные переменные будут скопированы в массив и, следовательно, не могут быть изменены.
Копирование массивов
Java предоставляет несколько способов копирования массива.
для цикла
Обратите внимание, что использование этой опции с массивом Object вместо примитивного массива будет заполнять копию ссылкой на исходное содержимое вместо его копии.
Object.clone ()
Поскольку массивы Object в Java, вы можете использовать Object.clone() .
Обратите внимание, что метод Object.clone для массива выполняет мелкую копию , то есть возвращает ссылку на новый массив, который ссылается на те же элементы, что и исходный массив.
Arrays.copyOf ()
java.util.Arrays предоставляет простой способ выполнить копию массива в другой. Вот основное использование:
Обратите внимание, что Arrays.copyOf также обеспечивает перегрузку, которая позволяет вам изменять тип массива:
System.arraycopy ()
public static void arraycopy(Object src, int srcPos, Object dest, int destPos, int length) Копирует массив из указанного исходного массива, начиная с указанной позиции, в указанную позицию целевого массива.
Ниже приведен пример использования
Arrays.copyOfRange ()
В основном используется для копирования части массива, вы также можете использовать его для копирования целого массива в другой, как показано ниже:
Литейные массивы
Массивы — это объекты, но их тип определяется типом содержащихся объектов. Поэтому нельзя просто отбрасывать A[] в T[] , но каждый член A[] конкретного A[] должен быть переведен в объект T Общий пример:
Таким образом, с учетом массива A[] :
Удалить элемент из массива
Java не предоставляет прямой метод в java.util.Arrays для удаления элемента из массива. Для его выполнения вы можете скопировать исходный массив в новый, не удаляя элемент или преобразовывая его в другую структуру, позволяющую удалить.
Использование ArrayList
Вы можете преобразовать массив в java.util.List , удалить элемент и преобразовать список обратно в массив следующим образом:
Использование System.arraycopy
System.arraycopy() можно использовать для создания копии исходного массива и удаления System.arraycopy() элемента. Ниже пример:
Использование Apache Commons Lang
Чтобы легко удалить элемент, вы можете использовать библиотеку Apache Commons Lang и особенно статический метод removeElement() класса ArrayUtils . Ниже пример:
Ковариантность массива
Объектные массивы являются ковариантными, что означает, что так же, как Integer является подклассом Number , Integer[] является подклассом Number[] . Это может показаться интуитивным, но может привести к неожиданному поведению:
Хотя Integer[] является подклассом Number[] , он может содержать только Integer s, и попытка назначить элемент Long выдает исключение во время выполнения.
Обратите внимание, что это поведение уникально для массивов, и его можно избежать, используя вместо этого общий List :
Для всех элементов массива не обязательно использовать один и тот же тип, если они являются подклассом типа массива:
Как изменить размер массива?
Простой ответ заключается в том, что вы не можете этого сделать. После создания массива его размер не может быть изменен. Вместо этого массив может быть только «изменен», создав новый массив с соответствующим размером и скопировав элементы из существующего массива в новый.
Предположим (например), что новый элемент необходимо добавить в массив listOfCities как указано выше. Для этого вам необходимо:
- создайте новый массив размером 4,
- скопируйте существующие 3 элемента старого массива в новый массив при смещениях 0, 1 и 2 и
- добавьте новый элемент в новый массив со смещением 3.
Существуют различные способы сделать это. До появления Java 6 наиболее кратким способом было:
Начиная с Java 6 методы Arrays.copyOf и Arrays.copyOfRange могут сделать это проще:
Для других способов копирования массива см. Следующий пример. Имейте в виду, что при изменении размера вам понадобится копия массива с другой длиной до оригинала.
Лучшие альтернативы изменению размера массива
Существуют два основных недостатка с изменением размера массива, как описано выше:
- Это неэффективно. Создание массива больше (или меньше) включает в себя копирование многих или всех существующих элементов массива и выделение нового объекта массива. Чем больше массив, тем он дороже.
- Вы должны иметь возможность обновлять любые «живые» переменные, содержащие ссылки на старый массив.
Один из вариантов — создать массив с достаточно большим размером для начала. Это возможно только в том случае, если вы можете точно определить этот размер до выделения массива . Если вы не можете этого сделать, возникает проблема изменения размера массива.
Другой альтернативой является использование класса структуры данных, предоставляемого библиотекой классов Java SE или сторонней библиотекой. Например, структура «коллекций» Java SE предоставляет ряд реализаций API-интерфейсов List , Set и Map с различными свойствами среды выполнения. Класс ArrayList ближе всего к характеристикам производительности простого массива (например, O (N) lookup, O (1) get и set, O (N) случайная вставка и удаление), обеспечивая при этом более эффективное изменение размера без проблемы с эталонным обновлением.
(Эффективность изменения размера для ArrayList исходит из стратегии удвоения размера массива поддержки при каждом изменении размера. Для типичного варианта использования это означает, что вы иногда изменяете размер. Когда вы амортизируете за весь срок службы списка, стоимость изменения размера для каждой вставки O(1) . При изменении размера простого массива может быть использована одна и та же стратегия.)
Поиск элемента в массиве
Существует множество способов найти местоположение значения в массиве. В приведенных ниже примерах показано, что массив является одним из следующих:
Кроме того, каждый устанавливает index или index2 либо индексу требуемого элемента, либо -1 если элемент отсутствует.
Использование Arrays.binarySearch (только для отсортированных массивов)
Использование массива Arrays.asList (только для не примитивных массивов)
Использование Stream
Линейный поиск с использованием цикла
Линейный поиск с использованием сторонних библиотек, таких как org.apache.commons
Примечание. Использование прямого линейного поиска более эффективно, чем перенос в список.
Тестирование, если массив содержит элемент
Вышеприведенные примеры могут быть адаптированы для проверки того, содержит ли массив элемент, просто проверяя, вычисляется ли вычисляемый индекс больше или равен нулю.
Кроме того, есть также несколько более сжатых вариантов:
Сортировка массивов
Сортировка массивов можно легко сделать с Массивы апи.
Сортировка массивов строк:
String — это не числовые данные, она определяет ее собственный порядок, который называется лексикографическим порядком, также известным как алфавитный порядок. Когда вы сортируете массив String с помощью метода sort() , он сортирует массив в естественный порядок, определенный интерфейсом Comparable, как показано ниже:
Увеличение порядка
Уменьшение порядка
Сортировка массива объектов
Чтобы отсортировать массив объектов, все элементы должны реализовать интерфейс Comparable или Comparator для определения порядка сортировки.
Мы можем использовать любой метод sort(Object[]) для сортировки массива объектов в его естественном порядке, но вы должны убедиться, что все элементы в массиве должны реализовать Comparable .
Кроме того, они должны быть взаимно сопоставимыми, например, e1.compareTo(e2) не должен бросать ClassCastException для любых элементов e1 и e2 в массиве. В качестве альтернативы вы можете отсортировать массив объектов в пользовательском порядке, используя метод sort(T[], Comparator) как показано в следующем примере.
Преобразование массивов между примитивами и коробочными типами
Иногда требуется преобразование примитивных типов в бокс- типы.
Для преобразования массива можно использовать потоки (в Java 8 и выше):
С более низкими версиями это может быть путем итерации примитивного массива и явного копирования его в массив в штучной упаковке:
Точно так же массив в коробке может быть преобразован в массив его примитивной копии: