Главная страница

СИ. Программирование на языке CC Часть Структурное программирование


Скачать 1.65 Mb.
НазваниеПрограммирование на языке CC Часть Структурное программирование
Дата11.02.2022
Размер1.65 Mb.
Формат файлаpdf
Имя файлаAlgLangCpp.pdf
ТипУчебное пособие
#359040
страница6 из 11
1   2   3   4   5   6   7   8   9   10   11
# i n c l u d e

4 5
using namespace
std
;
6 7
i n t
main
() {
8
double
a
,
x
,
y
,
s
,
s0
,
d
;
9
long
n
,
i
;
10
SetConsoleOutputCP
(1251);
11
cout
<< "Введите␣параметр␣a␣=␣";
12
cin
>>
a
;
13
cout
<< "Введите␣число␣сомножителей␣n␣=␣";
14
cin
>>
n
;
15
s
= 1;
16
x
=
a
/(
a
+1);
// первый сомножитель коэффициент для следующих сомножителей o r

(
i
= 0;
i
<
n
;
i
++){
19
cout
<<
i
+1 << "-й␣сомножитель␣=␣" <<
x
<<
endl
;
20
s
*=
x
;
// накапливаем произведение следующий сомножитель "Произведение" <<
s
<<
endl
;

— 76 —
24
s0
=
pow
(
a
,
n
*(
n
+1.0)/2.0) *
pow
(
a
+1, -(
n
-1.0)*(
n
+1.0)-1);
25
cout
<< "Контрольное␣значение␣=␣" <<
s0
<<
endl
;
26
d
=
s
- s0
;
27
i f
(
fabs
(
d
) < 1
e
-4 )
28
cout
<< "Ответ␣правильный,␣ошибка␣=␣" <<
d
<<
endl
;
29
e l s e
30
cout
<< "Ответ␣неверный,␣ошибка␣=␣" <<
d
<<
endl
;
31 Рис. 2.14. Экран программы из листинга
2.12
Суммирование бесконечных рядов.
Найдём сумму бесконечного ряда 1 1!

1 2!
)︂
− 𝑥
2
(︂ 1 2!

1 4!
)︂
+ 𝑥
3
(︂ 1 3!

1 6!
)︂
− . . . ± 𝑥
𝑖
(︂ 1
𝑖!

1
(2𝑖)!
)︂
∓ . . Из курса математического анализа известно, что данный ряд является разложением функции cos

𝑥 − При вычислении суммы бесконечного ряда на компьютере необходимо задать точность 𝜀 — некоторое малое число (0 < 𝜀 ≪ 1). Когда очередное слагаемое станет по модулю меньше 𝜀, то вычисления можно прекратить.
Словесное описание алгоритма суммирования бесконечного ряда) ввести точность 𝜀;
2) ввести значение переменной 𝑥;

— 77 —
3) вычислить значение 𝑢 очередного члена ряда) 𝑠 = 𝑠 + 𝑢;
5) если |𝑢| > 𝜀, перейти к пункту 3;
6) вывести При выполнении го пункта данного алгоритма во многих случаях необходимо вычисление факториалов, степеней аргумента 𝑥 и других произведений многих сомножителей. Для ускорения вычислений выгодно использовать рекуррентные формулы. В нашем случае используется формула
𝑎
𝑖
=
1
𝑖!
=
𝑎
𝑖−1
𝑖
,
где 𝑎
𝑖−1
— значение этого выражения для предыдущего члена ряда.
На рис.
2.15
показана схема алгоритма нахождения суммы бесконечного ряда. В данном алгоритме используются две управляющие структуры следование и цикл с постусловием.
Листинг
2.13
иллюстрирует пример решения задачи, на рис.
2.16
показан результат работы программы.
Листинг 2.13: Суммирование бесконечного ряда i n c l u d e

# i n c l u d e

# i n c l u d e

# i n c l u d e

i n t
main
(){
f l o a t
x
,
eps
;
double
a
,
b
,
c
,
u
,
s
,
f
,
e
;
long
i
;
SetConsoleOutputCP
(1251);
printf
("\nВычисление␣суммы␣бесконечного␣ряда\n");
printf
("Введите␣точность␣eps␣=␣");
scanf
("%g", &
eps
);
do
{
// цикл для разных значений x

— 78 Введите, &
x
);
i
= 1;
a
= 1.0;
b
= 0.5;
c
=
x
;
u
=
c
*(
a
- b
);
s
=
u
;
// сначала сумма равна первому слагаемому
Рис. 2.15. Схема алгоритма суммирования бесконечного ряда точность;
𝑥

значение аргумента счётчик просуммированных членов ряда первый член ряда (𝑢)
— рекуррентная формула для вычисления очередного члена ряда очередной член ряда сумма ряда

— 79 —
do
{
// цикл для слагаемых ряда i
++;
// счётчик слагаемых a
=
a
/
i
;
b
=
b
/ (2*
i
-1) / (2*
i
);
c
= - c
*
x
;
u
=
c
* (
a
- b
);
// очередное слагаемое s
+=
u
;
// накапливаем сумму (
fabs
(
u
) >
eps
) && (
i
< 10000) );
f
=
cos
(
sqrt
(
x
)) - exp
(- x
);
// контрольная функция e
=
s
- f
;
// ошибка printf
("Сумма␣ряда␣при␣x=%g␣равна␣%lg\n",
x
,
s
);
printf
("истинное␣значение␣=␣%lg,␣ошибка␣=␣%lg\n",
f
,
e
);
printf
("просуммировано␣%li␣слагаемых\n",
i
);
printf
("Будем␣продолжать␣(y/n)?␣");
}
while
(
getch
() == ’y’ Рис. 2.16. Результат работы программы из листинга

— 80 —
2.6. Контрольные вопросы. Пояснить смысл следующий понятий, привести примеры а) условный оператор б) цикл с предусловием в) цикл с постусловием г) цикл с параметром д) условная операция. Почему не рекомендуется использовать оператор перехода goto
?
3. Чем различаются операторы ветвления if и. Какая строка будет выведена в результате выполнения следующего фрагмента программы n t

a
= 5,
b
= 12;
i n t
x
=
a
&&
b
;
i f
(
x
)
printf
("true");
e l s e
printf
("false");
5. Какое число будет выведено в результате выполнения следующего фрагмента программы:
а)
i n t
a
= 9,
b
= 2;
i n t
x
=
a
<=
b
? ++
a
: -- б n t

a
= 9,
b
= 2;
i n в n t
x
= 5,
y
= 10;
y
-=
x
--;
i f
(
x
<
y
)
cout
<<
x
;
e l s г n t
x
= 5,
y
= 10;
y
-=
++
x
;
switch
(
x
) {
case
5:
cout
<< ’a’;
case
6:
cout
<< ’b’;
d e f a u l t
:
cout
<< ’c’;
}
6. Что будет выведено в результате выполнения следующего фрагмента программы

— 81 а n t

x
= 5;
while
(
x
< 8) б n t
x
= 5;
do
{
cout
<< ++
x
;
}
while
(
x
< в o r
(
i n t
i
=0,
j
=3;
i
<
j
; где- ж o r
(
i n t
i
=0,
j
=3;
i
<
j
;
j
--) {
cout
<<
i
++;
i f
(
i
<
j
)
continue
;
cout
<< ’.’ <<
j
;
}
7. Запишите уравнение прямой на плоскости. Какой смысл имеют входящие в него параметры. Как аналитически задать множество точек, лежащих ниже (выше) прямой на плоскости. Запишите уравнение окружности с заданными координатами центра и радиусом. Как аналитически задать множество точек, лежащих внутри круга с заданными координатами центра и радиусом Вне его. Сформулируйте правило окончания вычислений при суммировании бесконечных рядов

— 82 —
12. Какой ряд называется знакопостоянным? Знакочередующимся. Можно ли утверждать, что отбросив при суммировании все члены ряда,
начиная с первого, который по модулю меньше 𝜀, мы получим ошибку вычисления суммы ряда 𝐸
6 𝜀?
14. В листинге
2.13
через переменные 𝑎 и 𝑏 обозначены величины 1/𝑖! и
1/(2𝑖)!
соответственно. Что изменится, если в переменных 𝑎 и 𝑏 хранить значения знаменателей 𝑖! и (2𝑖)!, а очередной член ряда вычислять по формуле 𝑑 = 𝑐 · (1/𝑎 − 1/𝑏)?
15. Напишите формулу Тейлора разложения функции вряд вблизи произвольной точки 𝑥 = 𝑎.
16. Можете ли вы с помощью своей программы определить, является ли сходимость ряда равномерной. Попытайтесь сформулировать правило окончания цикла при вычислении бесконечного произведения. Как можно свести задачу вычисления бесконечного произведения к задаче вычисления бесконечной суммы

— 83 —
3. Массивы и указатели Массив — это упорядоченный набор однотипных элементов, доступ к которым осуществляется по их номеру (индексу. Одномерные статические массивы
При описании переменной-массива в квадратных скобках указывается количество элементов. Стандарты C89 и C90 языка C требуют, чтобы количество элементов задавалось в виде константы или константного выражения
(значение которого можно вычислить на этапе компиляции. Пример описания одномерного массива из десяти целых элементов n или i n t
n
= 10;
i n или d e f i n e
N
10
i n Рекомендуется использовать второй вариант.
Элементы массивов нумеруются, начиная с 0; поэтому в приведённых выше примерах элементы будут иметь индексы от 0 до Элементы одномерного массива располагаются в памяти последовательно, друг за другом, в соответствии сих индексами, без пропусков.
Новый стандарт разрешает в качестве размера локального массива
(т. е. объявленного внутри некоторого блока, ограниченного фигурными скобками, например, внутри какой-либо функции, в том числе функции указывать переменную целого типа, значение которой уже известно:
1
Компилятор Microsoft Visual C++ пока не поддерживает стандарт C99. Массивы с переменной длиной (Variable Length Array, VLA) можно использовать с компиляторами GNU
Compiler Collection (GCC) или MinGW, например, в Dev C++.

— 84 —
long
n
;
cout
>> "Введите␣число␣элементов␣=␣";
cin
>>
n
;
double
arr
[
n
];
Разумеется, если значение переменной после этого изменится, то размер массива arr всё равно останется прежним.
В описании массива можно использовать инициализатор = { 2, 6, 3, 1, 4, 2, 1 } Здесь первым семи элементам массива (с индексами от 0 до 6) присвоены начальные значения, остальные три элемента (с индексами от 7 до 9) по умолчанию инициализируются нулями. При использовании инициализатора размер массива в квадратных скобках можно опустить (оставив сами скобки) число элементов массива будет совпадать с числом значений, указанных в фигурных скобках. Также допускается не указывать размер переменной-мас- сива, если она является формальным параметром функции (см. раздел
4.1
).
Для доступа к отдельным элементам массива в квадратных скобках указывают нужный индекс, например = 10;
a
[8] =
a
[0] +
a
[4] При выполнении программы не производится никаких автоматических проверок выхода индекса за допустимые пределы, что может привести к ошибкам при небрежном программировании.
Пример 3.1. Сумма элементов массива. В листинге
3.1
приведён пример программы, которая запрашивает с клавиатуры фактический размер массива, значения его элементов и вычисляет их сумму и среднее значение на рис.
3.1
показан результат работы программы.
Листинг 3.1: Вычисление суммы элементов массива i n c l u d e

2
# i n c l u d e

3
using namespace
std
;

— 85 —
4 5
i n t
main
(){
6
const i n t
m
=10;
// размер массива массив и среднее значение элементов n t

n
;
// число элементов 11
do
{
12
cout
<< "Введите␣число␣элементов␣"
13
"(не␣больше␣" <<
m
<< ")␣=␣";
14
cin
>>
n
;
15
}
while
(
n
>
m
);
// пока не будет введено правильное значение 17
double
sum
= 0.0;
// здесь будем накапливать сумму элементов o r

(
i n t
i
=0;
i
<
n
;
i
++) {
19
cout
<< "␣␣введите␣элемент␣[" <<
i
<< "]␣=␣";
20
cin
>>
a
[
i
];
// вводим й элемент сумма элементов "Сумма␣введённых␣элементов␣=␣" <<
sum
<<
endl
;
24
x
=
sum
/
n
;
// среднее арифметическое "Среднее␣значение␣=␣" Рис. 3.1. Экран программы из листинга

— 86 Пример 3.2. Максимальный и минимальный элементы массива. В
листинге
3.2
приведён пример программы, в которой находятся максимальный и минимальный элементы массива. Сначала переменная max ини­
циализируется наименьшим, а переменная min
— наибольшим возможным числом для типа double
. Константа
DBL_MAX
определена в заголовочном файле. Затем мы перебираем все элементы массива в цикле, и, если очередной элемент больше текущего значения максимума (или меньше текущего значения минимума, то запоминаем новое значение максимума (минимума, а также номер позиции или Листинг 3.2: Максимальный и минимальный элементы массива i n c l u d e

2
# i n c l u d e

3
using namespace
std
;
4 5
i n t
main
(){
6
const i n t
m
=10;
// размер массива массив n t
n
;
// число элементов, "rus");
10
cout
<< "Введите␣число␣элементов␣"
11
"(не␣больше␣" <<
m
<< ")␣=␣";
12
cin
>>
n
;
13
i f
(
n
>
m
){
14
cout
<< "Введённое␣число␣слишком␣велико,\n"
15
"будет␣использовано␣значение␣" <<
m
<<
endl
;
16
n
=
m
;
17
}
18
double
max
= -
DBL_MAX
,
min
=
DBL_MAX
;
19
i n t
imax
= -1,
imin
= -1;
20
f o r
(
i n t
i
=0;
i
<
n
;
i
++) {
21
cout
<< "␣␣введите␣элемент␣[" <<
i
<< "]␣=␣";
22
cin
>>
a
[
i
];
// вводим й элемент

— 87 —
23
i f
(
a
[
i
] >
max
) {
24
max
=
a
[
i
];
imax
=
i
;
25
}
26
i f
(
a
[
i
] <
min
) {
27
min
=
a
[
i
];
imin
=
i
;
28
}
29
}
30
cout
<< "Максимальный␣элемент␣" <<
max
31
<< "␣с␣номером␣" <<
imax
<<
endl
;
32
cout
<< "Минимальный␣элемент␣" <<
min
33
<< "␣с␣номером␣" <<
imin
<<
endl
;
34
system
("pause");
35
return
0;
36
}
3.2. Указатели. Динамические массивы
Для создания различных структур данных произвольного размера (в том числе, массивов) используют специальную динамическую память, которая предоставляется программам операционной системой. Переменные, значения которых хранятся в динамической памяти, называются динамическими. Они не имеют имени, доступ к ним производится с помощью указателей.
Указатели.
Указатель — это переменная, которая хранит адрес некоторой области памяти. При описании указателя задаётся тип значения, на которое он должен указывать, и ставится звёздочка. Например, описание указателя на целое значение:
int
*
p1
;
описание указателя на вещественное число двойной точности:
double
*
p2
;
В одной строке можно описать и обычную переменную, и указатель, например, те. звёздочка относится к имени переменной, а не к названию типа.
Независимо от типа указателя, он занимает в памяти фиксированный размер байта).
Описав переменную-указатель, мы можем присвоить ей адрес другой переменной, используя оператор взятия адреса &. Например Указателю также можно присвоить адрес, хранящийся в другом указателе,
если их типы совместимы:
p3
=
p1
;
Указателю можно присвоить произвольный адрес в памяти, например (Считается, что никакая переменная не может иметь нулевой адрес, поэтому указатель, имеющий значение 0, никуда не указывает или p = Чтобы получить доступ к области памяти, адрес которой хранит указатель, используется операция разыменования (разадресации) — звёздочка перед именем переменной-указателя:
i n t
i
,
j
;
i n t
*
p1
(&
i
);
//
p1 указывает на i
*
p1
= эквивалентно i = 5;
j
= эквивалентно j = Можно описать указатель без определённого типа (если тип значения заранее неизвестен или указатель требуется использовать для работы со значениями разного типа):
void
*
p
;
но тогда каждый раз при разыменовании придётся использовать операцию приведения типа. Например &
i
;
j
= (Пример использования модификатора const при описании указателей

— 89 —
const i n t
k
= 5;
// целая константа i n t
*
p1
;
// указатель на целую константу n t
*
const
p2
= &
i
;
// константный указатель на целую переменную i n t
*
const
p3
= &
k
;
// константный указатель на целую константу
К указателям можно применять арифметические операции сложения, вычитания, инкремента и декремента. Если, например, описать указатель на длинное целое и присвоить ему адрес какой-либо переменной i n t
p
= то после выполнения операции p
+= адрес, хранящийся в указателе, увеличится на 4 · 2 = 8 (т. к. одна переменная типа long int занимает в памяти 4 байта).
Указатели и одномерные массивы.
Имя массива рассматривается компилятором как константный указатель на нулевой элемент массива. Поэтому после описания, например, массива int a[10]
запись
*(a+i)
эквивалентна обращению к i
-му элементу массива, т. е.
a[i]
Пример 3.3. Копирование элементов из одного массива в другой n t
a
[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10},
b
[10];
// Первый способ o r
(
i n t
i
= 0;
i
< 10;
i
++)
b
[
i
] =
a
[
i
];
// Второй способ o r
(
i n t
i
= 0;
i
< 10;
i
++)
*(
b
+
i
) = *(
a
+
i
);
// Третий способ

— 90 —
i n t
*
p1
, *
p2
;
f o r
(
i n t
i
= 0,
p1
=
a
,
p2
=
b
;
i
< 10;
i
++)
*(
p2
++) = Присваивание массивов не допускается. Если мы хотим скопировать элементы одного массива в другой, то должны сами сделать это в цикле.
Ссылки.
Ссылка — это синоним имени, которое указывается при её инициализации. Другими словами, ссылка — это указатель, который не требуется разыменовывать. Например n t
k
;
// целая переменная n t
&
r
=
k
;
// ссылка на переменную k
i n t
i
=
r
+ 5;
// тете ссылка на константу-символ
Обычно ссылки используются в качестве выходного параметра функции
(см. раздел, с.
117
).
Выделение и освобождение динамической памяти.
В приведённых выше примерах переменные-указатели хранили адреса других именованных переменных. Но обычно указатели используются для работы с безымянными данными, которые хранятся в динамической памяти.
Для выделения в динамической памяти области для хранения безымянной переменной используется операция в С) или функция в языке С).
Например, для создания динамической переменной целого типа:
1   2   3   4   5   6   7   8   9   10   11


написать администратору сайта