И.Г. Головин, И.А. Волкова - Языки и методы программирования, страница 14
Описание файла
PDF-файл из архива "И.Г. Головин, И.А. Волкова - Языки и методы программирования", который расположен в категории "". Всё это находится в предмете "языки программирования" из 7 семестр, которые можно найти в файловом архиве МГУ им. Ломоносова. Не смотря на прямую связь этого архива с МГУ им. Ломоносова, его также можно найти и в других разделах. .
Просмотр PDF-файла онлайн
Текст 14 страницы из PDF
Еще одно отличие62имени массива от указателя состоит в том, что операция sizeofдля указателя возвращает размер указателя (т.е. машинного адреса),а для имени массива — размер всей последовательности элементов,составляющей массив.Одномерные массивы в языках C# и Java. Объявление массивав этих языках имеет видТ [] array;Напомним, что array — это только ссылка, а собственно массивразмещается в видеarray = new T[Len];Здесь Len — произвольное целочисленное выражение (необязательно статическое).Можно использовать и явную инициализацию:int [] arr;arr = new int [] {1, 3, 5, 7, 9};Длина массива является квазидинамическим свойством, т. е.она задается динамически в момент создания, но измениться ужене может. Узнать длину массива во время выполнения программыможно с помощью свойства Length в C# и свойства length в Java.Приведем пример суммирования элементов массива:double [] arr;double sum = 0;for (int i = 0; i < arr.Length; i++) sum += arr[i];Операция индексирования контролируется при каждом обращении к ней.
Если индекс выйдет за пределы диапазона 0...Length-1,то генерируется исключительная ситуация (исключения описаныв гл. 9): в Java — ArraylndexOutOfBoundsException, а в C# —IndexOutOfRangeException.В отличие от С и C++ массивы в C# и Java — полноправныеобъекты, принадлежащее к классам специального вида. Оба языкапредоставляют большой набор операций над массивами, включающий в себя копирование элементов, поиск значений, слияние и разбиение и т.п. В Java эти операции сосредоточены в классах Systemи Arrays, а в C# — в классе Array.Еще раз отметим, что длина массива не может измениться после его размещения. В случае если требуется массив с переменнойдлиной, можно использовать класс ArrayList из стандартной библиотеки (он даже называется одинаково для обоих языков).
Этоткласс позволяет добавлять и удалять элементы из массива. В C++соответствующий класс из стандартной библиотеки STL называетсяvector.63Многомерные массивыМногомерные массивы в большинстве языков рассматриваютсякак массивы массивов (единственное исключение, пожалуй, составляет Фортран), например двумерная матрица рассматриваетсякак одномерный массив из одномерных массивов. Рассмотрим объявление матрицы на языках С и C++:float matr[N] [М] ;Это одномерный массив длиной N, каждый элемент которого (т.е.строка матрицы) — одномерный массив длиной М. Такой многомерный массив все равно остается непрерывной последовательностьюэлементов, вначале располагаются элементы первой строки, заними — второй и т.д. Если последовательно пробегать по элементам многомерного массива, то индексы меняются справа налево(и быстрее всех самый правый индекс), как в следующем примересуммирования элементов трехмерного массива:float m [Nl] [N2] [N3] , sum = 0.0;;for (int i = 0; i < N1; i++)for (int j = 0; j < N2; j++)for(int k = 0; k < N3; k++)sum += m[i] [j] [k] ;Такие массивы называют прямоугольными.Однако в языках с референциальной моделью возникает следующая проблема.
Массивы в таких языках представляются ссылками,поэтому, например, двумерный массив вместо прямоугольного представляет собой массив из ссылок на массивы-столбцы матрицы.Такие массивы уже не обязаны иметь одну и ту же длину и называются ступенчатыми. В С и C++ подобные массивы можно построить,используя массив из указателей.Приведем пример ступенчатого массива в языке Java (он же является примером на С#):int [][] jagged;jagged = new int [4][];// создали массив из ссылок на массивы intfor (int i = 3; i>=0; i--)jagged[i] = new int[i+l];// создали треугольную матрицуint det = 1;for (int i = 0; i < 5; i++)det *= jagged[i] [i];// вычислили определитель треугольной матрицыВ следующем примере массивы имеют вид прямоугольных (длинастолбцов одинаковая), но это все равно ступенчатые массивы:64double [][]a = new double [5][5];// создали квадратную матрицу 5x5int [] []b = new int [][] {{1,2,3}, {3,4,5}};// создали и инициализировали массив 2x3В языке Java все многомерные массивы ступенчатые, создатьпрямоугольный массив, элементы которого образуют в памяти непрерывную последовательность, в этом языке нельзя.
Однако заметим,что доступ к элементам ступенчатого массива менее эффективен,чем к элементам массивов в С и C++ (объясните почему). По этойпричине в язык C# добавлен еще один вид многомерных массивов —прямоугольные:intintfor[,] а = newsum = 0 ;int[5,6];(int i = 0; i< 5; i++)for (int j = 0; j < 6; j++)sum += a [i,j ];double [,] x = new double[4,]; // ошибка!!!int [,] b = {{1,2},{3}}; // ошибка!!!int [,] с = { {1,2}, {3,4},{5,6}};// создан прямоугольный массив 3x2Необходимость добавления прямоугольных массивов обусловленадвумя главными причинами: эффективностью и возможностью обработки массивов, совместимых с моделью данных языков типа С.Динамические строкиДинамическая строка (далее будем называть ее просто строкой) —это последовательность символов произвольной длины.
Длина строкиопределяется при размещении в памяти и далее не меняется. Напервый взгляд, строка может быть реализована (по крайней мере,в языках C# и Java) как массив из символов, однако это не так. Языки C# и Java содержат специальный встроенный тип (точнее, класс)String (в C# можно употреблять вместо этого имени ключевое слово string). В C++ встроенного типа строки нет, но зато есть классstring из стандартной библиотеки STL.Необходимость введения специального типа обусловлена несколькими причинами. Во-первых, набор операций для строк существенношире и специфичней набора операций для обычных массивов.
Этотнабор включает в себя много вариантов поиска (символа, подстроки,с учетом регистра), сравнения (с учетом разных правил упорядочения)и других подобных вариантов, редко применяемых для массивов.Кроме того, строки должны интегрироваться со встроенным в языкпонятием строковой константы ("literal constant"). Сравнитеинициализацию строки и символьного массива (С#, Java):65char [] strArr = { '1' , 'i ', 'n ', 1e '};String str = "line";Однако главным аргументом в пользу специальной реализациистрокового типа является то, что строки реализуются как неизменяемый объект.
Это означает, что содержимое строки послеее размещения и инициализации рассматривается как константа.Любые операции над строками (даже те, которые манипулируют содержимым строки) не меняют ее содержимое, а вырабатывают новоестроковое значение. Операция индексирования (s [ i ]) применимак строкам, но в отличие от массивов она возвращает не ссылку насимвол, а значение символа, поэтому для строки s нельзя писатьs [0 ] = ' ', так как значение не может быть левой частью операции присваивания.Для обычных массивов модификация отдельных элементов является обычной операцией так же, как и сортировка, меняющая порядокэлементов и т.
п.Зато ряд операций над строками в силу их неизменяемости можнореализовать существенно эффективней, чем операции над массивомсимволов.Отметим, что строки — это полноценные классы, обладающиебогатым набором операций. Самая частая операция над строками —конкатенация (сцепление) строк, обозначаемая как «+»:String si = "Hello", s2 = "world!", s;s = si + ", " + s2; // получилось: Hello, world!Правда, следует отметить, что использовать операцию конкатенации для конструирования новых строк следует с осторожностью.Рассмотрим пример на языке С#, который строит строку из входноготекста, удаляя из нее все концы строк:string s="", curr;while ((curr = Console.ReadLine ()) != null)s += curr;Console.WriteLine(s) ;Здесь мы воспользовались тем фактом, что функция ReadLine ()из класса Console не включает символ конца строки в возвращаемое значение, поэтому этого символа нет в выдаваемом тексте.На Java можно написать аналогичную программу, используя классSystem.Проблема в том, что мы используем операцию конкатенации дляпостроения постоянно разрастающейся строки.
Если входной текстдостаточно длинный, то возникает эффект фрагментации памяти: мытребуем все более длинные куски памяти, освобождая куски, которыекороче. Конечно, автоматический сборщик мусора исправит ситуацию, но производительность программы существенно упадет. Неслучайно и С#, и Java содержат стандартный класс StringBuilder,66который специально спроектирован для конструирования строквозрастающей длины.
Он работает с памятью более оптимально,чем реализация операции «+». После завершения конструированиястроки достаточно вызвать функцию ToString (в Java toString)для получения сконструированной строки:string curr;StringBuilder sb = new StringBuilder() ;while ((curr = Console.ReadLine()) != null)sb.Append(curr);Console.WriteLine(s);Записи (структуры)В традиционных императивных языках программирования, такихкак Паскаль или С, записи (в С они называются структурами) нарядус массивами используются очень широко.Запись — это совокупность объявлений переменных, которыеобъединены в отдельный объект. Эти переменные называются полямизаписи и доступны с помощью операции «точка».