Практическая работа №4. Работа с массивами 


Мы поможем в написании ваших работ!



ЗНАЕТЕ ЛИ ВЫ?

Практическая работа №4. Работа с массивами



Цель работы: изучение принципов работы с массивами в С++.

 

Задачи:

1. Изучить теоретический материал

2. Написать программу согласно индивидуальному варианту задания.

3. Ответить на контрольные вопросы.

4. Оформить отчет.

 

Теоретический материал

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

Рассмотрим примеры, различных описаний массивов:

// несколько описаний массивов

int temp[365]; // внешний массив из 365 целых чисел

main() {

float rain[365]; // автоматический массив из 365 чисел типа floaеt

static char code[12]; // статический массив из 12 символов

extern mas[25 ]; // внешний массив

 

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

Внешние и статические массивы можно инициализировать. Автоматические и регистровые массивы инициализировать нельзя. Прежде чем попытаться инициализировать массив, давайте посмотрим, что там находится, если мы в него ничего не записали.

// проверка содержимого массива

main() {

int mas1[2]; // автоматический массив

static int mas2[2]; // статический массив

printf("%d%d\n", mas1[1], mas2[1]);

}

Результат:

525 0

Если ничего не засылать в массив перед началом работы с ним, то внешние и статические массивы инициализируются нулем, а автоматические и регистровые массивы содержат какой-то «мусор», оставшийся в этой части памяти. Инициализировать массивы можно таким образом:

// дни месяца

int days[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};

 

main() {

…………

}

Массив определен вне тела функции, поэтому является внешним. Он инициирован списком, заключенным в скобки. Количество элементов в списке должно соответствовать размеру массива.

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

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

Динамические массивы

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

int n=100;

float *p=new float [n];

В этой строке создается указатель на float, которому присваивается адрес начала непрерывной области динамической памяти, достаточной для размещения 100 элементов вещественного типа. Адрес ее начала записывается в указатель р. Динамические массивы нельзя при создании инициализировать, и они не обнуляются.

Преимущество динамических массивов состоит в том, что размерность может быть переменной, то есть объем памяти, выделяемой под массив, определяется на этапе выполнения программы. Доступ к элементам динамического массива осуществляется точно так же, как и к статическим. Например, к пятому элементу можно обратиться как p[5] или *(p+5). Рассмотрим подробнее второе обращение. В переменной–указателе p хранится адрес начала массива. Для получения адреса пятого элемента к этому адресу прибавляется смещение 5. Операция сложения с константой для указателей учитывает размер адресуемых элементов, то есть на самом деле индекс умножается на длину элемента массива: p+5*sizeof(float). Затем с помощью операции разадресации * выполняется выборка значения из указанной области памяти.

Если динамический массив перестает быть нужным программе, и мы хотим освободить память, это делается с помощью оператора delete[].

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

Двумерный массив представляется в С++ как массив, состоящий из массивов. Для этого при его описании в квадратных скобках указывается вторая размерность.

int a[3][5];  // Целочисленная матрица из 3 сток и 5 столбцов.

Массив хранится по строкам в непрерывной области памяти.

a00 a01 a02 a031 a04 a10 a11 a12 a13 a14 a20 a21 a22 a23 a24

0-я строка 1- я строка 2-я строка

Строки массива ничем не отделены одна от другой, то есть прямоугольной матрицей двумерный массив является только в нашем воображении. В памяти сначала располагаетcя одномерный массив а[0], представляющий собой первую строку массива а, затем массив а[1] и т.д.

При просмотре массива от начала в первую очередь изменяется правый индекс (номер столбца). Для доступа к отдельному элементу массива указываются его индексы, например, a[i][j], где i и j – выражения целочисленного типа (или более экзотическим способом: *(a[i]+j)).

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

int mass2 [ ][2]={{1,1}, {0,2), {1,0} };

int mass2 [3][2]={1, 1, 0, 2, 1, 0};

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

int nstr=5;

int ** m=(int **) new int[nstr][10];

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

int nstr, nstb;

cout << "Введите количество строк и столбцов: ";

cin >> nstr >> nstb;

int **a=new int *[nstr] //1

for (int I=0; I<nstr; I++) //2

a[i]=new int [nstb]; //3

В операторе 1 объявляется переменная типа «указатель на указатель на int» и выделяется память под массив указателей на строки массива. В операторе 2 организуется цикл для выделения памяти под каждую строку массива. В операторе 3 каждому элементу массива указателей на строки присваивается адрес начала участка памяти, выделенного под строку двумерного массива. Каждая строка состоит из nstb элементов типа int.

Освобождение памяти из-под массива с любым количеством измерений выполняется с помощью операции delete[].

10.4 Указатели массивов

Имя массива определяет также его первый элемент, т. е. если mas[ ] — массив, то mas = &mas[0], и обе части равенства определяют адрес первого элемента массива. Оба обозначения являются константами типа указатель, поскольку они не изменяются на протяжении всей программы. Однако их можно присваивать переменной типа указатель и изменять значение переменной, как показано в нижеследующем примере.

// прибавление к указателю

main() {

int dates[4], *pti, index;

float bills[4], *ptf:

pti = dates; // присваивает адрес указателю массива

ptf = bills;

for (index = 0; index < 4; index++)

   printf(" указатели + %d: %10u %10u\n", index, pti + index, ptf + index);

}

Вот результат:

указатели +0: 56014 56026

указатели +1: 56016 56030

указатели +2: 56018 56034

указатели +3: 56020 56038

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

56014 + 1 =56016

56026 + 1=56030

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

Благодаря тому, что компилятор языка Си умеет это делать, мы имеем следующие равенства:

dates + 2 = = &dates[2] /*один и тот же адрес */

*(dates + 2) = = dates[2] /* одно и то же значение "/

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

Нужно различать выражения *(dates + 2) и *dates + 2. Операция (*) имеет более высокий приоритет, чем +, поэтому последнее выражение означает (* dates) + 2.

*(dates + 2) /* значение 3-го элемента массива dates */

dates + 2 /* 2 добавляется к значению 1-го элемента массива */

Задача 1. Количество элементов между минимумом и максимумом.

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

 

Для экономии времени при отладке значения элементов массива задаются путем инициализации.

 

#include <iostream.h>

 int main(){

const int n=10;

int a[n]={1,3,-5,1,-2,1,-1,3,8,4};

int I,imax,imin,count;

for (I=imax=imin=0; I<n; I++){

    if (a[I]>a[imax]) imax=I;

    if (a[I]<a[imin]) imin=I;

}

cout <<"\n\ max=" <<a[imax]<<" min="<< a[imin]; // Отладка

int ibeg=imax<imin? imax: imin;

int iend=imax<imin? imax: imax;

cout << "\n\t ibeg=" << ibeg<< " iend=" <<iend; // Отладка

for (count=0,I=ibeg+1; I<iend; I++)

if (a[I]>0) count++;

cout <<"\n Количество положительных элементов:"<< count << endl;

return 0;

 }

 

После нахождения каждой величины вставлена отладочная печать. Не пренебрегайте этим способом отладки и не жалейте времени.

Основные моменты при работе с одномерными массивами.

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

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

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

· Указатель – это переменная, в которой хранится адрес области памяти.

· Имя массива является указателем на его нулевой элемент.

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

· Освобождение памяти, выделенной посредством new(), выполняется с помощью операции delete().

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

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

· Алгоритмы сортировки массивов различаются по быстродействию, занимаемой памяти и области применения.

 

Задача 2. Среднее арифметическое и количество положительных элементов

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

 

#include <iostream.h>

 #include <iomanip.h>

 void main(){

const int nrow=3,ncol=4;

int a[nrow][ncol];

int i,j;

cout<<"Введи элементы массива:" << endl;

for (i=0; i<nrow; i++)

    for (j=0; j<ncol; j++) cin >> a[i][j];

for (i=0; i<nrow; i++){

    for (j=0; j<ncol; j++) cout << setw(4) << a[i][j] << " ";

    cout << endl;

}

int n_pos_el;

float s=0;

for (i=0; i<nrow; i++) {

    n_pos_el=0;

   for (j=0; j<ncol; j++) {

        s+=a[i][j];

        if (a[i][j]>0) n_pos_el++;

    }

    cout << " Строка: " << i << "кол-во пол. Элементов: " << n_pos_el << endl;

}

s/=nrow*ncol;

cout << " Среднее арифметическое: " << s << endl;

 }

 

После ввода значений элементов предусмотрен их контрольный вывод на экран. Для того, чтобы элементы матрицы располагались один под другим, используется манипулятор setw(), устанавливающий для очередного выводимого значения ширину поля в 4 символа. Для использования манипулятора необходимо подключить заголовочный файл <iomanip.h>. После каждой строки выводится символ перевода строки endl.

 

Основные моменты при работе с двумерными массивами.

· В массивах, определенных с помощью операторов описания, обе размерности должны быть константами или константными выражениями.

· Массив хранится по строкам в непрерывной области памяти.

· Первый индекс – номер строки, второй – номер столбца. Каждый индекс может изменяться от 0 до значения соответствующей размерности, уменьшенной на единицу.

· При описании массива можно в фигурных скобках задать начальные значения его элементов.

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

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

· Освобождение памяти из-под массива с любым количеством измерений выполняется с помощью операции delete()

Индивидуальные варианты заданий

1. В одномерном массиве, состоящем из n вещественных элементов, вычислить:

· сумму отрицательных элементов массива

· произведение элементов массива, расположенных между максимальным и минимальным элементами.

· Упорядочить элементы массива по возрастанию.

2. Дана целочисленная прямоугольная матрица. Определить:

· количество строк, не содержащих ни одного нулевого элемента

· максимальное из чисел, встречающихся в заданной матрице более одного раза.

3. В одномерном массиве, состоящем из n вещественных элементов, вычислить:

· сумму положительных элементов массива

· произведение элементов массива, расположенных между максимальным по модулю и минимальным по модулю элементами

· Упорядочить элементы массива по убыванию.

4. Дана целочисленная прямоугольная матрица.

· Определить количество столбцов, не содержащих ни одного нулевого элемента;

· Характеристикой строки целочисленной матрицы назовем сумму ее положительных четных элементов. Переставляя строки заданной матрицы, расположить их в соответствии с ростом характеристик.

5. В одномерном массиве, состоящем из n целых элементов, вычислить:

· произведение элементов массива с четными номерами

· сумму элементов массива, расположенных между первым и последним нулевыми элементами

· Преобразовать массив таким образом, чтобы сначала располагались все положительные элементы, а потом – все отрицательные (элементы, равные 0, считать положительными).

6. Дана целочисленная прямоугольная матрица. Определить:

· количество столбцов, содержащих хотя бы один нулевой элемент

· номе6р строки, в которой находится самая длинная серия одинаковых элементов

7. В одномерном массиве, состоящем из n вещественных элементов, вычислить:

· сумму элементов массива с нечетными номерами

· сумму элементов массива, расположенных между первым и последним отрицательными элементами

· Преобразовать массив, удалив из него элементы, модуль которых не превышает 1. Освободившиеся в конце массива элементы заполнить нулями.

8. Дана целочисленная прямоугольная матрица. Определить:

· произведение элементов в тех строках, которые не содержат отрицательных элементов

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

9. В одномерном массиве, состоящем из n вещественных элементов, вычислить:

· максимальный элемент массива

· сумму элементов массива, расположенных до последнего положительного элемента

· Преобразовать массив, удалив из него элементы, модуль которых находится в интервале между а и b. Освободившиеся в конце массива элементы заполнить нулями.

10. Дана целочисленная прямоугольная матрица. Определить:

· сумму элементов в тех столбцах, которые не содержат отрицательных элементов

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

11. В одномерном массиве, состоящем из n вещественных элементов, вычислить:

· минимальный элемент массива

· сумму элементов массива, расположенных между первым и последним положительным элементами

· Преобразовать массив таким образом, чтобы сначала располагались все элементы, равные нулю, а потом – все остальные.

12. Дана целочисленная прямоугольная матрица. Определить:

· сумму элементов в тех строках, которые содержат хотя бы один отрицательный элемент

· номера строк и столбцов всех седловых точек матрицы

· Примечание: Матрица А имеет седловую точку Аij, если Аij является минимальным элементом в I-той строке и максимальным в j-том столбце.

13. В одномерном массиве, состоящем из n целых элементов, вычислить:

· номер максимального элемента массива

· произведение элементов массива, расположенных между первым и вторым нулевыми элементами

· Преобразовать массив таким образом, чтобы в первой его половине располагались элементы, стоящие в нечетных позициях, а во второй половине – элементы, стоящие в четных позициях.

14. Для заданной матрицы размером 8 на 8 найти такие k,что k –строка матрицы совпадает с k-м столбцом.

· Найти сумму элементов в тех строках, которые содержат хотя бы один отрицательный элемент.

15. В одномерном массиве, состоящем из n вещественных элементов, вычислить:

· номер минимального элемента массива

· сумму элементов массива, расположенных между первым и вторым отрицательным элементами

· Преобразовать массив таким образом, чтобы сначала располагались все элементы, модуль которых не превышает 1, а потом все остальные.

16. В одномерном массиве, состоящем из n вещественных элементов, вычислить:

· максимальный по модулю элемент массива

· сумму элементов массива, расположенных между первым и вторым положительным элементами

· Преобразовать массив таким образом, чтобы элементы, равные нулю, располагались после всех остальных.

 

 

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

1. Как описываются в программе одномерные массивы?

2. Чем предпочтительней задавать размерность массивов?

3. Что такое указатели, как описываются указатели?

4. В чем разница между динамическими и статическими массивами?

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

6. Как описываются в программе двумерные массивы?

7. Как располагаются в памяти данные многомерного массива? Как осуществляется доступ к элементу массива?

8. Как выделить память под многомерный массив?

9. Как освободить память из-под массива?

10. В чем преимущество динамических массивов перед статическими?

 

Содержание отчета

1. Титульный лист

2. Цели, задачи работы

3. Индивидуальное задание

4. Блок-схема алгоритма (для каждой задачи)

5. Листинг программы(для каждой задачи)

6. Результат выполнения программы – скриншот (для каждой задачи)

7. Ответы на контрольные вопросы

 

 



Поделиться:


Последнее изменение этой страницы: 2021-04-20; просмотров: 277; Нарушение авторского права страницы; Мы поможем в написании вашей работы!

infopedia.su Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав. Обратная связь - 3.145.59.187 (0.088 с.)