Добавил:
ivanov666
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз:
Предмет:
Файл:Практикум по языкам программирования. Учебно-методическое пособие
.pdf
11
Задание. Составить алгоритм решения задачи согласно своему варианту и
написать программу на языке С++. В отчете предоставить блок-схемы
функции согласно заданию и основной функции.
Варианты заданий
1. Вводится последовательность целых чисел, 0 – конец
последовательности. Для каждого числа последовательности найти
количество его делителей (функцией оформить определение количества
делителей числа).
2. Вводится последовательность целых чисел, 0 – конец
последовательности. Для каждого числа последовательности найти сумму
его простых делителей (функцией оформить определение суммы простых
делителей числа).
3. Вводится последовательность из N целых чисел. Найти наименьшую
по значению цифру в каждом числе последовательности (функцией
оформить определение наименьшей цифры числа).
4. Вводится последовательность из N целых чисел. Найти наибольшую по
значению четную цифру в каждом числе последовательности
(функцией оформить определение наибольшей четной цифры числа).
5. Вводится последовательность из N целых чисел. Найти в каждом
числе
последовательности сумму четных цифр (функцией оформить
определение
суммы четных цифр числа).
6. Вводится последовательность целых чисел, 0 – конец
последовательности. Найти в каждом числе последовательности
количество четных и нечетных цифр (функциями оформить определение
количества четных и нечетных цифр числа).
7. Вводится последовательность из N целых чисел. Найти среднее
арифметическое цифр каждого числа последовательности
(функцией оформить определение среднего арифметического цифр числа).
8. Вводится последовательность целых чисел, 0 – конец
последовательности. Для каждого числа последовательности проверить,
представляют ли его цифры строго убывающую последовательность,
например, 6543 (результатом функции будет 1 – Да, 0 - НЕТ).
9. Вводится последовательность целых чисел, 0 – конец
последовательности. Для каждого числа последовательности проверить,
представляют ли его цифры строго возрастающую последовательность,
например, 1234 (результатом функции будет 1 – Да, 0 - НЕТ).

12
10. Вводится последовательность из N целых чисел. Найти количество двух-
и количество трехразрядных чисел в последовательности (функцией
оформить определение количества разрядов числа).
11. Вводится последовательность из N целых чисел. Для каждого числа
последовательности вывести новое число, которое получится после
записи цифр числа в обратном порядке (функцией оформить
определение нового числа для заданного).
12. Вводится последовательность из N целых чисел. Для каждого числа
последовательности найти количество цифр 5 (функцией оформить
определение количество цифр 5).
13. Дано натуральное число N. Определить M=N!. Проверить, как
изменилось
количество разрядов в числе M по сравнению с количеством
разрядов числа N (функцией оформить определение количества разрядов
числа)
14. Дано натуральное число N. Уменьшить число в 2 раза (деление
нацело). Проверить, изменилось ли в числе после уменьшения
количество разрядов (функцией оформить определение количества
разрядов числа).
15. Дано натуральное число N, проверить, простое оно или нет. Увеличить
его значение на натуральное число M. Проверить, осталось ли оно
простым
1
(функцией оформить проверку числа: функция возвращает 1,
если число простое, 0 – в противном случае).
16. Вводится последовательность из N целых чисел. Для каждого числа
последовательности вывести новое число, которое состоит только из
четных
цифр исходного числа (функцией оформить определение нового
числа для заданного).
17. Вводится последовательность из N целых чисел. Для каждого числа
последовательности определить минимальную цифру и ее
месторасположение в числе (функция определяет количество цифр в
числе).
18. Вводится последовательность из N целых чисел. Найти максимальное
совершенное число
2
в последовательности, если таких несколько,
вывести их количество (функцией оформить проверку числа:
результатом функции будет 1 – число совершенное, 0 – нет).
19. Вводится последовательность целых чисел, 0 – конец
последовательности. Определить среднее арифметическое простых чисел
последовательности (функцией оформить проверку числа: результатом
функции будет 1 – число простое, 0 – нет).

13
20. Вводится последовательность целых чисел, 0 – конец
последовательности. Найти количество совершенных и простых чисел в
последовательности (функцией оформить проверку числа: результатами
функций будет:1 – число простое, 0 – число непростое; 1 – число
совершенное, 0 – нет).
21.Вводится последовательность целых чисел, 0 – конец
последовательности. Определить минимальное простое число
последовательности (функцией оформить проверку числа: результатом
функции будет 1 – число простое, 0 – нет).
22.Вводится последовательность из N целых чисел. Каждое простое число
последовательности увеличить в два раза, посчитать количество
простых
чисел в исходной последовательности (функцией оформить
проверку числа: результатом функции будет 1 – число простое, 0 – нет).
23.Вводится последовательность целых чисел, 0 – конец
последовательности. Найти, каких чисел в последовательности больше простых или совершенных (функцией оформить проверку числа:
результатами функций будет: 1 – число простое, 0 – число непростое; 1
– число совершенное, 0 – нет).
24.Найти первое нечетное и второе четное избыточное число3, (функцией
оформить проверку числа: результатом функции будет 1, если число
избыточное, 0 – в противном случаем).
25.Сформировать последовательность из первых 10 избыточных чисел,
найти сумму элементов этой последовательности (функцией оформить
проверку числа: результатом функции будет 1, если число избыточное,
0 – в противном случае).
26.Вводится последовательность из N целых чисел. Сформировать
последовательность, каждый элемент которой равен сумме цифр
исходной последовательности. Найти сумму цифр в
сформированной последовательности (функцией оформить определение
суммы цифр числа).
1 Простым называется целое число, которое делится нацело только на само себя и единицу.
2 Совершенное число – это целое число, у которого сумма всех делителей, меньших его самого,
равна этому числу.

14
Содержание отчета
1. Номер и тема лабораторной работы.
2. Текст программы и этапы обработки ее в среде программирования.
3. Результаты работы программы.
4. Сдать отчет преподавателю.
Контрольные вопросы
1. Типы функции, используемые в программе на языке Си.
2. Структура функции, определенной пользователем.
3. Отличие типовой функции от бестиповой функции.
4. Типы параметров функции.
5. Для чего используются подпрограммы?
6. Структура бестиповой функции, определенной пользователем.
7. Как вызывается такая функция?
8. Правила взаимодействия списков фактических и формальных
параметров.

15
Практическая работа № 2
Тема: «Указатели и динамические массивы. Использование указателей в
качестве аргументов функций»
Цель работы: Знакомство с указателями в С++. Изучение одномерных
динамических массивов в языке С++. Знакомство с функциями,
возвращающими несколько значений. Передача указателя в качестве
параметра в функцию.
Указатели и массивы
2.1. Указатели
Указатель – это переменная, содержащая адрес области памяти.
Указатели широко применяются в языке С++. В некоторых случаях без них
просто не обойтись, а в некоторых программы с использованием указателей
становятся короче и эффективнее.
Начнем с того, что поговорим о структуре памяти любого компьютера. Как
известно, память компьютера представляет последовательность 8-битовых
байтов. Каждый байт пронумерован, причем нумерация начинается с нуля.
Номер байта называется адресом. Иногда говорят, что адрес указывает на
определенный байт. Таким образом, указатель является просто адресом байта
памяти.
Язык С++ позволяет определять переменные, которые могут хранить
адреса памяти. Такие переменные и называются указателями. Значение
указателя сообщает о том, где размещен объект, но ничего не говорит о
значении самого объекта.
Присваивая указателю то или иное допустимое значение, можно
обеспечить доступ к данным через этот указатель.
Для описания переменной типа указатель используется символ *.
Формат описания:
Тип *имя;
Указатель – адрес переменной какого-то определенного типа. Этот тип
сообщается компилятору при объявлении указателя.
int *x;
char *y;
Указатель
Объект
Данные или группа
данных

16
Пример следует понимать так: x – это указатель на ячейку, в которой
хранится целое значение, а y – указатель на однобайтовую ячейку,
предназначенную для хранения символа.
Двумя наиболее важными операциями, связанными с указателями,
являются операция обращения по адресу * и определение адреса &.
Операция обращения по адресу предназначена для записи или
считывания значения, размещенного по адресу, содержащемуся в переменнойуказателе.
Например:
int *x; //объявление указателя х
. . .
*x=5; //запись по адресу х значения 5
Операция определения адреса & возвращает адрес памяти своего операнда.
Операндом должна быть переменная.
Например:
int *x; // объявление указателя х
int a=5; //объявление и инициализация переменной а
x=&a; //копирование адреса переменной а в х
Кроме того, над указателями можно выполнять арифметические операции
сложения и вычитания.
Если у – указатель на целое, то унарная операция y++ увеличивает
значение адреса, хранящегося в переменной-указателе на число равное размеру
ячейки целого типа, т.е. на 2 байта для 16-разрядного процессора и на 4 байта –
для 32-разрядного; теперь оно является адресом следующей ячейки целого
типа. Соответственно, оператор y--; означает, что адрес уменьшается
аналогично на 2 или на 4 байта.
Указатели и целые числа можно складывать. Конструкция у + n (у –
указатель, n – целое число) задает адрес n-гo объекта, на который указывает у.
Это справедливо для любых объектов (int, char, float и др.); транслятор
будет масштабировать приращение адреса в соответствии с типом, указанным в
определении объекта.
Любой адрес можно проверить на равенство (==) или неравенство (!=),
больше (>) или меньше (<) с любым другим адресом.
Рассмотрим следующий фрагмент программы:
#include "stdafx.h"
int main()
{
int *x, *w;

17
int y;
*x=18;
y=-15;
w=&y;
. . .
}
Этот текст можно понимать так:
Выделить память под три переменные x, w, y, где x и w – переменные типа
указатель. Оператор *x=18; означает, что в ячейку, адрес которой записан в
x, помещается значение 18. Затем переменной y присваивается значение -15.
После чего в указатель w записывается адрес переменной y. Синтаксически
текст записан правильно. Проблема заключается в том, что указатель x не
инициализирован. Описание int *x; это лишь указание компилятору
резервировать память, необходимую для хранения адреса целой ячейки. Но в
этой памяти может оказаться адрес любой ячейки, в том числе и адрес, где
хранится полезная информация, например, операционная система. Запись в
такую ячейку может привести к сбою в работе компьютера. Поэтому при
работе с указателями их надо правильно инициализировать.
Существует 4 способа правильного задания начального значения для указателя:
1) Описать указатель глобально, т.е. вне любой функции. При этом
указатель будет инициализирован безопасным нулевым адресом. Кроме того
любому указателю можно присвоить безопасный нулевой адрес, например:
int *x;
x=NULL;
Гарантируется, что этот адрес не совпадет ни с одним адресом, уже
использованным в системе.
2) Присвоить указателю адрес переменной. Например: w=&y;
3) Присвоить указателю значение другого указателя, к этому моменту
правильно инициализированного. Например: x=w;
4) Использовать функции выделения динамической памяти
2.2 Динамическое выделение памяти
В языке С++ память можно выделять динамически. Динамическое
распределение памяти используется, прежде всего, тогда, когда заранее
неизвестно, сколько объектов понадобится в программе, и понадобятся ли они
вообще. С помощью динамического распределения памяти можно гибко
управлять временем жизни объектов, например, выделить память не в самом
начале программы (как для глобальных переменных), но, тем не менее,

18
сохранять нужные данные в этой памяти до конца программы. Распределяя
подобным образом память динамически, ваша программа непрерывно изменяет
свои потребности без дополнительного программирования. Если ваша
программа запрашивает память во время выполнения, она указывает требуемое
количество памяти, а используемый оператор языка C++ возвращает указатель
на эту память.
Динамическое распределение памяти во время выполнения является
чрезвычайно полезной возможностью.
Использование функции выделения динамической памяти malloc() или
calloc().
При использовании этих функция необходимо подключать библиотеку
<malloc.h>.
Рассмотрим пример использования функции malloc():
x=(int*)malloc(sizeof(int));
Приведенный пример означает, что функция выделит область памяти, размер
которой определит функция sizeof(). Если вы знаете, что размер ячейки
типа int равен 2 байтам, то можно написать проще: x=(int*)malloc(2);
По окончанию работы программы, память, выделенную функцией malloc()
рекомендуется освободить функцией free(x); Вернемся к приведенному
ранее фрагменту программы:
#include "stdafx.h"
#include <malloc.h>
int main()
{ int *x, *w;
int y;
x=(int*)malloc(sizeof(int));
*x=16;
y=-15;
w=&y;
. . .
}
Теперь никаких конфликтных ситуаций при работе с указателями не возникнет.
В языке С++ существует еще одна пара операторов new и delete для
динамического выделения и освобождения памяти.

19
Использование оператора new
Память для величины какого-либо типа можно выделить,
выполнив операцию new. В качестве операнда выступает название типа, а
результатом является адрес выделенной памяти.
long* lp;
lp = new long; // выделить память под новое целое число
float* cp;
// создать новый объект типа float
cp = new float;
Созданный таким образом объект существует до тех пор, пока память не будет
явно освобождена с помощью операции delete. В качестве
операнда delete должен быть задан адрес, возвращенный операцией new:
delete lp;
delete cp;
2.3. Понятие массива
При использовании простых переменных каждой области памяти для
хранения данных соответствует свое имя. Если с группой величин одинакового
типа требуется выполнять однообразные действия, им дают одно имя, а
различают по порядковому номеру. Это позволяет компактно записывать
множество операций с помощью циклов. Конечная именованная
последовательность однотипных величин называется массивом.
Описание одномерного массива
На языке С++ описание одномерного массива задается следующим
образом:
<тип элементов> <имя массива>[размер];
Компилятор отводит под массив память размером (sizeof(тип)хразмер)
байтов.
Описание массива в программе отличается от описания простой
переменной наличием после имени квадратных скобок, в которых задается
количество элементов массива (размерность):
float а [10]; // описание массива из 10 вещественных чисел
При описании массива можно сразу задать начальные значения его
элементам:

20
int dat[4]={5,8,-2,11};
float kom[]={3.5,6,-1.1};
Имя массива фактически является константой-указателем, ссылающимся
на начальный адрес данных (адрес первого элемента массива). Начальный адрес
массива определяет компилятор в момент описания массива, и такой адрес не
может быть переопределен. Первый элемент массива в языке С++ имеет
индекс ноль.
Например:
int Ar[5];
printf ("адрес Ar=%x\n",Ar);
printf ("адрес Ar=%x\n",&Ar[0]);
В приведенном фрагменте обе функции printf выводят адрес массива
Ar, т.к. выражения Ar и &Ar[0] эквивалентны.
2.4. Динамическое выделение памяти под массив
Если необходимо динамически создать массив, то нужно использовать
немного другую форму
new.
Предположим, что вашей программе необходим
массив для хранения 50 целочисленных значений. Используя оператор
new
, вы
можете заказать эту память, как показано ниже:
int *buffer = new int[50];
Говоря кратко, если оператор
new
успешно выделяет память, он
возвращает указатель на начало области этой памяти. В данном случае,
поскольку программа распределяет память для хранения массива целых чисел,
она присваивает возвращаемый указатель переменной, определенной как
указатель на тип
int
. Если оператор
new
не может выделить запрашиваемый
вами объем памяти, он возвратит
NULL
-указатель, который содержит значение
0. Каждый раз, когда программа динамически распределяет память с
использованием оператора
new
, она должна проверять возвращаемое
оператором new значение, чтобы определить, не равно ли оно
NULL
.
Чтобы
определить, выделил ли оператор
new
память, ваша программа должна
сравнить значение указателя с
NULL
, как показано в примерах ниже
:
Пример 1
.
Следующая программа использует оператор
new
для получения указателя на
100-элементный целочисленный массив:
#include "stdafx.h"
#include <iostream.h>
void main()
Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]
