bmstu_iu6_Cpp1 (823967), страница 9
Текст из файла (страница 9)
раздел 3.3);•использовать конструкцию:<Тип элемента> <Имя>[<Размер1>] [<Размер2>] ...[= {<Список значений >}];где <Тип элемента> – скалярный или сложный (в том числе массив) тип последовательнорасполагаемых элементов;<Имя> – имя массива – указатель, содержащий адрес первого элемента массива;<Размер 1>, <Размер 2>, … <Размер n> – размерности массива по каждому из n измерений;<Список значений> – перечень значений, инициализирующих выделяемое место впамяти.Количество размерностей определяет мерность массива, если задан один размер, томассив – одномерный, если два, то – двумерный или матрица, если три, то – трехмерный,если больше, то – многомерный.Массив в памяти не должен занимать более 2 Гб.3.4.1 Одномерные массивыПо правилам Си и С++ одномерный массив можно объявить:•статически – с использованием абстракции массив и указанием его размера,например:int a[10]; // массив на 10 целых чисел, индекс меняется от 0 до 9unsigned int koord[10]; // массив целых беззнаковых чисел•динамически – объявив только указатель на будущий массив и выделив память под массив во время выполнения программы, например:int *dinmas;// объявление указателя на целое числоdinmas=new int [100]; // выделение памяти под массив на 100 элементовОглавление54...delete [] dibmas;Инициализация одномерного массива при объявлении.
Массивы, объявляемыевне функций или с описателями static и extern (см. раздел 4.1.1), можно инициализировать. Инициализируемый массив можно объявлять без указания его размерности. Еслимассив объявлен с указанием количества элементов, то при инициализации должны бытьзаданы значения для всех элементов массива, например:extern int a[5]={0,-36,78,3789,50};Если массив объявлен без указания количества элементов, то количество элементовмассива определяется количеством заданных значений, например:extern long double c[]={7.89L,6.98L,0.5L,56.8L}; // 4 элементаЕсли инициализируется массив, для которого объявлен только указатель, то памятьдля размещения элементов массива выделять не надо, поскольку память выделяется дляразмещения констант, а затем адрес этой памяти заносится в указатель, например:static short *m={2,3,5,8,12,0,56};// массив на 7 элементовДоступ к элементам одномерного массива.
Доступ к элементам массива осуществляют по индексам. В качестве индекса можно указывать выражение с результатом целого (или символьного) типа. Если в качестве индекса указан целочисленный литерал иливыражение над целочисленными литералами, то доступ называют прямым. Если в качестве индексов указано выражение, содержащее идентификаторы переменных, то доступназывают косвенным. Независимо от способа задания индекс может меняться от 0 до величины на 1 меньшей размера. Например, если объявлен массив int a[5], тоа) прямой доступ:a[0]=5;// обращение к элементу с номером 0б) косвенный доступ:i=1; a[i+2]=5; // обращение к элементу с номером 3, который вычисляетсяПример 3.1.
Программа определения максимального элемента массива и его номера:#include <locale.h>#include <stdio.h>#include <conio.h>int main(int argc, char* argv[]){setlocale(0,"russian");float a[5],amax;int i,imax;puts("Введите 5 значений:");Оглавление55for(i=0;i<5;i++) scanf("%f",&a[i]);amax=a[0];imax=0;for(i=1;i<5;i++)if(a[i]>amax){amax=a[i]; imax=i;}puts("Значения:");for(i=0;i<5;i++) printf("%7.2f ",a[i]);printf("\n");printf("Максимум = %7.2fномер = %5d\n",amax, imax);puts("Нажмите любую клавишу для завершения...");_getch();return 0;}Следует помнить, что по правилам Си и С++ независимо от способа объявления массива его имя – это имя переменной-указателя, содержащего адрес первого элемента массива.
Поэтому для адресации элементов массива независимо от способа объявления можноиспользовать адресную арифметику. При этом следующие формы обращения эквивалентны:(list+i)⇔ &(list[i]) // адреса элементов*(list+i) ⇔ list[i]// значения элементов3.4.2 Многомерные массивыОбъявление многомерных массивов. Так же, как и одномерные массивы, двух- иболее мерные массивы можно объявить:• статически, например:int a[4][5]; // матрица элементов целого типа из 4 строк и 5 столбцов,// индексы меняются: первый от 0 до 3, второй от 0 до 4float b[10][20][2]; // трехмерный массив вещественных чисел из// 10 строк, 20 столбцов и 2 слоев• динамически, с помощью указателей, например:short **matr; .Оглавление56При статическом объявлении помять будет предоставлена одним куском по количеству определенных элементов.
Элементы в памяти будут расположены построчно: элементы нулевой строки, элементы первой строки и т.д. (см. рисунок 3.6).B35970-я строка1270121-я строка59032-я строкаРисунок 3.6 – Размещение элементов статической матрицы в памятиПри динамическом описании обычно реализуют более удобные структуры. Например матрицу с указателями, хранящими адреса строк матрицы в явном виде – массив динамических векторов (см. рисунок 3.7):float **D2;// объявлен указатель на матрицуD2=new float *[3];// выделение памяти под массив указателей на строки// матрицыfor(int i=0;i<3; i++)D2[i]=new float [4]; // выделение памяти под элементы строкD235971270125903Рисунок 3.7 – Массив динамических векторовОбращение к элементам этой структуры может выполняться также как и к элементамматрицы, например:D2[1][2]=3;Точно так же, как и в одномерных массивах, для адресации элементов многомерногомассива независимо от способа описания можно использовать адресную арифметику. Каждому уровню скобок при этом соответствует операция разыменования указателя, например:int m[2][3][4];m – «указатель указателя указателя», содержащий «адрес адреса адреса» первогоэлемента (см.
рисунок 3.8).m[1][0][0]m[0][0][0]mСлоиРисунок 3.8 – Трехмерная структура данныхОглавление57Для обращения к элементу этого массива необходимо три операции разыменования:*m=> m[0][?][?]**m=> m[0][0][?]***m => m[0][0][0]Аналогично:m[0][2][0] => *(*(*(m+0)+2)+0) => *(*(*m+2))m[i][j][k] => *(*(*(m+i)+j)+k) =>*(*(*(i+m)+j)+k)Пример 3.2. Написать программу, которая сортирует строки матрицы по возрастанию элементов с использованием указателей.#include <locale.h>#include <stdio.h>#include <conio.h>#include <stdlib.h>int **mas,*ptr;int b,n,m,i,j,k;int main(){setlocale(0,"russian");// Выделение памяти под матрицуprintf("Введите n=");scanf_s("%d",&n);printf("Введите m=");scanf_s("%d",&m);mas=newint *[n];// выделение памяти под массив указателейfor(i=0;i<n;i++)mas[i]=new int[m];// выделение памяти под строки матрицы//Заполнение матрицы даннымиfor(i=0;i<n;i++){printf("Введите %d элемента %d-й строки\n",m,i);for (j=0;j<m;j++)scanf_s("%d",&mas[i][j]);}Оглавление58// Вывод исходной матрицы на экранputs("Введенная матрица:");for(i=0;i<n;i++){for (j=0;j<m;j++)printf("%3d",mas[i][j]);printf("\n");}// Сортировка строк матрицы - реализована через указателиfor(i=0;i<n;i++){k=1;while(k!=0){ptr=mas[i];for(k=0,j=0;j<m-1;ptr++,j++)if (*ptr>*(ptr+1)){b=*ptr;*ptr=*(ptr+1);*(ptr+1)=b;k++;}}}// Вывод результатаputs("Сортированная матрица:");for(i=0;i<n;i++){for (j=0;j<m;j++)printf("%3d",mas[i][j]);printf("\n");}// Удаление динамической матрицы// удаление строк динамической матрицыfor(i=0;i<n;i++)delete[] mas[i];delete[] mas;// удаление массива указжателей на строкиОглавление59puts("Нажмите любую клавишу для завершения...");_getch();return 0;}3.5 СтрокиВ С++ символьная строка определяется как массив символов, который заканчивается нуль-символом – маркером конца строки «\0» (см.
рисунок 3.9). Если маркер конца строки в символьном массиве отсутствует, то такой массив строкой не является. Маркер концастроки позволяет отслеживать реальную длину строки, которая может быть меньше размера массива.Этострока\0Маркер конца строкиРисунок 3.9 – Внутреннее представление строкиОбращение к элементам строки осуществляется по индексу, так же как и к элементумассива.
Соответственно и нумерация символов начинается с 0.3.5.1 Объявление и инициализация строкСтроку можно объявить теми же способами, что и одномерный массив символов.Единственно при объявлении надо учитывать, что любая строка должна заканчиватьсямаркером конца строки (значение 0), под который должен быть выделен один байт:• объявление со статическим выделением памяти на этапе компиляцииchar <Имя строки>[<Размер>] [= <Строковая константа>];• объявление указателя на строкуchar *<Имя указателя>[= < Строковая константа>];Второй вариант предполагает, что либо строка инициализируется при объявлении,либо память под строку выделяют отдельно из области динамической памяти.Примеры:а) char str[6]; // под строку выделено 6 байт, т.е. она может иметь длину до 5б) char *stroka = ″Пример″; // под строку выделено 7 байтв) char *ptrstr;ptrstr=new char[6]; // динамически выделили 6 байтОглавление60…// освободили памятьdelete[] ptrstr;Между способами а и б-в, так же, как и для массивов, существует существенное различие.