Главная | Обратная связь | Поможем написать вашу работу!
МегаЛекции

алгоритмизация и программирование 12 глава




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

Pt += 2;

Pt будет указывать на третий элемент массива b. Истинное же значение указателя Pt изменится на число байтов, занимаемых одним элементом массива, умноженное на 2. Например, если каждый элемент массива b занимает 2 байта, то значение Pt (т.е. адрес в памяти, на который указывает Pt) увеличится на 4.

Аналогичные правила действуют и при вычитании из указателя целого значения.

Переменные указатели можно вычитать один из другого. Например, если Pt указывает на первый элемент массива b, а указатель Pt1 – на третий, то результат выражения Pt1 - Pt будет равен 2 – разности индексов элементов, на которые указывают эти указатели. И так будет, несмотря на то, что адреса, содержащиеся в этих указателях, различаются на 4 (если элемент массива занимает 2 байта).

Арифметика указателей теряет всякий смысл, если она выполняется не над указателями на массив. Сравнение указателей операциями >, <, >=, <= также имеют смысл только для указателей на один и тот же массив. Однако, операции отношения == и!= имеют смысл для любых указателей. При этом указатели равны, если они указывают на один и тот же адрес в памяти.

10.4. Порядок объявления динамических массивов

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

int a=10;

int *ptr=new int [a];

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

Доступ к элементам динамического массива осуществляется точно так же, как к статическим, например, к элементу номер 5 можно обратиться как ptr[5] или *(ptr+5).

Альтернативный способ создания динамического массива – использование функции malloc библиотеки Си:

int a=10;

int *ptr=(int *)malloc(a* sizeof (int));

Операция преобразования типа, записанная перед обращением к функции malloc, требуется потому, что функция возвращает значение указателя типа void *.

Память, зарезервированная под динамический массив с помощью new[], должна освобождаться оператором delete [], а память, выделенная функцией malloc – посредством функции free, например:

delete [] ptr;

free(ptr);

Размерность массива в операции delete не указывается, но квадратные скобки обязательны.

10.5. Передача массивов в качестве параметров функции

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

# include <iostream>

int sum(const int *mas, const int n);

int const n = 10;

int main()

{

int marks[n]= {3, 4, 5, 4, 4};

cout<<”сумма элементов массива: “<<sum(marks,n);

return 0;

}

int sum(const int *mas, const int n) //(величина n должна быть константой)

{

int s =0;

for (int i=0; i<n; i++) s += mas[i];

return s;

}

При передаче многомерных массивов все размеры, если они не известны на этапе компиляции, должны передаваться в качестве параметров. Внутри функции массив интерпретируется как одномерный, а его индекс пересчитывается в программе. В приведенном ниже примере с помощью функции подсчитывается сумма элементов двух двухмерных массивов. Размерность массива b известна на этапе компиляции, под массив a память выделяется динамически.

 

#include <conio.h>

#include <iostream>

# include <stdio.h>

# include <stdlib.h>

using namespace std;

int sum(const int *a, const int nstr, const int nstb);

int main()

{

int b[2][2] = {{2,2},{4,3}};

printf(сумма элементов b: %d\n”,sum(&b[0][0],2,2));

//имя массива передавать в sum нельзя из-за несоответствия типов

int i,j, nstr, nstb,*a;

print f(“введите количество строк и столбцов: \n”);

scanf (“%d%d”,&nstr, &nstb);

// формирование матрицы: выделение памяти

a = (int *)malloc(nstr * nstb * sizeof (int));

// ввод элементов массива

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

for (j=0; j<nstb; j++) scanf(“%d”,&a[i * nstb+j]);

// вывод на экран результата работы функции sum

printf(“сумма элементов a: %d\n”, sum(a,nstr,nstb));

//высвобождение памяти

free(a);

_getch();

return 0;

}

int sum(const int *a, const int nstr, const int nstb)

{

int i,j,s=0;

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

for (j=0;j<nstb; j++) s+=a[i * nstb + j];

return s;

}

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

#include <conio.h>

#include <iostream>

#include <stdio.h>

#include <stdlib.h>

using namespace std;

int sum(int **a, const int nstr, const int nstb);

int main()

{

int nstr, nstb;

cin>>nstr>>nstb;

int **a, i, j;

// формирование матрицы: выделение памяти

a = new int* [nstr]; // nstr строк в массиве

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

a[i] = new int [nstb]; //и nstb столбцов

// ввод элементов массива

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

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

// вывод на экран результата работы функции sum

cout<<sum(a, nstr, nstb);

//высвобождение памяти отводимой под двумерный динамический массив:

for (i = 0; i < nstr; i++) //где nstr – количество строк в массиве

delete [] a[i]; // удалили массив указателей

delete [] a; // удалили указатель на массив указателей

 

_getch();

return 0;

}

int sum(int **a, const int nstr, const int nstb)

{

int i, j, s=0;

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

for(j=0; j<nstb; j++) s+=a[i][j];

return s;

}

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


Лабораторная работа №10
Применение массивов и указателей для решения прикладных задач

ЦЕЛЬ РАБОТЫ: приобретение навыков организации ввода-вывода и обработки массива с использованием указателей и функций.

Выполнение работы: в соответствии с вариантом составить и реализовать программу.

Задание I

Изучить порядок описания и использования указателей:

· набрать и отладить следующую программу:

int main()

{

int a=7, b=2;

int *ptr=NULL;

cout<<"\na="<<a<<", &a="<<&a;

cout<<", b="<<b<<", &b="<<&b;

ptr=&a;

cout<<"\nДействие: ptr=&a. Результат: ptr="<<ptr<<", *ptr="<<*ptr;

ptr=&b;

cout<<"\nДействие: ptr=&b. Результат: ptr="<<ptr<<", *ptr="<<*ptr;

*ptr=137;

cout<<"\nДействие: *ptr=137. Результат: b="<<b;

ptr++;//или ptr+=2;

*ptr=-105;

cout<<"\nДействие: ptr++, *ptr=-105. Результат: ptr="

<<ptr<<", *ptr="<<*ptr<<endl;

return 0;

}

· предъявить результат и уметь объяснить работу программы.

Задание II

Реализовать с использованием указателей и механизма функций в соответствии с номером варианта:

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

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

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

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

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

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

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

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

- преобразовать массив таким образом, чтобы сначала располагались все положительные элементы, а потом – все отрицательные (элементы, равные 0, считать положительными); порядок следования элементов массива в выделенных группах не менять.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

• сумму модулей элементов массива, расположенных после первого элемента, равного нулю.

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

- номер минимального по модулю элемента массива;

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

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

• номер максимального по модулю элемента массива;

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

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

- количество элементов массива, лежащих в диапазоне от А до В;

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

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

• количество элементов массива, равных 0;

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

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

- количество элементов массива, больших С;

- преобразовать массив таким образом, чтобы сначала располагались все отрицательные элементы, а потом – все положительные (элементы, равные 0, считать положительными); порядок следования элементов массива в выделенных группах не менять.

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

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

• преобразовать массив таким образом, чтобы сначала располагались все положительные элементы, а потом – все отрицательные (элементы, равные 0, считать положительными); порядок следования элементов массива в выделенных группах не менять.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

- сумму модулей элементов массива, расположенных после первого элемента, равного нулю.

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

• номер минимального по модулю элемента массива;

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

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

- номер максимального по модулю элемента массива;

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

Задание III

В соответствии с вариантом, используя указатели и пользовательские функции, составить и реализовать программу:

Элементы вещественного одномерного динамического массива х размером n > 20 сгенерированы датчиком псевдослучайных чисел в диапазоне [-10, 10]. Сформировать массив y по формуле и выполнить указанные вычисления. Формулу записать с помощью математических символов в привычном виде. Вывести на экран исходный массив и результаты решения задачи. Все числа округлять до сотых. Анализ результатов выполнить с использованием известных математических пакетов.

1. y [ i ] = exp(x [ i ] - i), i = 0, 1,..., n -1, n = 2 k. Вычислить сумму произведений
Р = х [0] y [2 k -1] + x [1] y [2 k - 2] +... + x [2 k -1] y [0].

2. y [ i ] = x [ i ] / ln(abs(x [ i ] + 1.23)), i = 0, 1,..., n -1. Вычислить сумму отрицательных значений элементов массива x из первых 15 элементов массива у.

3. y [ i ] = exp(x [ i ]) / x [ i ], i = l, 2,..., n. Вычислить сумму всех произведений соответствующих элементов массивов х и у.

4. y [ i ] = ln(x [ i ] + 10.4) / (x [ i ] + l), i = 0, 1,..., n -1. Вычислить сумму положительных значений элементов массива x из последних 12 элементов массива у.

5. y [ i ] = cos(x [ i ]) + sin(x [ i ]) + 2.6, i = 0, 1,..., n -1. Вычислить сумму квадратов элементов массива у, стоящих на нечетных местах.

6. n = 2 k, у [0] = х [1], y [1] = x [1] x [3], y [2] = x [1] x [3] х [5],...,
у [ k -1] = х [1] х [3] х [5]... х [ n -1], у [ k ] = х [0], у [ k + 1] = х [0] х [2], у [ k + 2] = х [0] х [2] х [4],..., у [ n -1] = х [0] x [1]... x [ n - 2].

Вычесть из суммы первых k элементов массива у сумму последних k его элементов.

7. y [ i ] = sqrt(abs(x [ i ])), i = 0, 1,..., n -1. Вычислить количество элементов массива у, больших среднего арифметического элементов массива х.

8. у [0] = 5.2, у [1] = 4.3, у [2] = 0.09, у [3] = -0.5, у [4] = 7.15;
y [ i ] = cos(y [ i - l] + y [ i - 2] + y [ i - 3]) / (y[i - 4] · y [ i - 5]), i = 5, 6,..., n -1.

Вычислить произведение всех отрицательных чисел массива у (в этой задаче массива х нет).

9. n = 2 k, y [0] = x [0] х [1], у [1] = х [2] х [3],..., y [ k -1] = x [ n - 2] x [ n -1]. Вычислить сумму квадратов элементов массива у.

10. y [ i ] = x [ i ]2/3, i = 0, 1,..., n -1. Просуммировать элементы массива у с шагом 3, начиная с первого элемента.

11. n = 2 k, y [ i ] = sqrt(abs(cos(x [ i ]) + 6.7), i = 0, 1,..., n -1. Вычислить сумму произведений S = x [0] y [1] + x [2] у [3] +... + х [ n - 2] у [ n -1].

12. y [ i ] = i sin(x [ i ]), i = 0, 1,..., n -1. Вычислить произведение положительных значений из последних 14 элементов массива х.

13. y [ i ] = sin(exp(x [ i ])), i = 0, 1,..., n -1. Вычислить количество отрицательных элементов массива у с нечетными индексами.

14. y [0] = sqrt(abs(x [0] - x [1])), y [1] = sqrt(abs(x [1] - x [2])),...,
y [ n - 3] = sqrt(abs(x [ n - 3] - x [ n - 2])), y [ n - 2] = sqrt(abs(x [ n - 2] - x [ n -1])).

Просуммировать элементы массива у, имеющие индекс, кратный 3.

15. у [0] = х [0], у [1] = х [0] + х [1],..., у [ n -1] = х [0] + х [1] +... + х [ n -1]. Вычислить сумму кубов отрицательных элементов массива у.

16. n = 2 k, у [0] = х [0] - х [ n -1], у [1] = х [1] - х [ n - 2],..., у [ k -1] = х [ k -1] - х [ k ]. Из каждого элемента массива у вычесть среднее арифметическое элементов массива х.

17. y [ i ] = exp(cos(x [ i ])), i = 0, 1,..., n -1. Вычислить количество элементов массива у, попадающих в интервал [0, 1].

18. y [ i ] = l/8tg(x [ i ]), i = 0, 1,..., n -1. Вычислить количество отрицательных элементов массива х и сумму обратных элементов массива у.

19. у [0] = х [0], y [ n -1] = x [ n -1], y [ i ] = (x [ i - l] + x [ i ] + x [ i + l]) / 3. Вычислить количество положительных элементов массива у с четными индексами и найти их сумму.

20. y [ i ] = exp(x [ i ]) sin(x [ i ]), i = 0, 1,..., n -1. Вычислить сумму элементов массива у, стоящих на четных местах.

21. y [ i ] = tg(2 x [ i ]), i = 0, 1,..., n -1. Вычислить количество элементов массива у, меньших по своим значениям соответствующих элементов массива х.

22. y [ i ] = 3cos( x [ i ]), i = 0, 1,..., n -1. Вычислить количество элементов массива у, не попадающих в промежуток [0, 1].

23. y [ i ] = x [ i ]2 sin(l/ x [ i ]), i = 0, 1,..., n -1. Вычислить сумму положительных значений из первых 14 элементов массива у.

24. y [ i ] = cos(x [ i ]) - abs(x [ i ]), i = 0, 1,..., n -1. Из суммы квадратов элементов массива х вычесть сумму квадратов элементов массива у.

25. у [0] = 4.5, у [1] = -3.6, у [2] = -8.2, у [3] = 6;
y [ i ] = ln(abs(y [ i - 1])) / sin(y [ i - 2] / (y [ i - 4] y[i - 3])), i = 4, 5,..., n -1 (здесь массива х нет, а элементы массива у вычисляются с помощью рекуррентных соотношений). Вычислить сумму отрицательных элементов массива у.

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

1. Что такое указатель?

2. Каков общий вид объявления указателя? Приведите пример.

3. Как описать несколько указателей на данные одного и того же типа?

4. Каковы особенности инициализации указателей?

5. Что означает NULL?

6. Приведите пример использования операции взятия адреса (адресации). Поясните принцип проиллюстрированного действия.

7. Приведите пример использования операции «взятия значения по адресу» (косвенной адресации или разыменования). Поясните принцип проиллюстрированного действия.

8. Особенности использования символа «*».

9. Какова взаимосвязь между именем массива и указателем?

10. Как задать указателю адрес первого элемента массива.

11. Как получить значение i-го элемента массива при использовании указателя?

12. Каково различие между именем массива и соответствующим указателем?

13. Каков порядок объявления динамических массивов с использованием операции new? С использованием функции malloc?

14. Как освободить память, отведенную под динамический массив?

15. Каковы основные правила передачи массивов в качестве параметров функции?

Пример выполнения задания III лабораторной работы

Задание. В соответствии с вариантом, используя указатели и пользовательские функции, составить и реализовать программу:

Элементы вещественного одномерного динамического массива х размером n > 20 сгенерированы датчиком псевдослучайных чисел в диапазоне [-10, 10]. Сформировать массив y по формуле и выполнить указанные вычисления. Формулу записать с помощью математических символов в привычном виде. Вывести на экран исходный массив и результаты решения задачи. Все числа округлять до сотых. Анализ результатов выполнить с использованием известных математических пакетов.

y [ i ] = (15+exp(x [ i ] – i2))/(i 2+1), i = 0, 1,..., n - 1.

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

S = х [0] x [1] … x [ n - 1] + y [0] y [1]... y [ n - 1].

Решение

1. Математическая модель

Элементы вещественного одномерного динамического массива х размером n > 20 сгенерируем датчиком псевдослучайных чисел в диапазоне [-10, 10].

Для нахождения элементов массива y воспользуемся формулой:

.

Вывод массива организуем при помощи вспомагательной функции, использующей форматированный вывод данных с округлением до сотых.

Требуется найти сумму произведений элементов заданных массивов:

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

Аргументы: вещественный одномерный динамический массив x; целочисленное n – количество элементов массива.

Результаты: вещественный одномерный динамический массив y; сумма произведений элементов заданных массивов S (вещественного типа двойной точности).

Промежуточные величины: счетчик i (целого типа), имя массива lit (символьного типа), произведение элементов заданных массивов p (вещественного типа двойной точности).

4. Результат работы программы (алгоритм и листинг программы см. на следующей странице):

 

Введите количество элементов массивов n = 21

 

x:

 

-8.42 9.06 7.00 10.45 4.15 -6.26 8.49 9.48 0.98 4.11

-6.55 -5.25 0.95 1.95 -6.64 -2.19 6.58 6.67 -2.11 -7.30

5.56

 

y:

 

15.00 1590.15 7.02 1.93 0.88 0.58 0.41 0.30 0.23 0.18

0.15 0.12 0.10 0.09 0.08 0.07 0.06 0.05 0.05 0.04

0.04

 

S = 163630350633731.37

5. Анализ результатов с использованием известных математических пакетов выполнить самостоятельно.


 

2. Алгоритм 3. Программа
Функция double p_el(float *a, int np) вычисляет произведение элементов массива. Функция void list_mass(float *a, int nl, char lit) осуществляет форматированный вывод одномерного массива на экран
конец
Вывод массива х: list_mass(х, n, 'х');
i = 0..n-1
Ввод n
начало
Выделение памяти под динамический массив
Выделение памяти под динамический массив х
Генерация вещественных x[i] Î [-10, 10]
Вывод массива у: list_mass(y, n, 'y');
i = 0..n-1
Выделение памяти под динамический массив
Выделение памяти под динамический массив у
у[i] = (15 + exp(x[i]-i*i))/(i*i+1)
S=p_el(x,n)+p_el(y,n)
Вывод S
Высвобождение памяти, отводимой под динамические массивы х и у

  #include <conio.h> #include <iomanip> #include <iostream> #include <stdio.h> #include <time.h> // для time(0) #include <stdlib.h> // для srand() и rand()   using namespace std;   double p_el(float *a, int ns); void list_mass(float *a, int nl, char lit);   int main() { srand(time(0)); cout<<"Введите количество элементов массивов n = "; int n; cin>>n; //формирование маccива х: float *x = new float [n]; for (int i = 0; i < n; i++) x[i] = (float)(rand()%2100-1000)/100; list_mass(x, n, 'x');//вывод массива х //формирование маccива у: float *y = new float [n]; for (int i=0; i<n; i++) y[i] = (15 + exp(x[i]-i*i))/(i*i+1); list_mass(y, n, 'y');//вывод массива у double S = p_el(x,n) + p_el(y,n); cout<< "\n S = "<< fixed << setprecision(2) <<S; //высвобождение памяти, отводимой под динамические массивы: delete [] y; delete [] x; _getch(); return 0; }   double p_el(float *a, int np) { double p = 1; for(int i=0; i<np; i++) p*=a[i]; return p; }   void list_mass(float *a, int nl, char lit) { cout<<"\n"<<lit<<":\n "<<endl; for(int i=0; i<nl; i++) printf ("%5.2f\t",a[i]); cout<<"\n"; }  

 

Поделиться:





Воспользуйтесь поиском по сайту:



©2015 - 2024 megalektsii.ru Все авторские права принадлежат авторам лекционных материалов. Обратная связь с нами...